From 202d72bdae5246b35400e760f93df5273780030b Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 19 Dec 2023 20:50:14 +0100 Subject: [PATCH 001/134] gnb: double byte_buffer_segment size and half number of segments in buffer pool --- include/srsran/adt/detail/byte_buffer_segment_pool.h | 2 +- lib/support/byte_buffer.cpp | 2 +- tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/srsran/adt/detail/byte_buffer_segment_pool.h b/include/srsran/adt/detail/byte_buffer_segment_pool.h index 452e6570f4..fa30a8bb0f 100644 --- a/include/srsran/adt/detail/byte_buffer_segment_pool.h +++ b/include/srsran/adt/detail/byte_buffer_segment_pool.h @@ -23,4 +23,4 @@ using byte_buffer_segment_pool = fixed_size_memory_block_pool Date: Thu, 21 Dec 2023 16:55:49 +0100 Subject: [PATCH 002/134] support: support for trace events that only trigger when the duration is above a certain threshold --- include/srsran/support/event_tracing.h | 19 ++++++++ lib/support/event_tracing.cpp | 47 +++++++++++++++---- tests/unittests/support/event_tracer_test.cpp | 23 ++++++++- 3 files changed, 79 insertions(+), 10 deletions(-) diff --git a/include/srsran/support/event_tracing.h b/include/srsran/support/event_tracing.h index 7294384097..3cfea29330 100644 --- a/include/srsran/support/event_tracing.h +++ b/include/srsran/support/event_tracing.h @@ -46,6 +46,17 @@ struct trace_event { SRSRAN_FORCE_INLINE trace_event(const char* name_, trace_point start_tp_) : name(name_), start_tp(start_tp_) {} }; +struct trace_thres_event { + const char* name; + trace_point start_tp; + trace_duration thres; + + SRSRAN_FORCE_INLINE trace_thres_event(const char* name_, trace_point start_tp_, trace_duration thres_) : + name(name_), start_tp(start_tp_), thres(thres_) + { + } +}; + /// \brief Trace event type with defined name, starting point but no duration. /// \remark The creation of this type should be trivial so that compiler optimizes it out for null tracers. struct instant_trace_event { @@ -68,6 +79,8 @@ class null_event_tracer void operator<<(const trace_event& event) const {} + void operator<<(const trace_thres_event& event) const {} + void operator<<(const instant_trace_event& event) const {} }; @@ -82,6 +95,8 @@ class file_event_tracer void operator<<(const trace_event& event) const; + void operator<<(const trace_thres_event& event) const; + void operator<<(const instant_trace_event& event) const; }; @@ -102,6 +117,8 @@ class logger_event_tracer void operator<<(const trace_event& event) const; + void operator<<(const trace_thres_event& event) const; + void operator<<(const instant_trace_event& event) const; private: @@ -121,6 +138,8 @@ class test_event_tracer void operator<<(const trace_event& event); + void operator<<(const trace_thres_event& event); + void operator<<(const instant_trace_event& event); std::vector pop_last_events() { return std::move(last_events); } diff --git a/lib/support/event_tracing.cpp b/lib/support/event_tracing.cpp index 2755307f39..814b87899b 100644 --- a/lib/support/event_tracing.cpp +++ b/lib/support/event_tracing.cpp @@ -84,11 +84,8 @@ struct trace_event_extended : public trace_event { const char* thread_name; trace_duration duration; - trace_event_extended(const trace_event& event) : - trace_event(event), - cpu(sched_getcpu()), - thread_name(this_thread_name()), - duration(duration_cast(trace_point::clock::now() - event.start_tp)) + trace_event_extended(const trace_event& event, trace_duration duration_) : + trace_event(event), cpu(sched_getcpu()), thread_name(this_thread_name()), duration(duration_) { } }; @@ -207,7 +204,20 @@ void file_event_tracer::operator<<(const trace_event& event) const if (not is_trace_file_open()) { return; } - trace_file_writer->write_trace(trace_event_extended{event}); + const auto dur = std::chrono::duration_cast(now() - event.start_tp); + trace_file_writer->write_trace(trace_event_extended{event, dur}); +} + +template <> +void file_event_tracer::operator<<(const trace_thres_event& event) const +{ + if (not is_trace_file_open()) { + return; + } + const auto dur = std::chrono::duration_cast(now() - event.start_tp); + if (dur >= event.thres) { + trace_file_writer->write_trace(trace_event_extended{trace_event{event.name, event.start_tp}, dur}); + } } template <> @@ -222,7 +232,16 @@ void file_event_tracer::operator<<(const instant_trace_event& event) const template <> void logger_event_tracer::operator<<(const trace_event& event) const { - log_ch("{}", trace_event_extended{event}); + log_ch("{}", trace_event_extended{event, std::chrono::duration_cast(now() - event.start_tp)}); +} + +template <> +void logger_event_tracer::operator<<(const trace_thres_event& event) const +{ + const trace_duration dur = std::chrono::duration_cast(now() - event.start_tp); + if (dur >= event.thres) { + log_ch("{}", trace_event_extended{trace_event{event.name, event.start_tp}, dur}); + } } template <> @@ -233,10 +252,20 @@ void logger_event_tracer::operator<<(const instant_trace_event& event) con void test_event_tracer::operator<<(const trace_event& event) { - last_events.push_back(fmt::format("{}", trace_event_extended{event})); + const auto end_tp = now(); + last_events.push_back(fmt::format( + "{}", trace_event_extended{event, std::chrono::duration_cast(end_tp - event.start_tp)})); +} + +void test_event_tracer::operator<<(const trace_thres_event& event) +{ + const trace_duration dur = std::chrono::duration_cast(now() - event.start_tp); + if (dur >= event.thres) { + last_events.push_back(fmt::format("{}", trace_event_extended{trace_event{event.name, event.start_tp}, dur})); + } } void test_event_tracer::operator<<(const instant_trace_event& event) { last_events.push_back(fmt::format("{}", instant_trace_event_extended{event})); -} +} \ No newline at end of file diff --git a/tests/unittests/support/event_tracer_test.cpp b/tests/unittests/support/event_tracer_test.cpp index d012d9e05b..67b2412bc9 100644 --- a/tests/unittests/support/event_tracer_test.cpp +++ b/tests/unittests/support/event_tracer_test.cpp @@ -33,9 +33,14 @@ TEST(event_tracing_test, event_trace_formatting) trace_point tp = tracer.now(); tracer << trace_event("test_event", tp); + tracer << trace_thres_event("test_event2", tp, trace_duration{1000000000}); + tracer << trace_thres_event("test_event3", tp, trace_duration{0}); - std::string event_out = tracer.pop_last_events()[0]; + std::vector events = tracer.pop_last_events(); + ASSERT_EQ(events.size(), 2); + // First event. + std::string event_out = events[0]; fmt::print("event: {}\n", event_out); ASSERT_EQ(event_out[0], '{'); @@ -43,6 +48,15 @@ TEST(event_tracing_test, event_trace_formatting) ASSERT_TRUE(event_out.find("\"name\": \"test_event\"") != std::string::npos); ASSERT_TRUE(event_out.find("\"ph\": \"X\"") != std::string::npos); ASSERT_TRUE(event_out.find("\"cat\": \"process\"") != std::string::npos); + + // Third event. + event_out = events[1]; + fmt::print("event2: {}\n", event_out); + ASSERT_EQ(event_out[0], '{'); + ASSERT_EQ(event_out.back(), '}'); + ASSERT_TRUE(event_out.find("\"name\": \"test_event3\"") != std::string::npos); + ASSERT_TRUE(event_out.find("\"ph\": \"X\"") != std::string::npos); + ASSERT_TRUE(event_out.find("\"cat\": \"process\"") != std::string::npos); } TEST(event_tracing_test, instant_event_trace_formatting) @@ -75,6 +89,8 @@ TEST(event_tracing_test, file_event_tracer) tracer << instant_trace_event("test_event2", instant_trace_event::cpu_scope::global); tracer << instant_trace_event("test_event3", instant_trace_event::cpu_scope::thread); tracer << instant_trace_event("test_event4", instant_trace_event::cpu_scope::process); + tracer << trace_thres_event("test_event5", tp, trace_duration{1000000000}); + tracer << trace_thres_event("test_event6", tp, trace_duration{0}); close_trace_file(); @@ -101,6 +117,11 @@ TEST(event_tracing_test, file_event_tracer) ASSERT_TRUE(std::getline(fptr, line)); ASSERT_NE(line.find("\"name\": \"test_event4\""), std::string::npos); ASSERT_NE(line.find("\"s\": \"p\""), std::string::npos); + ASSERT_TRUE(std::getline(fptr, line)); + ASSERT_NE(line.find("\"name\": \"test_event6\""), std::string::npos); + ASSERT_NE(line.find("\"ph\": \"X\""), std::string::npos); + ASSERT_TRUE(std::getline(fptr, line)); + ASSERT_EQ(line, "]"); } TEST(event_tracing_test, deactivated_file_event_tracer) From 37325923dd7e124b8c056556f1c92ae3f7058176 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 21 Dec 2023 17:47:14 +0100 Subject: [PATCH 003/134] phy,gnb: add L1 traces and optimize execution Apply clang --- apps/examples/du/phy_factory.cpp | 11 +- apps/examples/phy/upper_phy_ssb_example.cpp | 4 +- apps/gnb/gnb_appconfig.h | 14 +-- apps/gnb/gnb_appconfig_cli11_schema.cpp | 21 +--- apps/gnb/gnb_appconfig_translators.cpp | 5 +- apps/gnb/gnb_appconfig_validators.cpp | 22 +--- apps/gnb/gnb_du_factory.cpp | 8 +- apps/gnb/gnb_worker_manager.cpp | 81 +++++-------- apps/gnb/gnb_worker_manager.h | 1 - apps/gnb/radio_notifier_sample.h | 3 + .../srsran/instrumentation/traces/du_traces.h | 7 ++ .../srsran/instrumentation/traces/ru_traces.h | 23 ++++ .../srsran/phy/adapters/phy_error_adapter.h | 5 + .../srsran/phy/support/support_factories.h | 29 ++++- .../srsran/phy/upper/upper_phy_factories.h | 11 +- .../phy/fapi_to_phy_translator.cpp | 25 +++- lib/instrumentation/CMakeLists.txt | 5 +- lib/instrumentation/traces/du_traces.cpp | 2 + lib/instrumentation/traces/ru_traces.cpp | 13 ++ lib/ofh/transmitter/CMakeLists.txt | 5 +- .../transmitter/ofh_downlink_handler_impl.cpp | 3 +- .../lower/lower_phy_baseband_processor.cpp | 13 ++ .../processors/downlink/pdxch/CMakeLists.txt | 4 +- .../downlink/pdxch/pdxch_processor_impl.cpp | 2 + .../processors/uplink/prach/CMakeLists.txt | 2 +- .../uplink/prach/prach_processor_worker.cpp | 5 + lib/phy/support/CMakeLists.txt | 7 +- .../resource_grid_pool_asynchronous_impl.cpp | 111 ++++++++++++++++++ .../resource_grid_pool_asynchronous_impl.h | 67 +++++++++++ .../resource_grid_pool_generic_impl.cpp | 30 +++++ .../support/resource_grid_pool_generic_impl.h | 42 +++++++ lib/phy/support/resource_grid_pool_impl.cpp | 32 ----- lib/phy/support/resource_grid_pool_impl.h | 34 ------ lib/phy/support/support_factories.cpp | 17 ++- lib/phy/upper/CMakeLists.txt | 16 ++- .../pdsch_processor_concurrent_impl.cpp | 10 ++ .../pusch/pusch_decoder_impl.cpp | 5 + ...ownlink_processor_single_executor_impl.cpp | 58 +++++---- .../downlink_processor_single_executor_impl.h | 8 +- lib/phy/upper/uplink_processor_impl.cpp | 12 ++ lib/phy/upper/uplink_processor_impl.h | 5 + lib/phy/upper/upper_phy_factories.cpp | 47 ++++---- lib/phy/upper/upper_phy_impl.h | 1 + .../phy/support/resource_grid_pool_test.cpp | 2 +- .../phy/upper/downlink_processor_test.cpp | 14 --- 45 files changed, 561 insertions(+), 281 deletions(-) create mode 100644 include/srsran/instrumentation/traces/ru_traces.h create mode 100644 lib/instrumentation/traces/ru_traces.cpp create mode 100644 lib/phy/support/resource_grid_pool_asynchronous_impl.cpp create mode 100644 lib/phy/support/resource_grid_pool_asynchronous_impl.h create mode 100644 lib/phy/support/resource_grid_pool_generic_impl.cpp create mode 100644 lib/phy/support/resource_grid_pool_generic_impl.h delete mode 100644 lib/phy/support/resource_grid_pool_impl.cpp delete mode 100644 lib/phy/support/resource_grid_pool_impl.h diff --git a/apps/examples/du/phy_factory.cpp b/apps/examples/du/phy_factory.cpp index 6e2c0ea4bb..4e9cf9cd00 100644 --- a/apps/examples/du/phy_factory.cpp +++ b/apps/examples/du/phy_factory.cpp @@ -57,9 +57,10 @@ std::unique_ptr srsran::create_upper_phy(const upper_phy_params& upper_config.ldpc_decoder_early_stop = true; unsigned nof_slots_per_subframe = get_nof_slots_per_subframe(params.scs); - upper_config.nof_slots_dl_rg = dl_pipeline_depth * nof_slots_per_subframe; - upper_config.nof_dl_processors = upper_config.nof_slots_dl_rg; - upper_config.nof_slots_ul_rg = ul_pipeline_depth * nof_slots_per_subframe; + upper_config.nof_dl_rg = dl_pipeline_depth * nof_slots_per_subframe; + upper_config.dl_rg_expire_timeout_slots = upper_config.nof_dl_rg - 2; + upper_config.nof_dl_processors = upper_config.nof_dl_rg; + upper_config.nof_ul_rg = ul_pipeline_depth; upper_config.max_ul_thread_concurrency = 4; upper_config.max_pusch_concurrency = 1; upper_config.nof_pusch_decoder_threads = 1; @@ -75,13 +76,13 @@ std::unique_ptr srsran::create_upper_phy(const upper_phy_params& upper_config.dl_bw_rb = bw_rb; upper_config.ul_bw_rb = bw_rb; - upper_config.tx_buffer_config.nof_buffers = upper_config.nof_slots_ul_rg; + upper_config.tx_buffer_config.nof_buffers = upper_config.nof_ul_rg; upper_config.tx_buffer_config.nof_codeblocks = 128; upper_config.tx_buffer_config.max_codeblock_size = ldpc::MAX_CODEBLOCK_SIZE; upper_config.tx_buffer_config.expire_timeout_slots = 100 * nof_slots_per_subframe; upper_config.tx_buffer_config.external_soft_bits = false; - upper_config.rx_buffer_config.max_softbuffers = upper_config.nof_slots_ul_rg; + upper_config.rx_buffer_config.max_softbuffers = upper_config.nof_dl_rg; upper_config.rx_buffer_config.max_nof_codeblocks = 128; upper_config.rx_buffer_config.max_codeblock_size = ldpc::MAX_CODEBLOCK_SIZE; upper_config.rx_buffer_config.expire_timeout_slots = 100 * nof_slots_per_subframe; diff --git a/apps/examples/phy/upper_phy_ssb_example.cpp b/apps/examples/phy/upper_phy_ssb_example.cpp index b1510309a4..10b14baac1 100644 --- a/apps/examples/phy/upper_phy_ssb_example.cpp +++ b/apps/examples/phy/upper_phy_ssb_example.cpp @@ -340,11 +340,11 @@ std::unique_ptr srsran::upper_phy_ssb_example::create(con } // Create DL resource grid pool. - dl_rg_pool = create_resource_grid_pool(nof_sectors, nof_slots, std::move(dl_grids)); + dl_rg_pool = create_generic_resource_grid_pool(std::move(dl_grids)); ASSERT_FACTORY(dl_rg_pool); // Create UL resource grid pool. - ul_rg_pool = create_resource_grid_pool(nof_sectors, nof_slots, std::move(ul_grids)); + ul_rg_pool = create_generic_resource_grid_pool(std::move(ul_grids)); ASSERT_FACTORY(ul_rg_pool); } diff --git a/apps/gnb/gnb_appconfig.h b/apps/gnb/gnb_appconfig.h index f15aa461f4..5c02c6b7dd 100644 --- a/apps/gnb/gnb_appconfig.h +++ b/apps/gnb/gnb_appconfig.h @@ -1057,8 +1057,6 @@ struct upper_phy_threads_appconfig { /// - \c concurrent: for using a processor that processes code blocks in parallel, or /// - \c lite: for using a memory optimized processor. std::string pdsch_processor_type = "auto"; - /// Number of threads for encoding PDSCH concurrently. Only used if \c pdsch_processor_type is set to \c concurrent. - unsigned nof_pdsch_threads = 1; /// \brief Number of threads for concurrent PUSCH decoding. /// /// If the number of PUSCH decoder threads is greater than zero, the PUSCH decoder will enqueue received soft bits and @@ -1095,29 +1093,25 @@ struct expert_threads_appconfig { if (nof_threads < 4) { upper_threads.nof_ul_threads = 1; upper_threads.nof_pusch_decoder_threads = 0; - upper_threads.nof_pdsch_threads = 1; - upper_threads.nof_dl_threads = 1; + upper_threads.nof_dl_threads = 2; lower_threads.execution_profile = lower_phy_thread_profile::single; ofh_threads.is_downlink_parallelized = false; } else if (nof_threads < 8) { upper_threads.nof_ul_threads = 1; upper_threads.nof_pusch_decoder_threads = 1; - upper_threads.nof_pdsch_threads = 2; - upper_threads.nof_dl_threads = 2; + upper_threads.nof_dl_threads = 4; lower_threads.execution_profile = lower_phy_thread_profile::dual; ofh_threads.is_downlink_parallelized = true; } else if (nof_threads < 16) { upper_threads.nof_ul_threads = 1; upper_threads.nof_pusch_decoder_threads = 1; - upper_threads.nof_pdsch_threads = 4; - upper_threads.nof_dl_threads = 2; + upper_threads.nof_dl_threads = 4; lower_threads.execution_profile = lower_phy_thread_profile::quad; ofh_threads.is_downlink_parallelized = true; } else { upper_threads.nof_ul_threads = 2; upper_threads.nof_pusch_decoder_threads = 2; - upper_threads.nof_pdsch_threads = 8; - upper_threads.nof_dl_threads = 4; + upper_threads.nof_dl_threads = 6; lower_threads.execution_profile = lower_phy_thread_profile::quad; ofh_threads.is_downlink_parallelized = true; } diff --git a/apps/gnb/gnb_appconfig_cli11_schema.cpp b/apps/gnb/gnb_appconfig_cli11_schema.cpp index a239127dd0..4133f676bb 100644 --- a/apps/gnb/gnb_appconfig_cli11_schema.cpp +++ b/apps/gnb/gnb_appconfig_cli11_schema.cpp @@ -2083,9 +2083,6 @@ static void configure_cli11_upper_phy_threads_args(CLI::App& app, upper_phy_thre "PDSCH processor type: auto, generic, concurrent and lite.") ->capture_default_str() ->check(pdsch_processor_check); - app.add_option("--nof_pdsch_threads", config.nof_pdsch_threads, "Number of threads to encode PDSCH.") - ->capture_default_str() - ->check(CLI::Number); app.add_option("--nof_pusch_decoder_threads", config.nof_pusch_decoder_threads, "Number of threads to decode PUSCH.") ->capture_default_str() ->check(CLI::Number); @@ -2193,26 +2190,16 @@ static void manage_ntn_optional(CLI::App& app, gnb_appconfig& gnb_cfg) static void manage_expert_execution_threads(CLI::App& app, gnb_appconfig& gnb_cfg) { - // When no downlink threads property is defined, make sure that the value of this variable is smaller than the - // max_proc_delay. - upper_phy_threads_appconfig& upper = gnb_cfg.expert_execution_cfg.threads.upper_threads; - CLI::App* expert_cmd = app.get_subcommand("expert_execution"); - if (expert_cmd->count_all() < 1 || expert_cmd->get_subcommand("threads")->count_all() < 1 || - expert_cmd->get_subcommand("threads")->get_subcommand("upper_phy")->count_all() < 1 || - expert_cmd->get_subcommand("threads")->get_subcommand("upper_phy")->count("--nof_dl_threads") == 0) { - upper.nof_dl_threads = std::min(upper.nof_dl_threads, gnb_cfg.expert_phy_cfg.max_processing_delay_slots); - } - if (!variant_holds_alternative(gnb_cfg.ru_cfg)) { return; } // Ignore the default settings based in the number of CPU cores for ZMQ. if (variant_get(gnb_cfg.ru_cfg).device_driver == "zmq") { - upper.nof_pdsch_threads = 1; - upper.nof_pusch_decoder_threads = 0; - upper.nof_ul_threads = 1; - upper.nof_dl_threads = 1; + upper_phy_threads_appconfig& upper = gnb_cfg.expert_execution_cfg.threads.upper_threads; + upper.nof_pusch_decoder_threads = 0; + upper.nof_ul_threads = 1; + upper.nof_dl_threads = 1; gnb_cfg.expert_execution_cfg.threads.lower_threads.execution_profile = lower_phy_thread_profile::blocking; } } diff --git a/apps/gnb/gnb_appconfig_translators.cpp b/apps/gnb/gnb_appconfig_translators.cpp index 2dba26d835..2fc4e16694 100644 --- a/apps/gnb/gnb_appconfig_translators.cpp +++ b/apps/gnb/gnb_appconfig_translators.cpp @@ -1582,9 +1582,10 @@ std::vector srsran::generate_du_low_config(const gnb_appconfig cfg.nof_rx_ports = cell.nof_antennas_ul; cfg.ldpc_decoder_iterations = config.expert_phy_cfg.pusch_decoder_max_iterations; cfg.ldpc_decoder_early_stop = config.expert_phy_cfg.pusch_decoder_early_stop; - cfg.nof_slots_dl_rg = dl_pipeline_depth; + cfg.nof_dl_rg = dl_pipeline_depth; + cfg.dl_rg_expire_timeout_slots = dl_pipeline_depth - 2; cfg.nof_dl_processors = dl_pipeline_depth; - cfg.nof_slots_ul_rg = ul_pipeline_depth; + cfg.nof_ul_rg = ul_pipeline_depth; cfg.max_ul_thread_concurrency = config.expert_execution_cfg.threads.upper_threads.nof_ul_threads + 1; cfg.max_pusch_concurrency = max_pusch_concurrency; cfg.nof_pusch_decoder_threads = config.expert_execution_cfg.threads.upper_threads.nof_pusch_decoder_threads + diff --git a/apps/gnb/gnb_appconfig_validators.cpp b/apps/gnb/gnb_appconfig_validators.cpp index 5d5e73f951..64b7352925 100644 --- a/apps/gnb/gnb_appconfig_validators.cpp +++ b/apps/gnb/gnb_appconfig_validators.cpp @@ -1113,19 +1113,11 @@ static bool validate_upper_phy_threads_appconfig(const upper_phy_threads_appconf valid = false; } - if ((config.pdsch_processor_type == "concurrent") && !nof_pdsch_threads_range.contains(config.nof_pdsch_threads)) { - fmt::print("For concurrent PDSCH processor. Number of PHY PDSCH threads (i.e., {}) must be in range {}.\n", - config.nof_pdsch_threads, + if ((config.pdsch_processor_type == "concurrent") && !nof_pdsch_threads_range.contains(config.nof_dl_threads)) { + fmt::print("For concurrent PDSCH processor. Number of PHY DL threads (i.e., {}) must be in range {}.\n", + config.nof_dl_threads, nof_pdsch_threads_range); valid = false; - } else if ((config.pdsch_processor_type == "auto") && !nof_ul_dl_threads_range.contains(config.nof_pdsch_threads)) { - fmt::print("For auto PDSCH processor. Number of PHY PDSCH threads (i.e., {}) must be in range {}.\n", - config.nof_pdsch_threads, - nof_ul_dl_threads_range); - valid = false; - } else if ((config.pdsch_processor_type != "auto") && (config.pdsch_processor_type != "concurrent") && - (config.nof_pdsch_threads > 1)) { - fmt::print("Number of PHY PDSCH threads (i.e., {}) is ignored.\n", config.nof_pdsch_threads); } if (!nof_ul_dl_threads_range.contains(config.nof_dl_threads)) { @@ -1134,14 +1126,6 @@ static bool validate_upper_phy_threads_appconfig(const upper_phy_threads_appconf valid = false; } - if (config.nof_dl_threads > max_processing_delay_slots) { - fmt::print("Number of PHY DL threads (i.e., {}) cannot be larger than the maximum processing delay in slots " - "(i.e., {}).\n", - config.nof_dl_threads, - max_processing_delay_slots); - valid = false; - } - return valid; } diff --git a/apps/gnb/gnb_du_factory.cpp b/apps/gnb/gnb_du_factory.cpp index 2f24e489e4..b6b5f011f6 100644 --- a/apps/gnb/gnb_du_factory.cpp +++ b/apps/gnb/gnb_du_factory.cpp @@ -39,14 +39,12 @@ static du_low_configuration create_du_low_config(const gnb_appconfig& const upper_phy_threads_appconfig& upper_phy_threads_cfg = params.expert_execution_cfg.threads.upper_threads; if ((upper_phy_threads_cfg.pdsch_processor_type == "lite") || - ((upper_phy_threads_cfg.pdsch_processor_type == "auto") && (upper_phy_threads_cfg.nof_pdsch_threads == 1))) { + ((upper_phy_threads_cfg.pdsch_processor_type == "auto") && (upper_phy_threads_cfg.nof_dl_threads == 1))) { du_lo_cfg.dl_proc_cfg.pdsch_processor.emplace(); } else if ((upper_phy_threads_cfg.pdsch_processor_type == "concurrent") || - ((upper_phy_threads_cfg.pdsch_processor_type == "auto") && - (upper_phy_threads_cfg.nof_pdsch_threads > 1))) { + ((upper_phy_threads_cfg.pdsch_processor_type == "auto") && (upper_phy_threads_cfg.nof_dl_threads > 1))) { pdsch_processor_concurrent_configuration pdsch_proc_config; - pdsch_proc_config.nof_pdsch_codeblock_threads = params.expert_execution_cfg.threads.upper_threads.nof_dl_threads + - params.expert_execution_cfg.threads.upper_threads.nof_pdsch_threads; + pdsch_proc_config.nof_pdsch_codeblock_threads = params.expert_execution_cfg.threads.upper_threads.nof_dl_threads; pdsch_proc_config.max_nof_simultaneous_pdsch = (MAX_UE_PDUS_PER_SLOT + 1) * params.expert_phy_cfg.max_processing_delay_slots; pdsch_proc_config.pdsch_codeblock_task_executor = pdsch_codeblock_executor; diff --git a/apps/gnb/gnb_worker_manager.cpp b/apps/gnb/gnb_worker_manager.cpp index 5d818d356c..6efc621b3c 100644 --- a/apps/gnb/gnb_worker_manager.cpp +++ b/apps/gnb/gnb_worker_manager.cpp @@ -241,18 +241,10 @@ void worker_manager::create_du_cu_executors(const gnb_appconfig& appcfg) *exec_map.at("ctrl_exec")); } - // Select the PDSCH concurrent thread only if the PDSCH processor type is set to concurrent or auto. - unsigned nof_pdsch_workers = 1; const upper_phy_threads_appconfig& upper_phy_threads_cfg = appcfg.expert_execution_cfg.threads.upper_threads; - if ((upper_phy_threads_cfg.pdsch_processor_type == "concurrent") || - (upper_phy_threads_cfg.pdsch_processor_type == "auto")) { - nof_pdsch_workers = upper_phy_threads_cfg.nof_pdsch_threads; - } - create_du_low_executors(is_blocking_mode_active, upper_phy_threads_cfg.nof_ul_threads, upper_phy_threads_cfg.nof_dl_threads, - nof_pdsch_workers, upper_phy_threads_cfg.nof_pusch_decoder_threads, cells_cfg, appcfg.expert_phy_cfg.max_processing_delay_slots); @@ -261,16 +253,12 @@ void worker_manager::create_du_cu_executors(const gnb_appconfig& appcfg) void worker_manager::create_du_low_executors(bool is_blocking_mode_active, unsigned nof_ul_workers, unsigned nof_dl_workers, - unsigned nof_pdsch_workers, unsigned nof_pusch_decoder_workers, span cells_cfg, unsigned pipeline_depth) { using namespace execution_config_helper; - du_low_dl_executors.resize(cells_cfg.size()); - upper_pdsch_exec.resize(cells_cfg.size()); - if (is_blocking_mode_active) { // Create a single worker, shared by the whole PHY. create_prio_worker("phy_worker", @@ -283,18 +271,26 @@ void worker_manager::create_du_low_executors(bool is_block upper_pusch_exec.push_back(exec_mng.executors().at("phy_exec")); upper_pucch_exec.push_back(exec_mng.executors().at("phy_exec")); upper_prach_exec.push_back(exec_mng.executors().at("phy_exec")); + upper_pdsch_exec.push_back(exec_mng.executors().at("phy_exec")); du_low_dl_executors[cell_id].emplace_back(exec_mng.executors().at("phy_exec")); } } else { // RF case. for (unsigned cell_id = 0, cell_end = cells_cfg.size(); cell_id != cell_end; ++cell_id) { - const std::string cell_id_str = std::to_string(cell_id); - const std::string name_ul = "up_phy_ul#" + cell_id_str; - const auto prio = os_thread_realtime_priority::max() - 15; - std::vector cpu_masks; + const std::string cell_id_str = std::to_string(cell_id); + const std::string name_ul = "up_phy_ul#" + cell_id_str; + const std::string name_dl = "up_phy_dl#" + cell_id_str; + const auto prio = os_thread_realtime_priority::max() - 15; + + std::vector ul_cpu_masks; for (unsigned w = 0; w != nof_ul_workers; ++w) { - cpu_masks.push_back(affinity_mng.calcute_affinity_mask(gnb_sched_affinity_mask_types::l1_ul)); + ul_cpu_masks.push_back(affinity_mng.calcute_affinity_mask(gnb_sched_affinity_mask_types::l1_ul)); + } + + std::vector dl_cpu_masks; + for (unsigned w = 0; w != nof_dl_workers; ++w) { + dl_cpu_masks.push_back(affinity_mng.calcute_affinity_mask(gnb_sched_affinity_mask_types::l1_dl)); } // Instantiate PHY UL workers. @@ -303,7 +299,7 @@ void worker_manager::create_du_low_executors(bool is_block task_worker_queue_size, {{"upper_pusch_exec#" + cell_id_str}, {"upper_pucch_exec#" + cell_id_str}}, prio, - cpu_masks); + ul_cpu_masks); upper_pusch_exec.push_back(exec_mng.executors().at("upper_pusch_exec#" + cell_id_str)); upper_pucch_exec.push_back(exec_mng.executors().at("upper_pucch_exec#" + cell_id_str)); @@ -317,19 +313,21 @@ void worker_manager::create_du_low_executors(bool is_block os_thread_realtime_priority::max() - 2); upper_prach_exec.push_back(exec_mng.executors().at("prach_exec#" + cell_id_str)); + const std::string exec_name = "du_low_dl_exec#" + cell_id_str; + // Instantiate dedicated PHY DL workers. - for (unsigned i_dl_worker = 0; i_dl_worker != nof_dl_workers; ++i_dl_worker) { - // Create upper PHY DL executors. - const std::string suffix = std::to_string(cell_id) + "#" + std::to_string(i_dl_worker); - const std::string worker_name = "up_phy_dl#" + suffix; - const std::string exec_name = "du_low_dl_exec#" + suffix; - create_prio_worker(worker_name, - task_worker_queue_size, - {{exec_name}}, - affinity_mng.calcute_affinity_mask(gnb_sched_affinity_mask_types::l1_dl), - os_thread_realtime_priority::max() - 10); - du_low_dl_executors[cell_id].emplace_back(exec_mng.executors().at("du_low_dl_exec#" + suffix)); + create_worker_pool(name_dl, + nof_dl_workers, + task_worker_queue_size, + {{exec_name}}, + os_thread_realtime_priority::max() - 10, + dl_cpu_masks); + + du_low_dl_executors.emplace_back(); + for (unsigned w = 0; w != nof_dl_workers; ++w) { + du_low_dl_executors.back().emplace_back(exec_mng.executors().at(exec_name)); } + upper_pdsch_exec.push_back(exec_mng.executors().at(exec_name)); } } @@ -355,31 +353,6 @@ void worker_manager::create_du_low_executors(bool is_block upper_pusch_decoder_exec.push_back(nullptr); } } - - for (unsigned cell_id = 0, cell_end = cells_cfg.size(); cell_id != cell_end; ++cell_id) { - if (nof_pdsch_workers > 1) { - const std::string name_pdsch = "pdsch#" + std::to_string(cell_id); - unsigned max_nof_pdsch_cb_slot = - ((pdsch_constants::MAX_NRE_PER_RB * MAX_RB * get_bits_per_symbol(modulation_scheme::QAM256) * - cells_cfg[cell_id].cell.nof_antennas_dl) / - ldpc::MAX_MESSAGE_SIZE) * - pipeline_depth; - - const auto prio = os_thread_realtime_priority::max() - 10; - std::vector cpu_masks; - for (unsigned w = 0; w != nof_pdsch_workers; ++w) { - cpu_masks.push_back(affinity_mng.calcute_affinity_mask(gnb_sched_affinity_mask_types::l1_dl)); - } - - create_worker_pool(name_pdsch, - nof_pdsch_workers, - max_nof_pdsch_cb_slot, - {{"upper_pdsch_exec#" + std::to_string(cell_id)}}, - prio, - cpu_masks); - upper_pdsch_exec[cell_id] = exec_mng.executors().at("upper_pdsch_exec#" + std::to_string(cell_id)); - } - } } void worker_manager::create_ofh_executors(span cells, bool is_downlink_parallelized) diff --git a/apps/gnb/gnb_worker_manager.h b/apps/gnb/gnb_worker_manager.h index 15ed9e96d7..e5cc496b01 100644 --- a/apps/gnb/gnb_worker_manager.h +++ b/apps/gnb/gnb_worker_manager.h @@ -112,7 +112,6 @@ struct worker_manager { void create_du_low_executors(bool is_blocking_mode_active, unsigned nof_ul_workers, unsigned nof_dl_workers, - unsigned nof_pdsch_workers, unsigned nof_pusch_decoder_workers, span cells_cfg, unsigned pipeline_depth); diff --git a/apps/gnb/radio_notifier_sample.h b/apps/gnb/radio_notifier_sample.h index 3757954bd0..a7b8f5658a 100644 --- a/apps/gnb/radio_notifier_sample.h +++ b/apps/gnb/radio_notifier_sample.h @@ -10,6 +10,7 @@ #pragma once +#include "srsran/instrumentation/traces/ru_traces.h" #include "srsran/radio/radio_notification_handler.h" #include "fmt/format.h" @@ -26,6 +27,8 @@ class radio_notification_handler_logger : public radio_notification_handler void on_radio_rt_event(const event_description& description) override { + ru_tracer << instant_trace_event(description.type.to_string(), instant_trace_event::cpu_scope::global); + // Forward event. if (handler) { handler->on_radio_rt_event(description); diff --git a/include/srsran/instrumentation/traces/du_traces.h b/include/srsran/instrumentation/traces/du_traces.h index 2ffa7f27e8..0960b30b0e 100644 --- a/include/srsran/instrumentation/traces/du_traces.h +++ b/include/srsran/instrumentation/traces/du_traces.h @@ -14,8 +14,15 @@ namespace srsran { +/// Set to true for enabling layer 1 trace. +constexpr bool L1_TRACE_ENABLED = false; + +/// Set to true for enabling layer 2 trace. constexpr bool L2_TRACE_ENABLED = false; +/// 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; diff --git a/include/srsran/instrumentation/traces/ru_traces.h b/include/srsran/instrumentation/traces/ru_traces.h new file mode 100644 index 0000000000..dc6c8db43c --- /dev/null +++ b/include/srsran/instrumentation/traces/ru_traces.h @@ -0,0 +1,23 @@ +/* + * + * 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/support/event_tracing.h" + +namespace srsran { + +/// Set to true for enabling radio unit trace. +constexpr bool RU_TRACE_ENABLED = false; + +/// RU event tracing. This tracer is used to analyze latencies in the RU processing. +extern file_event_tracer ru_tracer; + +} // namespace srsran \ No newline at end of file diff --git a/include/srsran/phy/adapters/phy_error_adapter.h b/include/srsran/phy/adapters/phy_error_adapter.h index eef42e875c..222a959835 100644 --- a/include/srsran/phy/adapters/phy_error_adapter.h +++ b/include/srsran/phy/adapters/phy_error_adapter.h @@ -10,6 +10,7 @@ #pragma once +#include "srsran/instrumentation/traces/du_traces.h" #include "srsran/phy/lower/lower_phy_error_notifier.h" #include "srsran/phy/support/resource_grid_context.h" @@ -36,6 +37,7 @@ class phy_error_adapter : public lower_phy_error_notifier "Real-time failure in low-phy: Downlink data late for sector {} and slot {}.", context.sector, context.slot); + l1_tracer << instant_trace_event{"on_late_resource_grid", instant_trace_event::cpu_scope::global}; } // See interface for documentation. @@ -47,6 +49,7 @@ class phy_error_adapter : public lower_phy_error_notifier context.sector, context.slot, context.start_symbol); + l1_tracer << instant_trace_event{"on_prach_request_late", instant_trace_event::cpu_scope::global}; } // See interface for documentation. @@ -58,6 +61,7 @@ class phy_error_adapter : public lower_phy_error_notifier context.sector, context.slot, context.start_symbol); + l1_tracer << instant_trace_event{"on_prach_request_overflow", instant_trace_event::cpu_scope::global}; } // See interface for documentation. @@ -68,6 +72,7 @@ class phy_error_adapter : public lower_phy_error_notifier "Real-time failure in low-phy: PUxCH request late for sector {}, slot {}.", context.sector, context.slot); + l1_tracer << instant_trace_event{"on_puxch_request_late", instant_trace_event::cpu_scope::global}; } }; diff --git a/include/srsran/phy/support/support_factories.h b/include/srsran/phy/support/support_factories.h index 0893e890ff..fe72da1ac2 100644 --- a/include/srsran/phy/support/support_factories.h +++ b/include/srsran/phy/support/support_factories.h @@ -15,6 +15,7 @@ #include "srsran/phy/support/prach_buffer.h" #include "srsran/phy/support/prach_buffer_pool.h" #include "srsran/phy/support/resource_grid_pool.h" +#include "srsran/support/executors/task_executor.h" #include #include @@ -43,13 +44,31 @@ std::unique_ptr create_resource_grid_mapper(unsigned nof_ports, unsigned nof_subc, resource_grid_writer& writer); /// \brief Creates a generic resource grid pool. -/// \param[in] nof_sectors Number of radio sectors. -/// \param[in] nof_slots umber of slots to be buffered, per sector. +/// +/// It selects a different resource grid every time a resource grid is requested. The resource grid is repeated every +/// \c grids.size() requests. +/// /// \param[in] grids Resource grids, ownerships are transferred to the pool. /// \return A generic resource grid pool. -std::unique_ptr create_resource_grid_pool(unsigned nof_sectors, - unsigned nof_slots, - std::vector>&& grids); +std::unique_ptr +create_generic_resource_grid_pool(std::vector> grids); + +/// \brief Creates an asynchronous resource grid pool. +/// +/// It selects a different resource grid every time a resource grid is requested. The resource grid expires +/// \c expire_timeout_slots after it is requested. When a resource grid expires, it is asynchronously set to zero. +/// +/// The resource grid repetition is not deterministic but it is guaranteed that it is repeated after +/// \c expire_timeout_slots. +/// +/// \param[in] expire_timeout_slots Number of slots after which resource grids are expired. +/// \param[in] async_executor Asynchronous task executor for setting the grid to zero. +/// \param[in] grids Resource grids, ownerships are transferred to the pool. +/// \return An asynchronous resource grid pool. +std::unique_ptr +create_asynchronous_resource_grid_pool(unsigned expire_timeout_slots, + task_executor& async_executor, + std::vector> grids); /// \brief Creates a long PRACH sequence buffer. /// diff --git a/include/srsran/phy/upper/upper_phy_factories.h b/include/srsran/phy/upper/upper_phy_factories.h index db167da72a..f09581e237 100644 --- a/include/srsran/phy/upper/upper_phy_factories.h +++ b/include/srsran/phy/upper/upper_phy_factories.h @@ -256,10 +256,13 @@ struct upper_phy_config { unsigned nof_tx_ports; /// Number of receive antenna ports. unsigned nof_rx_ports; - /// Number of slots the downlink resource grid will support. - unsigned nof_slots_dl_rg; - /// Number of slots the uplink resource grid will support. - unsigned nof_slots_ul_rg; + /// Number of downlink resource grids. Downlink resource grids minimum reuse time is \c dl_rg_expire_timeout_slots + /// slots. + unsigned nof_dl_rg; + /// Downlink resource grid timeout expiration in number of slots. + unsigned dl_rg_expire_timeout_slots; + /// Number of uplink resource grids. They are reused after \c nof_ul_rg slots. + unsigned nof_ul_rg; /// Number of PRACH buffer. unsigned nof_prach_buffer; /// Maximum number of time-domain occasions. diff --git a/lib/fapi_adaptor/phy/fapi_to_phy_translator.cpp b/lib/fapi_adaptor/phy/fapi_to_phy_translator.cpp index 646d235b14..707c9b6474 100644 --- a/lib/fapi_adaptor/phy/fapi_to_phy_translator.cpp +++ b/lib/fapi_adaptor/phy/fapi_to_phy_translator.cpp @@ -280,8 +280,9 @@ void fapi_to_phy_translator::dl_tti_request(const fapi::dl_tti_request_message& { // :TODO: check the current slot matches the DL_TTI.request slot. Do this in a different class. // :TODO: check the messages order. Do this in a different class. - slot_point slot(scs, msg.sfn, msg.slot); - slot_point current_slot = get_current_slot(); + slot_point slot(scs, msg.sfn, msg.slot); + slot_point current_slot = get_current_slot(); + trace_point tp = l1_tracer.now(); if (!pdsch_repository.empty()) { logger.warning( @@ -340,6 +341,7 @@ void fapi_to_phy_translator::dl_tti_request(const fapi::dl_tti_request_message& slot); slot_controller_mngr.release_controller(slot); } + l1_tracer << trace_event("dl_tti_request", tp); } /// Returns true if the given PUCCH PDU is valid, otherwise false. @@ -442,8 +444,9 @@ static expected translate_ul_tti_pdus_to_phy_pdus(const fapi::ul_tt void fapi_to_phy_translator::ul_tti_request(const fapi::ul_tti_request_message& msg) { // :TODO: check the messages order. Do this in a different class. - slot_point slot(scs, msg.sfn, msg.slot); - slot_point current_slot = get_current_slot(); + slot_point slot(scs, msg.sfn, msg.slot); + slot_point current_slot = get_current_slot(); + trace_point tp = l1_tracer.now(); // Clear the repository for the message slot. ul_pdu_repository.clear_slot(slot); @@ -500,11 +503,13 @@ void fapi_to_phy_translator::ul_tti_request(const fapi::ul_tti_request_message& resource_grid& ul_rg = ul_rg_pool.get_resource_grid(pool_context); // Request to capture uplink slot. ul_request_processor.process_uplink_slot_request(rg_context, ul_rg); + l1_tracer << trace_event("ul_tti_request", tp); } void fapi_to_phy_translator::ul_dci_request(const fapi::ul_dci_request_message& msg) { - slot_point current_slot = get_current_slot(); + slot_point current_slot = get_current_slot(); + trace_point tp = l1_tracer.now(); // Ignore messages that do not correspond to the current slot. if (!is_message_in_time(msg)) { @@ -547,11 +552,13 @@ void fapi_to_phy_translator::ul_dci_request(const fapi::ul_dci_request_message& slot); slot_controller_mngr.release_controller(slot); } + l1_tracer << trace_event("ul_dci_request", tp); } void fapi_to_phy_translator::tx_data_request(const fapi::tx_data_request_message& msg) { - slot_point current_slot = get_current_slot(); + slot_point current_slot = get_current_slot(); + trace_point tp = l1_tracer.now(); // Ignore messages that do not correspond to the current slot. if (!is_message_in_time(msg)) { @@ -636,10 +643,14 @@ void fapi_to_phy_translator::tx_data_request(const fapi::tx_data_request_message // All the PDSCH PDUs have been processed. Clear the repository. pdsch_repository.clear(); + + l1_tracer << trace_event("tx_data_request", tp); } void fapi_to_phy_translator::handle_new_slot(slot_point slot) { + trace_point tp = l1_tracer.now(); + // Update the atomic variable that holds the slot point. current_slot_count_val.store(slot.system_slot(), std::memory_order_release); @@ -653,6 +664,8 @@ void fapi_to_phy_translator::handle_new_slot(slot_point slot) // Update the logger context. logger.set_context(slot.sfn(), slot.slot_index()); + + l1_tracer << trace_event("handle_new_slot", tp); } template diff --git a/lib/instrumentation/CMakeLists.txt b/lib/instrumentation/CMakeLists.txt index f4be25c928..87711c3ea7 100644 --- a/lib/instrumentation/CMakeLists.txt +++ b/lib/instrumentation/CMakeLists.txt @@ -6,5 +6,8 @@ # the distribution. # -add_library(srsran_instrumentation traces/du_traces.cpp traces/up_traces.cpp) +add_library(srsran_instrumentation + traces/du_traces.cpp + traces/ru_traces.cpp + traces/up_traces.cpp) target_link_libraries(srsran_instrumentation srsran_support) diff --git a/lib/instrumentation/traces/du_traces.cpp b/lib/instrumentation/traces/du_traces.cpp index d1b1c7cc8c..da27b2de1f 100644 --- a/lib/instrumentation/traces/du_traces.cpp +++ b/lib/instrumentation/traces/du_traces.cpp @@ -10,4 +10,6 @@ #include "srsran/instrumentation/traces/du_traces.h" +srsran::file_event_tracer srsran::l1_tracer; + srsran::file_event_tracer srsran::l2_tracer; diff --git a/lib/instrumentation/traces/ru_traces.cpp b/lib/instrumentation/traces/ru_traces.cpp new file mode 100644 index 0000000000..e112c7d8bc --- /dev/null +++ b/lib/instrumentation/traces/ru_traces.cpp @@ -0,0 +1,13 @@ +/* + * + * 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 "srsran/instrumentation/traces/ru_traces.h" + +srsran::file_event_tracer srsran::ru_tracer; diff --git a/lib/ofh/transmitter/CMakeLists.txt b/lib/ofh/transmitter/CMakeLists.txt index 518c6ace49..a2c7128a77 100644 --- a/lib/ofh/transmitter/CMakeLists.txt +++ b/lib/ofh/transmitter/CMakeLists.txt @@ -20,7 +20,10 @@ set(SOURCES ofh_transmitter_impl.cpp) add_library(srsran_ofh_transmitter STATIC ${SOURCES}) -target_link_libraries(srsran_ofh_transmitter srsran_ran srslog) +target_link_libraries(srsran_ofh_transmitter + srsran_ran + srsran_instrumentation + srslog) if (DPDK_FOUND) add_definitions(-DDPDK_FOUND) diff --git a/lib/ofh/transmitter/ofh_downlink_handler_impl.cpp b/lib/ofh/transmitter/ofh_downlink_handler_impl.cpp index 38f868cd74..38dd8ad8e6 100644 --- a/lib/ofh/transmitter/ofh_downlink_handler_impl.cpp +++ b/lib/ofh/transmitter/ofh_downlink_handler_impl.cpp @@ -10,6 +10,7 @@ #include "ofh_downlink_handler_impl.h" #include "helpers.h" +#include "srsran/instrumentation/traces/du_traces.h" #include "srsran/phy/support/resource_grid_context.h" #include "srsran/phy/support/resource_grid_reader.h" @@ -52,7 +53,7 @@ void downlink_handler_impl::handle_dl_data(const resource_grid_context& context, "Dropped late downlink resource grid in slot '{}' and sector#{}. No OFH data will be transmitted for this slot", context.slot, context.sector); - + l1_tracer << instant_trace_event{"handle_dl_data_late", instant_trace_event::cpu_scope::thread}; return; } diff --git a/lib/phy/lower/lower_phy_baseband_processor.cpp b/lib/phy/lower/lower_phy_baseband_processor.cpp index fd714892e7..8b5f26a3e6 100644 --- a/lib/phy/lower/lower_phy_baseband_processor.cpp +++ b/lib/phy/lower/lower_phy_baseband_processor.cpp @@ -10,6 +10,7 @@ #include "lower_phy_baseband_processor.h" #include "srsran/adt/interval.h" +#include "srsran/instrumentation/traces/ru_traces.h" using namespace srsran; @@ -116,18 +117,24 @@ void lower_phy_baseband_processor::dl_process(baseband_gateway_timestamp timesta last_tx_time.emplace(std::chrono::high_resolution_clock::now()); // Process downlink buffer. + trace_point tp = ru_tracer.now(); baseband_gateway_transmitter_metadata baseband_md = downlink_processor.process(dl_buffer->get_writer(), timestamp); + ru_tracer << trace_event("downlink_baseband", tp); // Set transmission timestamp. baseband_md.ts = timestamp + tx_time_offset; // Enqueue transmission. report_fatal_error_if_not(tx_executor.execute([this, tx_buffer = std::move(dl_buffer), baseband_md]() mutable { + trace_point tx_tp = ru_tracer.now(); + // Transmit buffer. transmitter.transmit(tx_buffer->get_reader(), baseband_md); // Return transmit buffer to the queue. tx_buffers.push_blocking(std::move(tx_buffer)); + + ru_tracer << trace_event("transmit_baseband", tx_tp); }), "Failed to execute transmit task."); @@ -148,7 +155,9 @@ void lower_phy_baseband_processor::ul_process() std::unique_ptr rx_buffer = rx_buffers.pop_blocking(); // Receive baseband. + trace_point tp = ru_tracer.now(); baseband_gateway_receiver::metadata rx_metadata = receiver.receive(rx_buffer->get_writer()); + ru_tracer << trace_event("receive_baseband", tp); // Update last timestamp. { @@ -159,11 +168,15 @@ void lower_phy_baseband_processor::ul_process() // Queue uplink buffer processing. report_fatal_error_if_not(uplink_executor.execute([this, ul_buffer = std::move(rx_buffer), rx_metadata]() mutable { + trace_point ul_tp = ru_tracer.now(); + // Process UL. uplink_processor.process(ul_buffer->get_reader(), rx_metadata.ts); // Return buffer to receive. rx_buffers.push_blocking(std::move(ul_buffer)); + + ru_tracer << trace_event("uplink_baseband", ul_tp); }), "Failed to execute uplink processing task."); diff --git a/lib/phy/lower/processors/downlink/pdxch/CMakeLists.txt b/lib/phy/lower/processors/downlink/pdxch/CMakeLists.txt index 1a2300a366..8f3f2daa21 100644 --- a/lib/phy/lower/processors/downlink/pdxch/CMakeLists.txt +++ b/lib/phy/lower/processors/downlink/pdxch/CMakeLists.txt @@ -9,4 +9,6 @@ add_library(srsran_lower_phy_pdxch_processor STATIC pdxch_processor_factories.cpp pdxch_processor_impl.cpp) -target_link_libraries(srsran_lower_phy_pdxch_processor srsran_lower_phy_modulation) \ No newline at end of file +target_link_libraries(srsran_lower_phy_pdxch_processor + srsran_instrumentation + srsran_lower_phy_modulation) \ No newline at end of file diff --git a/lib/phy/lower/processors/downlink/pdxch/pdxch_processor_impl.cpp b/lib/phy/lower/processors/downlink/pdxch/pdxch_processor_impl.cpp index 99b2d6d8cd..2fc9f9ac6c 100644 --- a/lib/phy/lower/processors/downlink/pdxch/pdxch_processor_impl.cpp +++ b/lib/phy/lower/processors/downlink/pdxch/pdxch_processor_impl.cpp @@ -9,6 +9,7 @@ */ #include "pdxch_processor_impl.h" +#include "srsran/instrumentation/traces/du_traces.h" #include "srsran/phy/support/resource_grid_reader_empty.h" #include "srsran/srsvec/zero.h" @@ -94,5 +95,6 @@ void pdxch_processor_impl::handle_request(const resource_grid_reader& grid, cons late_context.slot = request.slot; late_context.sector = context.sector; notifier->on_pdxch_request_late(late_context); + l1_tracer << instant_trace_event{"on_pdxch_request_late", instant_trace_event::cpu_scope::thread}; } } diff --git a/lib/phy/lower/processors/uplink/prach/CMakeLists.txt b/lib/phy/lower/processors/uplink/prach/CMakeLists.txt index 4b69c45011..07df28592d 100644 --- a/lib/phy/lower/processors/uplink/prach/CMakeLists.txt +++ b/lib/phy/lower/processors/uplink/prach/CMakeLists.txt @@ -9,4 +9,4 @@ add_library(srsran_lower_phy_prach_processor STATIC prach_processor_factories.cpp prach_processor_worker.cpp) -target_link_libraries(srsran_lower_phy_prach_processor srsran_lower_phy_modulation) \ No newline at end of file +target_link_libraries(srsran_lower_phy_prach_processor srsran_lower_phy_modulation srsran_instrumentation) \ No newline at end of file diff --git a/lib/phy/lower/processors/uplink/prach/prach_processor_worker.cpp b/lib/phy/lower/processors/uplink/prach/prach_processor_worker.cpp index 85b8c65ea5..22af77d6df 100644 --- a/lib/phy/lower/processors/uplink/prach/prach_processor_worker.cpp +++ b/lib/phy/lower/processors/uplink/prach/prach_processor_worker.cpp @@ -10,6 +10,7 @@ #include "prach_processor_worker.h" #include "srsran/gateways/baseband/buffer/baseband_gateway_buffer_reader_view.h" +#include "srsran/instrumentation/traces/ru_traces.h" #include "srsran/ran/prach/prach_preamble_information.h" #include "srsran/srsvec/copy.h" @@ -95,6 +96,8 @@ void prach_processor_worker::accumulate_samples(const baseband_gateway_buffer_re state = states::processing; if (!async_task_executor.execute([this, nof_ports]() { + trace_point tp = ru_tracer.now(); + for (unsigned i_port = 0; i_port != nof_ports; ++i_port) { // Prepare PRACH demodulator configuration. ofdm_prach_demodulator::configuration config; @@ -114,6 +117,8 @@ void prach_processor_worker::accumulate_samples(const baseband_gateway_buffer_re demodulator->demodulate(*buffer, buffered_samples.get_channel_buffer(i_port), config); } + ru_tracer << trace_event("prach_demodulate", tp); + // Notify PRACH window reception. notifier->on_rx_prach_window(*buffer, prach_context); diff --git a/lib/phy/support/CMakeLists.txt b/lib/phy/support/CMakeLists.txt index c5481513fb..bf17e8cd43 100644 --- a/lib/phy/support/CMakeLists.txt +++ b/lib/phy/support/CMakeLists.txt @@ -10,13 +10,14 @@ add_library(srsran_phy_support STATIC interpolator/interpolator_linear_impl.cpp prach_buffer_pool_impl.cpp re_pattern.cpp - resource_grid_pool_impl.cpp resource_grid_impl.cpp + resource_grid_mapper_impl.cpp + resource_grid_pool_asynchronous_impl.cpp + resource_grid_pool_generic_impl.cpp resource_grid_reader_impl.cpp resource_grid_writer_impl.cpp - resource_grid_mapper_impl.cpp support_factories.cpp) -target_link_libraries(srsran_phy_support srsvec) +target_link_libraries(srsran_phy_support srsvec srsran_instrumentation) install(TARGETS srsran_phy_support EXPORT srsran_export) \ No newline at end of file diff --git a/lib/phy/support/resource_grid_pool_asynchronous_impl.cpp b/lib/phy/support/resource_grid_pool_asynchronous_impl.cpp new file mode 100644 index 0000000000..8f22e24936 --- /dev/null +++ b/lib/phy/support/resource_grid_pool_asynchronous_impl.cpp @@ -0,0 +1,111 @@ +/* + * + * 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 "resource_grid_pool_asynchronous_impl.h" +#include "srsran/adt/optional.h" +#include "srsran/instrumentation/traces/du_traces.h" +#include "srsran/phy/support/resource_grid.h" +#include "srsran/phy/support/resource_grid_context.h" +#include "srsran/phy/support/resource_grid_reader.h" +#include "srsran/support/executors/task_executor.h" +#include "srsran/support/srsran_assert.h" + +using namespace srsran; + +resource_grid_pool_asynchronous_impl::resource_grid_pool_asynchronous_impl(unsigned expire_timeout_slots_, + task_executor& async_executor_, + std::vector grids_) : + logger(srslog::fetch_basic_logger("PHY", true)), + expire_timeout_slots(expire_timeout_slots_), + grids(std::move(grids_)), + grids_str_zero(grids.size()), + grids_str_reserved(grids.size()), + reserved(grids.size()), + available(grids.size()), + async_executor(async_executor_) +{ + // Make sure the expiration timeout is consistent with the number of grids. If the expiration time is greater than + // or equal to the number of grids, the pool blocks. + srsran_assert(expire_timeout_slots < grids.size(), + "The grid expiration time (i.e., {}) must be lesser than the number of grids (i.e., {}).", + expire_timeout_slots, + grids.size()); + + // Move grids to available list. + for (unsigned i_grid = 0, i_grid_end = grids.size(); i_grid != i_grid_end; ++i_grid) { + grids_str_zero[i_grid] = "set_all_zero#" + std::to_string(i_grid); + grids_str_reserved[i_grid] = "rg_reserved#" + std::to_string(i_grid); + + bool success = available.push_blocking(i_grid); + srsran_assert(success, "Failed to push grid."); + } +} + +resource_grid& resource_grid_pool_asynchronous_impl::get_resource_grid(const resource_grid_context& context) +{ + // While the reserved buffer is not empty and the first element is expired. + while (!reserved.empty() && (reserved.top().expiration <= context.slot)) { + // Read first element. + reserved_resource_grid grid = reserved.top(); + + // Extract grid identifier. + unsigned grid_id = grid.grid_id; + + // Skip setting to zero if the grid is empty. + if (grids[grid_id]->get_reader().is_empty()) { + reserved.pop(); + available.push_blocking(grid_id); + continue; + } + + // Create lambda function for setting the grid to zero. + auto set_all_zero_func = [this, grid_id]() { + trace_point tp = l1_tracer.now(); + + // Set grid to zero. + grids[grid_id]->set_all_zero(); + + // Queue available grid. + bool success = available.push_blocking(grid_id); + srsran_assert(success, "Failed to push grid."); + + l1_tracer << trace_event(grids_str_zero[grid_id].c_str(), tp); + }; + + // Try to execute the asynchronous housekeeping task. + bool success = async_executor.execute(set_all_zero_func); + + // Pop the resource grid identifier if it was successfully executed. Otherwise, it skips zeroing. + if (success) { + reserved.pop(); + } else { + logger.warning(context.slot.sfn(), context.slot.slot_index(), "Failed to enqueue grid zeroing task."); + break; + } + } + + // Trace point for grid reservation. + trace_point tp = l1_tracer.now(); + + // Pop first available grid. + optional grid = available.pop_blocking(); + srsran_assert(grid.has_value(), "Failed to pop grid."); + + // Prepare reserved grid and enqueue. + reserved_resource_grid reserved_grid; + reserved_grid.expiration = context.slot + expire_timeout_slots; + reserved_grid.grid_id = grid.value(); + reserved.push(reserved_grid); + + // Trace the resource grid reservation. + l1_tracer << trace_event(grids_str_reserved[grid.value()].c_str(), tp); + + return *grids[reserved_grid.grid_id]; +} diff --git a/lib/phy/support/resource_grid_pool_asynchronous_impl.h b/lib/phy/support/resource_grid_pool_asynchronous_impl.h new file mode 100644 index 0000000000..0f1fea5328 --- /dev/null +++ b/lib/phy/support/resource_grid_pool_asynchronous_impl.h @@ -0,0 +1,67 @@ +/* + * + * 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/adt/concurrent_queue.h" +#include "srsran/adt/ring_buffer.h" +#include "srsran/phy/support/resource_grid.h" +#include "srsran/phy/support/resource_grid_context.h" +#include "srsran/phy/support/resource_grid_pool.h" +#include "srsran/support/event_tracing.h" +#include +#include + +namespace srsran { + +class task_executor; + +/// Implements a generic resource grid pool that zeroes the resource grids after a number of slots. +class resource_grid_pool_asynchronous_impl : public resource_grid_pool +{ +public: + using resource_grid_ptr = std::unique_ptr; + + /// \brief Constructs a resource grid pool. + /// \param expire_timeout_slots_ Resource grid timeout expiration in slots. + /// \param async_executor_ Asynchronous housekeeping executor. + /// \param grids_ Resource grids. + resource_grid_pool_asynchronous_impl(unsigned expire_timeout_slots_, + task_executor& async_executor_, + std::vector> grids); + + // See interface for documentation. + resource_grid& get_resource_grid(const resource_grid_context& context) override; + +private: + struct reserved_resource_grid { + slot_point expiration; + unsigned grid_id; + }; + + /// PHY logger. + srslog::basic_logger& logger; + /// Grid expiration timeout in slots. + unsigned expire_timeout_slots; + /// Actual pool of resource grids. + std::vector grids; + /// Pool of resource grid zero set string for tracing. + std::vector grids_str_zero; + /// Pool of resource grid reservation string for tracing. + std::vector grids_str_reserved; + /// Reserved resource grids. + ring_buffer reserved; + /// Queue of resource grids ready to use. + concurrent_queue available; + /// Asynchronous task executor. + task_executor& async_executor; +}; + +} // namespace srsran diff --git a/lib/phy/support/resource_grid_pool_generic_impl.cpp b/lib/phy/support/resource_grid_pool_generic_impl.cpp new file mode 100644 index 0000000000..4cebf9adee --- /dev/null +++ b/lib/phy/support/resource_grid_pool_generic_impl.cpp @@ -0,0 +1,30 @@ +/* + * + * 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 "resource_grid_pool_generic_impl.h" +#include "srsran/support/srsran_assert.h" + +using namespace srsran; + +resource_grid_pool_generic_impl::resource_grid_pool_generic_impl(std::vector grids_) : + grids(std::move(grids_)) +{ + srsran_assert(std::all_of(grids.begin(), grids.end(), [](const auto& ptr) { return ptr != nullptr; }), + "Detected invalid grid pointer."); +} + +resource_grid& resource_grid_pool_generic_impl::get_resource_grid(const resource_grid_context& context) +{ + unsigned index = count; + + count = (count + 1) % grids.size(); + + return *grids[index]; +} diff --git a/lib/phy/support/resource_grid_pool_generic_impl.h b/lib/phy/support/resource_grid_pool_generic_impl.h new file mode 100644 index 0000000000..c99e312233 --- /dev/null +++ b/lib/phy/support/resource_grid_pool_generic_impl.h @@ -0,0 +1,42 @@ +/* + * + * 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/adt/complex.h" +#include "srsran/adt/concurrent_queue.h" +#include "srsran/adt/ring_buffer.h" +#include "srsran/phy/support/resource_grid_pool.h" +#include "srsran/srsvec/aligned_vec.h" +#include "srsran/support/executors/task_executor.h" +#include + +namespace srsran { + +/// Implements a generic resource grid pool. +class resource_grid_pool_generic_impl : public resource_grid_pool +{ +public: + using resource_grid_ptr = std::unique_ptr; + + /// \brief Constructs a resource grid pool. + /// \param grids_ Actual vector containing resource grids. + resource_grid_pool_generic_impl(std::vector grids_); + + // See interface for documentation. + resource_grid& get_resource_grid(const resource_grid_context& context) override; + +private: + unsigned count = 0; + /// Actual pool of resource grids. + std::vector grids; +}; + +} // namespace srsran diff --git a/lib/phy/support/resource_grid_pool_impl.cpp b/lib/phy/support/resource_grid_pool_impl.cpp deleted file mode 100644 index c2964fc972..0000000000 --- a/lib/phy/support/resource_grid_pool_impl.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - * - * 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 "resource_grid_pool_impl.h" - -using namespace srsran; - -resource_grid_pool_impl::resource_grid_pool_impl(unsigned nof_sectors_, - unsigned nof_slots_, - std::vector>&& grids_) : - nof_slots(nof_slots_), nof_sectors(nof_sectors_), grids(std::move(grids_)) -{ - assert(nof_slots_ * nof_sectors_ == grids.size()); -} - -resource_grid& resource_grid_pool_impl::get_resource_grid(const resource_grid_context& context) -{ - assert(context.sector < nof_sectors); - - // Select slot from the absolute system slot - unsigned slot = context.slot.system_slot() % nof_slots; - - // Select resource grid and return the reference - return *grids[slot * nof_sectors + context.sector]; -} diff --git a/lib/phy/support/resource_grid_pool_impl.h b/lib/phy/support/resource_grid_pool_impl.h deleted file mode 100644 index 19fd4a47a8..0000000000 --- a/lib/phy/support/resource_grid_pool_impl.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * - * 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/adt/complex.h" -#include "srsran/phy/support/resource_grid_pool.h" -#include "srsran/srsvec/aligned_vec.h" -#include - -namespace srsran { - -class resource_grid_pool_impl : public resource_grid_pool -{ -private: - unsigned nof_slots; - unsigned nof_sectors; - - std::vector> grids; - -public: - resource_grid_pool_impl(unsigned nof_sectors_, - unsigned nof_slots_, - std::vector>&& grids_); - resource_grid& get_resource_grid(const resource_grid_context& context) override; -}; -} // namespace srsran diff --git a/lib/phy/support/support_factories.cpp b/lib/phy/support/support_factories.cpp index 7c0eb0c8f7..889d82a783 100644 --- a/lib/phy/support/support_factories.cpp +++ b/lib/phy/support/support_factories.cpp @@ -13,7 +13,8 @@ #include "prach_buffer_impl.h" #include "prach_buffer_pool_impl.h" #include "resource_grid_impl.h" -#include "resource_grid_pool_impl.h" +#include "resource_grid_pool_asynchronous_impl.h" +#include "resource_grid_pool_generic_impl.h" #include "srsran/phy/generic_functions/precoding/precoding_factories.h" #include "srsran/ran/prach/prach_constants.h" @@ -49,11 +50,17 @@ class resource_grid_factory_impl : public resource_grid_factory } // namespace std::unique_ptr -srsran::create_resource_grid_pool(unsigned nof_sectors, - unsigned nof_slots, - std::vector>&& grids) +srsran::create_generic_resource_grid_pool(std::vector> grids) { - return std::make_unique(nof_sectors, nof_slots, std::move(grids)); + return std::make_unique(std::move(grids)); +} + +std::unique_ptr +srsran::create_asynchronous_resource_grid_pool(unsigned expire_timeout_slots, + task_executor& async_executor, + std::vector> grids) +{ + return std::make_unique(expire_timeout_slots, async_executor, std::move(grids)); } std::unique_ptr diff --git a/lib/phy/upper/CMakeLists.txt b/lib/phy/upper/CMakeLists.txt index 0eac5034c2..6e11202519 100644 --- a/lib/phy/upper/CMakeLists.txt +++ b/lib/phy/upper/CMakeLists.txt @@ -13,8 +13,12 @@ add_subdirectory(equalization) add_subdirectory(sequence_generators) add_subdirectory(signal_processors) -add_library(srsran_downlink_processor downlink_processor_single_executor_impl.cpp downlink_processor_pool_impl.cpp) -target_link_libraries(srsran_downlink_processor srsran_channel_processors) +add_library(srsran_downlink_processor + downlink_processor_single_executor_impl.cpp + downlink_processor_pool_impl.cpp) +target_link_libraries(srsran_downlink_processor + srsran_instrumentation + srsran_channel_processors) add_library(srsran_uplink_processor uplink_processor_impl.cpp @@ -23,7 +27,13 @@ add_library(srsran_uplink_processor target_link_libraries(srsran_uplink_processor srsran_channel_processors) add_library(srsran_upper_phy upper_phy_factories.cpp upper_phy_impl.cpp upper_phy_factories.cpp upper_phy_rx_symbol_handler_impl.cpp upper_phy_rx_results_notifier_wrapper.cpp) -target_link_libraries(srsran_upper_phy srsran_downlink_processor srsran_uplink_processor srsran_phy_support srsran_generic_funcs srsran_channel_equalizer) +target_link_libraries(srsran_upper_phy + srsran_instrumentation + srsran_downlink_processor + srsran_uplink_processor + srsran_phy_support + srsran_generic_funcs + srsran_channel_equalizer) add_library(log_likelihood_ratio log_likelihood_ratio.cpp) diff --git a/lib/phy/upper/channel_processors/pdsch_processor_concurrent_impl.cpp b/lib/phy/upper/channel_processors/pdsch_processor_concurrent_impl.cpp index 7499965a25..a7ccd01294 100644 --- a/lib/phy/upper/channel_processors/pdsch_processor_concurrent_impl.cpp +++ b/lib/phy/upper/channel_processors/pdsch_processor_concurrent_impl.cpp @@ -10,9 +10,11 @@ #include "pdsch_processor_concurrent_impl.h" #include "pdsch_processor_validator_impl.h" +#include "srsran/instrumentation/traces/du_traces.h" #include "srsran/phy/support/resource_grid_mapper.h" #include "srsran/phy/upper/tx_buffer.h" #include "srsran/phy/upper/unique_tx_buffer.h" +#include "srsran/support/event_tracing.h" using namespace srsran; @@ -253,6 +255,8 @@ void pdsch_processor_concurrent_impl::fork_cb_batches() pseudo_random_generator::state_s c_init = scrambler->get_state(); auto async_task = [this, cb_batch_size, c_init, i_cb]() { + trace_point process_pdsch_tp = l1_tracer.now(); + // Select codeblock processor. pdsch_codeblock_processor& cb_processor = cb_processor_pool->get(); @@ -310,6 +314,8 @@ void pdsch_processor_concurrent_impl::fork_cb_batches() notifier->on_finish_processing(); } } + + l1_tracer << trace_event("CB batch", process_pdsch_tp); }; // Try to execute task asynchronously. @@ -334,6 +340,8 @@ void pdsch_processor_concurrent_impl::fork_cb_batches() void pdsch_processor_concurrent_impl::process_dmrs() { + trace_point process_dmrs_tp = l1_tracer.now(); + bounded_bitset rb_mask_bitset = config.freq_alloc.get_prb_mask(config.bwp_start_rb, config.bwp_size_rb); // Select the DM-RS reference point. @@ -357,6 +365,8 @@ void pdsch_processor_concurrent_impl::process_dmrs() // Put DM-RS. dmrs_generator_pool->get().map(*mapper, dmrs_config); + l1_tracer << trace_event("process_dmrs", process_dmrs_tp); + // Decrement asynchronous task counter. if (async_task_counter.fetch_sub(1) == 1) { // Notify end of the processing. 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 ba58931cf1..11a4d4b026 100644 --- a/lib/phy/upper/channel_processors/pusch/pusch_decoder_impl.cpp +++ b/lib/phy/upper/channel_processors/pusch/pusch_decoder_impl.cpp @@ -9,6 +9,7 @@ */ #include "pusch_decoder_impl.h" +#include "srsran/instrumentation/traces/du_traces.h" #include "srsran/phy/upper/channel_processors/pusch/pusch_decoder_notifier.h" #include "srsran/phy/upper/channel_processors/pusch/pusch_decoder_result.h" #include "srsran/phy/upper/rx_softbuffer.h" @@ -155,6 +156,8 @@ void pusch_decoder_impl::on_end_softbits() // Code block processing task. auto cb_process_task = [this, cb_meta, rm_buffer, cb_llrs, &cb_crc = cb_crcs[cb_id], block_crc, message]() { + trace_point tp = l1_tracer.now(); + // Check current CRC status. if (cb_crc) { // Dematch the new LLRs and combine them with the ones from previous transmissions. We do this everytime, @@ -189,6 +192,8 @@ void pusch_decoder_impl::on_end_softbits() if (cb_counter.fetch_sub(1) == 1) { join_and_notify(); } + + l1_tracer << trace_event("cb_decode", tp); }; // Execute task asynchronously if an executor is available and the number of codeblocks is larger than one. diff --git a/lib/phy/upper/downlink_processor_single_executor_impl.cpp b/lib/phy/upper/downlink_processor_single_executor_impl.cpp index d0c7cb94be..9e72e36145 100644 --- a/lib/phy/upper/downlink_processor_single_executor_impl.cpp +++ b/lib/phy/upper/downlink_processor_single_executor_impl.cpp @@ -9,6 +9,7 @@ */ #include "downlink_processor_single_executor_impl.h" +#include "srsran/instrumentation/traces/du_traces.h" #include "srsran/phy/support/resource_grid_mapper.h" #include "srsran/phy/upper/channel_processors/channel_processor_formatters.h" #include "srsran/phy/upper/signal_processors/signal_processor_formatters.h" @@ -60,12 +61,16 @@ void downlink_processor_single_executor_impl::process_pdcch(const pdcch_processo // Try to enqueue the PDU processing task. bool enqueued = executor.execute([this, pdu]() { + trace_point process_pdcch_tp = l1_tracer.now(); + // Do not execute if the grid is not available. if (current_grid != nullptr) { resource_grid_mapper& mapper = current_grid->get_mapper(); pdcch_proc->process(mapper, pdu); } + l1_tracer << trace_event("process_pdcch", process_pdcch_tp); + // Report task completion to FSM. on_task_completion(); }); @@ -100,10 +105,14 @@ void downlink_processor_single_executor_impl::process_pdsch( // Try to enqueue the PDU processing task. bool enqueued = executor.execute([this, sb = std::move(softbuffer), data, pdu]() mutable { + trace_point process_pdsch_tp = l1_tracer.now(); + // Do not execute if the grid is not available. if (current_grid != nullptr) { resource_grid_mapper& mapper = current_grid->get_mapper(); pdsch_proc->process(mapper, std::move(sb), pdsch_notifier, data, pdu); + + l1_tracer << trace_event("process_pdsch", process_pdsch_tp); } else { // Inform about the dropped PDSCH. logger.warning(pdu.slot.sfn(), pdu.slot.slot_index(), "Resource grid not configured. Ignoring PDSCH {:s}.", pdu); @@ -140,11 +149,15 @@ void downlink_processor_single_executor_impl::process_ssb(const ssb_processor::p // Try to enqueue the PDU processing task. bool enqueued = executor.execute([this, pdu]() { + trace_point process_ssb_tp = l1_tracer.now(); + // Do not execute if the grid is not available. if (current_grid != nullptr) { ssb_proc->process(current_grid->get_writer(), pdu); } + l1_tracer << trace_event("process_ssb", process_ssb_tp); + // Report task completion to FSM. on_task_completion(); }); @@ -178,12 +191,16 @@ void downlink_processor_single_executor_impl::process_nzp_csi_rs(const nzp_csi_r // Try to enqueue the PDU processing task. bool enqueued = executor.execute([this, config]() { + trace_point process_nzp_csi_rs_tp = l1_tracer.now(); + // Do not execute if the grid is not available. if (current_grid != nullptr) { resource_grid_mapper& mapper = current_grid->get_mapper(); csi_rs_proc->map(mapper, config); } + l1_tracer << trace_event("process_nzp_csi_rs", process_nzp_csi_rs_tp); + // Report task completion to FSM. on_task_completion(); }); @@ -200,43 +217,30 @@ void downlink_processor_single_executor_impl::process_nzp_csi_rs(const nzp_csi_r bool downlink_processor_single_executor_impl::configure_resource_grid(const resource_grid_context& context, resource_grid& grid) { - { - std::lock_guard lock(mutex); + std::lock_guard lock(mutex); - // Don't configure the grid if the DL processor is not available. - if (!state.is_idle()) { - return false; - } + // Don't configure the grid if the DL processor is not available. + if (!state.is_idle()) { + return false; + } - report_fatal_error_if_not(current_grid == nullptr, "A previously configured resource grid is still in use."); + report_fatal_error_if_not(current_grid == nullptr, "A previously configured resource grid is still in use."); - current_grid = &grid; - rg_context = context; + current_grid = &grid; + rg_context = context; - // update internal state to allow processing PDUs and increase the pending task counter. - state.on_resource_grid_configured(); - state.on_task_creation(); - } + // update internal state to allow processing PDUs and increase the pending task counter. + state.on_resource_grid_configured(); - // Set the resource grid to zero asynchronously. - bool enqueued = executor.execute([this]() { - current_grid->set_all_zero(); - // Report task completion to FSM. - on_task_completion(); - }); - - // If que task could not be enqueued. - if (!enqueued) { - // Report task drop to FSM. - on_task_completion(); - return false; - } + l1_tracer << instant_trace_event("configure_rg", instant_trace_event::cpu_scope::thread); return true; } void srsran::downlink_processor_single_executor_impl::finish_processing_pdus() { + l1_tracer << instant_trace_event("finish_processing_pdus", instant_trace_event::cpu_scope::global); + bool can_send_grid = false; { std::lock_guard lock(mutex); @@ -251,6 +255,8 @@ void srsran::downlink_processor_single_executor_impl::finish_processing_pdus() void downlink_processor_single_executor_impl::send_resource_grid() { + l1_tracer << instant_trace_event("send_resource_grid", instant_trace_event::cpu_scope::global); + // Send the resource grid if available. if (current_grid != nullptr) { gateway.send(rg_context, current_grid->get_reader()); diff --git a/lib/phy/upper/downlink_processor_single_executor_impl.h b/lib/phy/upper/downlink_processor_single_executor_impl.h index 69f5c8d586..f49de24b6b 100644 --- a/lib/phy/upper/downlink_processor_single_executor_impl.h +++ b/lib/phy/upper/downlink_processor_single_executor_impl.h @@ -11,6 +11,7 @@ #pragma once #include "downlink_processor_single_executor_state.h" +#include "srsran/instrumentation/traces/du_traces.h" #include "srsran/phy/support/resource_grid_context.h" #include "srsran/phy/upper/downlink_processor.h" #include @@ -99,7 +100,12 @@ class downlink_processor_single_executor_impl : public downlink_processor, priva // Do nothing. } - void on_finish_processing() override { callback.on_task_completion(); } + void on_finish_processing() override + { + l1_tracer << instant_trace_event("pdsch_on_finish_processing", instant_trace_event::cpu_scope::thread); + + callback.on_task_completion(); + } private: detail::downlink_processor_callback& callback; diff --git a/lib/phy/upper/uplink_processor_impl.cpp b/lib/phy/upper/uplink_processor_impl.cpp index 60335f2102..0ff4f3320b 100644 --- a/lib/phy/upper/uplink_processor_impl.cpp +++ b/lib/phy/upper/uplink_processor_impl.cpp @@ -9,6 +9,7 @@ */ #include "uplink_processor_impl.h" +#include "srsran/instrumentation/traces/du_traces.h" #include "srsran/phy/support/prach_buffer.h" #include "srsran/phy/support/prach_buffer_context.h" #include "srsran/phy/upper/unique_rx_softbuffer.h" @@ -55,12 +56,16 @@ void uplink_processor_impl::process_prach(upper_phy_rx_results_notifier& notifie const prach_buffer& buffer, const prach_buffer_context& context) { + trace_point tp = l1_tracer.now(); + ul_prach_results ul_results; ul_results.context = context; ul_results.result = prach->detect(buffer, get_prach_dectector_config_from_prach_context(context)); // Notify the PRACH results. notifier.on_new_prach_results(ul_results); + + l1_tracer << trace_event("process_prach", tp); } void uplink_processor_impl::process_pusch(span data, @@ -69,6 +74,7 @@ void uplink_processor_impl::process_pusch(span dat const resource_grid_reader& grid, const uplink_processor::pusch_pdu& pdu) { + trace_point tp = l1_tracer.now(); // Pop an adaptor identifier. optional adaptor_id = free_pusch_adaptors.try_pop(); if (!adaptor_id.has_value()) { @@ -86,12 +92,16 @@ void uplink_processor_impl::process_pusch(span dat // Process PUSCH. pusch_proc->process(data, std::move(softbuffer), processor_notifier, grid, pdu.pdu); + + l1_tracer << trace_event("process_pusch", tp); } void uplink_processor_impl::process_pucch(upper_phy_rx_results_notifier& notifier, const resource_grid_reader& grid, const uplink_processor::pucch_pdu& pdu) { + trace_point tp = l1_tracer.now(); + srsran_assert(pdu.context.format == pucch_format::FORMAT_1 || pdu.context.format == pucch_format::FORMAT_2, "Currently supporting PUCCH Format 1 and 2 only."); @@ -124,4 +134,6 @@ void uplink_processor_impl::process_pucch(upper_phy_rx_results_notifier& not // Notify the PUCCH results. notifier.on_new_pucch_results(result); + + l1_tracer << trace_event("process_pucch", tp); } diff --git a/lib/phy/upper/uplink_processor_impl.h b/lib/phy/upper/uplink_processor_impl.h index 41d994de02..c4ae104959 100644 --- a/lib/phy/upper/uplink_processor_impl.h +++ b/lib/phy/upper/uplink_processor_impl.h @@ -11,6 +11,7 @@ #pragma once #include "srsran/adt/concurrent_queue.h" +#include "srsran/instrumentation/traces/du_traces.h" #include "srsran/phy/upper/channel_processors/pusch/pusch_processor_result_notifier.h" #include "srsran/phy/upper/uplink_processor.h" #include "srsran/phy/upper/upper_phy_rx_results_notifier.h" @@ -87,6 +88,8 @@ class pusch_processor_result_notifier_adaptor : private pusch_processor_result_n } notifier->on_new_pusch_results_control(result); + + l1_tracer << instant_trace_event("on_uci", instant_trace_event::cpu_scope::thread); } // See interface for documentation. @@ -109,6 +112,8 @@ class pusch_processor_result_notifier_adaptor : private pusch_processor_result_n // Return the adaptor identifier to the queue. queue.push_blocking(queue_identifier); + + l1_tracer << instant_trace_event("on_sch", instant_trace_event::cpu_scope::thread); } free_adaptor_queue& queue; diff --git a/lib/phy/upper/upper_phy_factories.cpp b/lib/phy/upper/upper_phy_factories.cpp index 6864d1d936..590432dc3b 100644 --- a/lib/phy/upper/upper_phy_factories.cpp +++ b/lib/phy/upper/upper_phy_factories.cpp @@ -23,6 +23,7 @@ #include "srsran/phy/upper/channel_processors/pusch/factories.h" #include "srsran/phy/upper/unique_rx_softbuffer.h" #include "srsran/support/error_handling.h" +#include using namespace srsran; @@ -284,41 +285,33 @@ create_dl_resource_grid_pool(const upper_phy_config& config, std::shared_ptr> grids; - grids.reserve(nof_sectors * nof_slots); - for (unsigned sector_idx = 0; sector_idx != nof_sectors; ++sector_idx) { - for (unsigned slot_id = 0; slot_id != nof_slots; ++slot_id) { - std::unique_ptr grid = - rg_factory->create(config.nof_tx_ports, MAX_NSYMB_PER_SLOT, config.dl_bw_rb * NRE); - report_fatal_error_if_not(grid, "Invalid resource grid."); - grids.push_back(std::move(grid)); - } - } - return create_resource_grid_pool(nof_sectors, nof_slots, std::move(grids)); + // Generate resource grid instances. + std::vector> grids(config.nof_dl_rg); + std::generate( + grids.begin(), grids.end(), [&rg_factory, nof_tx_ports = config.nof_tx_ports, dl_bw_rb = config.dl_bw_rb]() { + return rg_factory->create(nof_tx_ports, MAX_NSYMB_PER_SLOT, dl_bw_rb * NRE); + }); + + return create_asynchronous_resource_grid_pool( + config.dl_rg_expire_timeout_slots, *config.dl_executors.front(), std::move(grids)); } static std::unique_ptr create_ul_resource_grid_pool(const upper_phy_config& config, std::shared_ptr rg_factory) { + // Configure one pool per upper PHY. report_fatal_error_if_not(rg_factory, "Invalid resource grid factory."); - unsigned nof_sectors = 1; - unsigned nof_slots = config.nof_slots_ul_rg; - std::vector> grids; - grids.reserve(nof_sectors * nof_slots); - for (unsigned sector_idx = 0; sector_idx != nof_sectors; ++sector_idx) { - for (unsigned slot_id = 0; slot_id != nof_slots; ++slot_id) { - std::unique_ptr grid = - rg_factory->create(config.nof_rx_ports, MAX_NSYMB_PER_SLOT, config.ul_bw_rb * NRE); - report_fatal_error_if_not(grid, "Invalid resource grid."); - grids.push_back(std::move(grid)); - } - } + + // Generate resource grid instances. + std::vector> grids(config.nof_ul_rg); + std::generate( + grids.begin(), grids.end(), [&rg_factory, nof_rx_ports = config.nof_rx_ports, ul_bw_rb = config.ul_bw_rb]() { + return rg_factory->create(nof_rx_ports, MAX_NSYMB_PER_SLOT, ul_bw_rb * NRE); + }); // Create UL resource grid pool. - return create_resource_grid_pool(nof_sectors, nof_slots, std::move(grids)); + return create_generic_resource_grid_pool(std::move(grids)); } static std::shared_ptr create_ul_processor_factory(const upper_phy_config& config) @@ -544,7 +537,7 @@ class upper_phy_factory_impl : public upper_phy_factory phy_config.rx_symbol_printer_port = config.rx_symbol_printer_port; phy_config.rx_symbol_printer_prach = config.rx_symbol_printer_prach; phy_config.rx_symbol_request_notifier = config.rx_symbol_request_notifier; - phy_config.nof_slots_ul_pdu_repository = config.nof_slots_ul_rg; + phy_config.nof_slots_ul_pdu_repository = config.nof_ul_rg; phy_config.dl_rg_pool = create_dl_resource_grid_pool(config, rg_factory); report_fatal_error_if_not(phy_config.dl_rg_pool, "Invalid downlink resource grid pool."); diff --git a/lib/phy/upper/upper_phy_impl.h b/lib/phy/upper/upper_phy_impl.h index f7b50a2867..0cd93a178a 100644 --- a/lib/phy/upper/upper_phy_impl.h +++ b/lib/phy/upper/upper_phy_impl.h @@ -14,6 +14,7 @@ #include "upper_phy_pdu_validators.h" #include "upper_phy_rx_results_notifier_wrapper.h" #include "upper_phy_rx_symbol_handler_impl.h" +#include "srsran/instrumentation/traces/du_traces.h" #include "srsran/phy/support/prach_buffer_pool.h" #include "srsran/phy/support/resource_grid_pool.h" #include "srsran/phy/upper/downlink_processor.h" diff --git a/tests/unittests/phy/support/resource_grid_pool_test.cpp b/tests/unittests/phy/support/resource_grid_pool_test.cpp index b85249ef58..40fb158840 100644 --- a/tests/unittests/phy/support/resource_grid_pool_test.cpp +++ b/tests/unittests/phy/support/resource_grid_pool_test.cpp @@ -33,7 +33,7 @@ void test(unsigned nof_slots, unsigned nof_sectors) } // Create resource grid pool - std::unique_ptr pool = create_resource_grid_pool(nof_sectors, nof_slots, std::move(grid_pool)); + std::unique_ptr pool = create_generic_resource_grid_pool(std::move(grid_pool)); // Iterate all parameters and assert grid reference for (unsigned slot_count = 0; slot_count != nof_slots; ++slot_count) { diff --git a/tests/unittests/phy/upper/downlink_processor_test.cpp b/tests/unittests/phy/upper/downlink_processor_test.cpp index 321c78ed8e..2f6199c59e 100644 --- a/tests/unittests/phy/upper/downlink_processor_test.cpp +++ b/tests/unittests/phy/upper/downlink_processor_test.cpp @@ -329,20 +329,6 @@ TEST(downlinkProcessorTest, finishWithoutProcessingPdusSendsTheGrid) resource_grid_spy grid(0, 0, 0); dl_processor->configure_resource_grid({slot, sector}, grid); - // The resource grid should not have been set to zero yet. - ASSERT_FALSE(grid.has_set_all_zero_method_been_called()); - - // The resource grid set all zero should be enqueued. - ASSERT_TRUE(executor.has_pending_tasks()); - - // Run resource grid zero set. - executor.run_pending_tasks(); - - // The resource grid set all zero should have been called. - ASSERT_TRUE(grid.has_set_all_zero_method_been_called()); - - ASSERT_FALSE(gw.sent); - // By finishing PDUs, the resource grid should be sent. dl_processor->finish_processing_pdus(); From 5d199f954798dc0a0c77371b589e0977b3fe21b8 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 22 Dec 2023 11:34:52 +0100 Subject: [PATCH 004/134] Fix export --- lib/instrumentation/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/instrumentation/CMakeLists.txt b/lib/instrumentation/CMakeLists.txt index 87711c3ea7..469f6e64d2 100644 --- a/lib/instrumentation/CMakeLists.txt +++ b/lib/instrumentation/CMakeLists.txt @@ -11,3 +11,6 @@ add_library(srsran_instrumentation traces/ru_traces.cpp traces/up_traces.cpp) target_link_libraries(srsran_instrumentation srsran_support) + +install(TARGETS srsran_instrumentation + EXPORT srsran_export) From 259575715f2465b3559122f9236ec4dac4e9d17c Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 27 Dec 2023 17:13:54 +0100 Subject: [PATCH 005/134] gnb: fix worker manager for ZMQ --- apps/gnb/gnb_worker_manager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/gnb/gnb_worker_manager.cpp b/apps/gnb/gnb_worker_manager.cpp index 6efc621b3c..b858d94e6e 100644 --- a/apps/gnb/gnb_worker_manager.cpp +++ b/apps/gnb/gnb_worker_manager.cpp @@ -259,6 +259,8 @@ void worker_manager::create_du_low_executors(bool is_block { using namespace execution_config_helper; + du_low_dl_executors.resize(cells_cfg.size()); + if (is_blocking_mode_active) { // Create a single worker, shared by the whole PHY. create_prio_worker("phy_worker", From 951f61a7cfbdad8c6e5c357e1aa78c66e76d80d3 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 28 Dec 2023 10:37:53 +0100 Subject: [PATCH 006/134] gnb: fix worker manager for RF --- apps/gnb/gnb_worker_manager.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/gnb/gnb_worker_manager.cpp b/apps/gnb/gnb_worker_manager.cpp index b858d94e6e..3d2dee4347 100644 --- a/apps/gnb/gnb_worker_manager.cpp +++ b/apps/gnb/gnb_worker_manager.cpp @@ -325,9 +325,8 @@ void worker_manager::create_du_low_executors(bool is_block os_thread_realtime_priority::max() - 10, dl_cpu_masks); - du_low_dl_executors.emplace_back(); for (unsigned w = 0; w != nof_dl_workers; ++w) { - du_low_dl_executors.back().emplace_back(exec_mng.executors().at(exec_name)); + du_low_dl_executors[cell_id].emplace_back(exec_mng.executors().at(exec_name)); } upper_pdsch_exec.push_back(exec_mng.executors().at(exec_name)); } From 77f72915bdd38f8b8cbd58c0e8950e462bdbb081 Mon Sep 17 00:00:00 2001 From: Piotr Gawlowicz Date: Tue, 21 Nov 2023 23:58:35 +0100 Subject: [PATCH 007/134] e2: refactor e2sm_rc service module --- include/srsran/e2/e2sm/e2sm.h | 77 ++++++- lib/e2/CMakeLists.txt | 2 + lib/e2/common/e2_entity.cpp | 9 + lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.cpp | 8 + lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.h | 1 + lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.cpp | 12 + lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.h | 3 + lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp | 31 +++ lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h | 1 + .../e2sm_rc_control_action_du_executor.cpp | 95 ++++++++ .../e2sm_rc_control_action_du_executor.h | 54 +++++ .../e2sm_rc/e2sm_rc_control_service_impl.cpp | 205 ++++++++++++++++++ .../e2sm_rc/e2sm_rc_control_service_impl.h | 109 ++++++++++ lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.cpp | 34 +++ lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.h | 15 +- .../procedures/e2_ric_control_procedure.cpp | 44 +++- lib/e2/procedures/e2_ric_control_procedure.h | 8 +- tests/unittests/e2/common/e2_test_helpers.h | 81 ++++++- .../e2/e2_ric_control_procedure_test.cpp | 2 +- 19 files changed, 760 insertions(+), 31 deletions(-) create mode 100644 lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp create mode 100644 lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h create mode 100644 lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp create mode 100644 lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h diff --git a/include/srsran/e2/e2sm/e2sm.h b/include/srsran/e2/e2sm/e2sm.h index 3e33d403e4..3aeb3694fa 100644 --- a/include/srsran/e2/e2sm/e2sm.h +++ b/include/srsran/e2/e2sm/e2sm.h @@ -16,10 +16,13 @@ #include "srsran/asn1/e2ap/e2ap.h" #include "srsran/asn1/e2ap/e2sm_kpm.h" #include "srsran/asn1/e2ap/e2sm_rc.h" +#include "srsran/e2/e2_messages.h" #include "srsran/support/async/async_task.h" namespace srsran { +enum e2sm_service_model_t { KPM, RC, UNKNOWN_SM }; + struct e2_sm_event_trigger_definition_s { enum e2sm_ric_service_type_t { REPORT, INSERT, POLICY, UNKNOWN }; e2sm_ric_service_type_t ric_service_type; @@ -27,11 +30,38 @@ struct e2_sm_event_trigger_definition_s { }; struct e2_sm_action_definition_s { - enum e2sm_service_model_t { KPM, RC, UNKNOWN }; e2sm_service_model_t service_model; variant action_definition; }; +struct e2_sm_ric_control_request_s { + e2sm_service_model_t service_model; + bool ric_call_process_id_present = false; + bool ric_ctrl_ack_request_present = false; + uint64_t ric_call_process_id; + variant request_ctrl_hdr; + variant request_ctrl_msg; + bool ric_ctrl_ack_request; +}; + +/// RIC control action executor maps an control action request to the proper stack functions. +class e2sm_control_action_executor +{ +public: + virtual ~e2sm_control_action_executor() = default; + /// \brief get action id associated with the control action executor. + /// \return Returns action id. + virtual uint32_t get_action_id() = 0; + /// \brief check if the requested RIC control action is supported. + /// \param[in] req is a RIC control action request (with control header and message). + /// \return Returns true if action supported by control action executor. + virtual bool ric_control_action_supported(const e2_sm_ric_control_request_s& req) = 0; + /// \brief trigger execution of the RIC control action. + /// \param[in] req is a RIC control action request (with control header and message). + /// \return Returns RIC control response. + virtual async_task execute_ric_control_action(const e2_sm_ric_control_request_s& req) = 0; +}; + class e2sm_report_service { public: @@ -50,6 +80,27 @@ class e2sm_report_service virtual srsran::byte_buffer get_indication_header() = 0; }; +class e2sm_control_service +{ +public: + virtual ~e2sm_control_service() = default; + /// \brief get style type id associated with the control service. + /// \return Returns style type id. + virtual uint32_t get_style_type() = 0; + /// \brief add an RIC control action executor associated with a specific action id. + /// \param[in] act_executor is a RIC control action executor that maps RIC action to the proper stack functions. + /// \return Returns true if action executor successfully added. + virtual bool add_e2sm_rc_control_action_executor(std::unique_ptr act_executor) = 0; + /// \brief check if the requested RIC control action is supported. + /// \param[in] req is a RIC control action request (with control header and message). + /// \return Returns true if the action supported by control service. + virtual bool control_request_supported(const e2_sm_ric_control_request_s& req) = 0; + /// \brief trigger execution of the RIC control action. + /// \param[in] req is a RIC control action request (with control header and message). + /// \return Returns RIC control response. + virtual async_task execute_control_request(const e2_sm_ric_control_request_s& req) = 0; +}; + class e2sm_handler { public: @@ -62,6 +113,10 @@ class e2sm_handler /// \param[in] buf /// \return Returns the E2SM Event Trigger Definition. virtual e2_sm_event_trigger_definition_s handle_packed_event_trigger_definition(const srsran::byte_buffer& buf) = 0; + /// \brief Handle the packed E2SM Event Trigger Definition. + /// \param[in] buf + /// \return Returns the E2SM Event Trigger Definition. + virtual e2_sm_ric_control_request_s handle_packed_ric_control_request(const asn1::e2ap::ri_cctrl_request_s& req) = 0; /// @brief Pack the RAN function description. virtual asn1::unbounded_octstring pack_ran_function_description() = 0; }; @@ -73,15 +128,23 @@ class e2sm_interface /// \brief gets a reference to the packer for this service model. /// \return Returns a reference to the packer. virtual e2sm_handler& get_e2sm_packer() = 0; - /// \brief Check if the requested RIC action is supported - /// \param[in] ric_action - /// \return Returns true if action suppored by E2SM + /// \brief Check if the requested RIC action is supported. + /// \param[in] ric_action is a RIC action to be setup. + /// \return Returns true if action supported by E2SM. virtual bool action_supported(const asn1::e2ap::ri_caction_to_be_setup_item_s& ric_action) = 0; - /// \brief gets a unique_ptr to the e2sm report service for an action - /// \param[in] action - /// \return Returns a unique_ptr to the e2sm report service + /// \brief gets a unique_ptr to the e2sm report service for an action. + /// \param[in] action is a RIC action to be setup (in binary form). + /// \return Returns a unique_ptr to the e2sm report service. virtual std::unique_ptr get_e2sm_report_service(const srsran::byte_buffer& action_definition) = 0; + /// \brief add an RIC control service associated with a specific style id. + /// \param[in] control_service is a RIC control service. + /// \return Returns true if the control service successfully added. + virtual bool add_e2sm_control_service(std::unique_ptr control_service) = 0; + /// \brief gets a unique_ptr to the e2sm control service for a control msg. + /// \param[in] req is a RIC control action request (with control header and message). + /// \return Returns a unique_ptr to the e2sm report service. + virtual e2sm_control_service* get_e2sm_control_service(const e2_sm_ric_control_request_s& req) = 0; /// \brief gets a reference to the param configurator for this service model. /// \return Returns a reference to the param configurator. virtual e2sm_param_configurator* get_param_configurator() = 0; diff --git a/lib/e2/CMakeLists.txt b/lib/e2/CMakeLists.txt index dd0c6b6189..2139b553b4 100644 --- a/lib/e2/CMakeLists.txt +++ b/lib/e2/CMakeLists.txt @@ -21,6 +21,8 @@ set(SOURCES e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.cpp e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp e2sm/e2sm_rc/e2sm_rc_impl.cpp + e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp + e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp e2sm/e2sm_factory.cpp e2sm/e2sm_manager.cpp e2sm/e2sm_kpm/e2sm_kpm_utils.cpp diff --git a/lib/e2/common/e2_entity.cpp b/lib/e2/common/e2_entity.cpp index 7b4ade5dc1..2b500b8c8f 100644 --- a/lib/e2/common/e2_entity.cpp +++ b/lib/e2/common/e2_entity.cpp @@ -12,6 +12,8 @@ #include "../e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.h" #include "../e2sm/e2sm_kpm/e2sm_kpm_impl.h" #include "../e2sm/e2sm_rc/e2sm_rc_asn1_packer.h" +#include "../e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h" +#include "../e2sm/e2sm_rc/e2sm_rc_control_service_impl.h" #include "../e2sm/e2sm_rc/e2sm_rc_impl.h" #include "e2_impl.h" #include "e2_subscription_manager_impl.h" @@ -57,6 +59,13 @@ e2_entity::e2_entity(e2ap_configuration& cfg_, rc_provider = std::make_unique(); auto e2sm_rc_packer = std::make_unique(*rc_provider); auto e2sm_rc_iface = std::make_unique(logger, *e2sm_rc_packer, e2_param_config_, *rc_provider); + // Create e2sm_rc Control Service Style 2 + std::unique_ptr rc_control_service_style2 = std::make_unique(2); + std::unique_ptr rc_control_action_2_6_executor = + std::make_unique(e2_param_config_); + rc_control_service_style2->add_e2sm_rc_control_action_executor(std::move(rc_control_action_2_6_executor)); + + e2sm_rc_iface->add_e2sm_control_service(std::move(rc_control_service_style2)); e2sm_handlers.push_back(std::move(e2sm_rc_packer)); e2sm_mngr->add_e2sm_service(e2sm_rc_asn1_packer::oid, std::move(e2sm_rc_iface)); } 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 a97d3969ea..2d803b9474 100644 --- a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.cpp +++ b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.cpp @@ -33,6 +33,14 @@ e2sm_kpm_asn1_packer::handle_packed_e2sm_action_definition(const srsran::byte_bu return action_def; } +e2_sm_ric_control_request_s +e2sm_kpm_asn1_packer::handle_packed_ric_control_request(const asn1::e2ap::ri_cctrl_request_s& req) +{ + printf("Failure - RIC control not available in e2sm_kpm.\n"); + e2_sm_ric_control_request_s control_request = {}; + return control_request; +} + e2_sm_event_trigger_definition_s e2sm_kpm_asn1_packer::handle_packed_event_trigger_definition(const srsran::byte_buffer& event_trigger_definition) { diff --git a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.h b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.h index cf0ee195eb..1cea2f7150 100644 --- a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.h +++ b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.h @@ -32,6 +32,7 @@ class e2sm_kpm_asn1_packer : public e2sm_handler /// Receive populated ASN1 struct that needs to be unpacked and forwarded. e2_sm_action_definition_s handle_packed_e2sm_action_definition(const srsran::byte_buffer& action_definition) override; + e2_sm_ric_control_request_s handle_packed_ric_control_request(const asn1::e2ap::ri_cctrl_request_s& req) override; e2_sm_event_trigger_definition_s handle_packed_event_trigger_definition(const srsran::byte_buffer& event_trigger_definition) override; diff --git a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.cpp b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.cpp index 4a004c0f53..3185de7af5 100644 --- a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.cpp +++ b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.cpp @@ -234,6 +234,18 @@ e2sm_kpm_impl::get_e2sm_report_service(const srsran::byte_buffer& action_definit } } +bool e2sm_kpm_impl::add_e2sm_control_service(std::unique_ptr control_service) +{ + logger.warning("Control Service not supported"); + return false; +} + +e2sm_control_service* e2sm_kpm_impl::get_e2sm_control_service(const e2_sm_ric_control_request_s& req) +{ + logger.warning("Control Service not supported"); + return nullptr; +} + e2sm_handler& e2sm_kpm_impl::get_e2sm_packer() { return e2sm_packer; diff --git a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.h b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.h index 7b930895fd..e0eb1a9880 100644 --- a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.h +++ b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.h @@ -32,6 +32,9 @@ class e2sm_kpm_impl : public e2sm_interface bool action_supported(const asn1::e2ap::ri_caction_to_be_setup_item_s& ric_action) override; std::unique_ptr get_e2sm_report_service(const srsran::byte_buffer& action_definition) override; + e2sm_control_service* get_e2sm_control_service(const e2_sm_ric_control_request_s& request) override; + + bool add_e2sm_control_service(std::unique_ptr control_service) override; void process_control_header(const srsran::byte_buffer& ctrl_header_buff, ric_control_config& ctrl_config) override; void process_control_message(const srsran::byte_buffer& ctrl_msg_buff, ric_control_config& ctrl_config) override; diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp index 9311811a3f..1a64692d1a 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp @@ -34,6 +34,37 @@ e2sm_rc_asn1_packer::handle_packed_e2sm_action_definition(const srsran::byte_buf return action_def; } +e2_sm_ric_control_request_s +e2sm_rc_asn1_packer::handle_packed_ric_control_request(const asn1::e2ap::ri_cctrl_request_s& req) +{ + e2_sm_ric_control_request_s ric_control_request = {}; + ric_control_request.service_model = e2sm_service_model_t::RC; + ric_control_request.ric_call_process_id_present = req->ri_ccall_process_id_present; + ric_control_request.ric_ctrl_ack_request_present = req->ri_cctrl_ack_request_present; + + if (ric_control_request.ric_call_process_id_present) { + ric_control_request.ric_call_process_id = req->ri_ccall_process_id->to_number(); + } + + asn1::cbit_ref bref_hdr(req->ri_cctrl_hdr.value); + asn1::cbit_ref bref_msg(req->ri_cctrl_msg.value); + if (variant_get(ric_control_request.request_ctrl_hdr).unpack(bref_hdr) != + asn1::SRSASN_SUCCESS) { + printf("Failed to unpack E2SM RC Control Request Header\n"); + } + + if (variant_get(ric_control_request.request_ctrl_msg).unpack(bref_msg) != + asn1::SRSASN_SUCCESS) { + printf("Failed to unpack E2SM RC Control Request Message\n"); + } + + if (ric_control_request.ric_ctrl_ack_request_present) { + ric_control_request.ric_ctrl_ack_request = + req->ri_cctrl_ack_request->value == asn1::e2ap::ri_cctrl_ack_request_e::ack; + } + return ric_control_request; +}; + e2_sm_event_trigger_definition_s e2sm_rc_asn1_packer::handle_packed_event_trigger_definition(const srsran::byte_buffer& event_trigger_definition) { diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h index 094f6b5dc3..21d2db03ed 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h @@ -30,6 +30,7 @@ class e2sm_rc_asn1_packer : public e2sm_handler e2sm_rc_asn1_packer(e2sm_param_provider& rc_provider); /// Receive populated ASN1 struct that needs to be unpacked and forwarded. e2_sm_action_definition_s handle_packed_e2sm_action_definition(const srsran::byte_buffer& action_definition) override; + e2_sm_ric_control_request_s handle_packed_ric_control_request(const asn1::e2ap::ri_cctrl_request_s& req) override; e2_sm_event_trigger_definition_s handle_packed_event_trigger_definition(const srsran::byte_buffer& event_trigger_definition) override; diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp new file mode 100644 index 0000000000..b0d3d7da98 --- /dev/null +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp @@ -0,0 +1,95 @@ +/* + * + * 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 "e2sm_rc_control_action_du_executor.h" + +using namespace asn1::e2ap; +using namespace asn1::e2sm_rc; +using namespace srsran; + +e2sm_rc_control_action_du_executor_base::e2sm_rc_control_action_du_executor_base( + e2sm_param_configurator& param_configurator_) : + logger(srslog::fetch_basic_logger("E2SM-RC")), param_configurator(param_configurator_) +{ +} + +uint32_t e2sm_rc_control_action_du_executor_base::get_action_id() +{ + return action_id; +} + +e2sm_rc_control_action_2_6_du_executor::e2sm_rc_control_action_2_6_du_executor( + e2sm_param_configurator& param_configurator_) : + e2sm_rc_control_action_du_executor_base(param_configurator_) +{ + // Control Action description: + // To control the radio resource management policy for slice-specific PRB quota allocation + action_id = 6; + action_name = "Slice-level PRB quota"; + action_params.insert({1, "RRM Policy Ratio List"}); + action_params.insert({2, "RRM Policy Ratio Group"}); + action_params.insert({3, "RRM Policy"}); + // Note: 4 missing in TS + action_params.insert({5, "RRM Policy Member List"}); + action_params.insert({6, "RRM Policy Member"}); + action_params.insert({7, "PLMN Identity"}); + action_params.insert({8, "S-NSSAI"}); + action_params.insert({9, "SST"}); + action_params.insert({10, "SD"}); + action_params.insert({11, "Min PRB Policy Ratio"}); + action_params.insert({12, "Max PRB Policy Ratio"}); + action_params.insert({13, "Dedicated PRB Policy Ratio"}); +}; + +bool e2sm_rc_control_action_2_6_du_executor::ric_control_action_supported(const e2_sm_ric_control_request_s& req) +{ + const e2_sm_rc_ctrl_msg_format1_s& ctrl_msg = + variant_get(req.request_ctrl_msg).ric_ctrl_msg_formats.ctrl_msg_format1(); + + for (auto& ran_p : ctrl_msg.ran_p_list) { + if (action_params.find(ran_p.ran_param_id) == action_params.end()) { + return false; + } + }; + return true; +}; + +async_task +e2sm_rc_control_action_2_6_du_executor::execute_ric_control_action(const e2_sm_ric_control_request_s& req) +{ + const e2_sm_rc_ctrl_hdr_format1_s& ctrl_hdr = + variant_get(req.request_ctrl_hdr).ric_ctrl_hdr_formats.ctrl_hdr_format1(); + const e2_sm_rc_ctrl_msg_format1_s& ctrl_msg = + variant_get(req.request_ctrl_msg).ric_ctrl_msg_formats.ctrl_msg_format1(); + + ctrl_config.ue_id = ctrl_hdr.ue_id.gnb_du_ue_id().gnb_cu_ue_f1ap_id; + + for (auto& ran_p : ctrl_msg.ran_p_list) { + if (action_params.find(ran_p.ran_param_id) != action_params.end()) { + if (ran_p.ran_param_id == 11) { + ctrl_config.min_prb_alloc = ran_p.ran_param_value_type.ran_p_choice_elem_true().ran_param_value.value_int(); + } else if (ran_p.ran_param_id == 12) { + ctrl_config.max_prb_alloc = ran_p.ran_param_value_type.ran_p_choice_elem_true().ran_param_value.value_int(); + } + } else { + logger.error("Parameter not supported"); + } + } + + return launch_async([this](coro_context>& ctx) { + CORO_BEGIN(ctx); + ric_control_config_response ctrl_response; + CORO_AWAIT_VALUE(ctrl_response, param_configurator.configure_ue_mac_scheduler(ctrl_config)); + e2_ric_control_response e2_resp; + e2_resp.success = ctrl_response.harq_processes_result and ctrl_response.max_prb_alloc_result and + ctrl_response.min_prb_alloc_result; + CORO_RETURN(e2_resp); + }); +}; \ No newline at end of file diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h new file mode 100644 index 0000000000..7e4ca50500 --- /dev/null +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h @@ -0,0 +1,54 @@ +/* + * + * 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/adt/optional.h" +#include "srsran/asn1/asn1_utils.h" +#include "srsran/e2/e2.h" +#include "srsran/e2/e2sm/e2sm.h" +#include + +namespace srsran { + +class e2sm_rc_control_action_du_executor_base : public e2sm_control_action_executor +{ +public: + e2sm_rc_control_action_du_executor_base(e2sm_param_configurator& param_configurator_); + virtual ~e2sm_rc_control_action_du_executor_base() = default; + + /// e2sm_control_request_executor functions. + uint32_t get_action_id() override; + bool ric_control_action_supported(const e2_sm_ric_control_request_s& req) override = 0; + async_task execute_ric_control_action(const e2_sm_ric_control_request_s& req) override = 0; + +protected: + srslog::basic_logger& logger; + uint32_t action_id; + std::string action_name; + std::map action_params; + e2sm_param_configurator& param_configurator; +}; + +class e2sm_rc_control_action_2_6_du_executor : public e2sm_rc_control_action_du_executor_base +{ +public: + e2sm_rc_control_action_2_6_du_executor(e2sm_param_configurator& param_configurator_); + virtual ~e2sm_rc_control_action_2_6_du_executor() = default; + + /// e2sm_control_request_executor functions. + bool ric_control_action_supported(const e2_sm_ric_control_request_s& req) override; + async_task execute_ric_control_action(const e2_sm_ric_control_request_s& req) override; + + // Helper variables. + ric_control_config ctrl_config; +}; + +} // namespace srsran diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp new file mode 100644 index 0000000000..73358fe4e2 --- /dev/null +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp @@ -0,0 +1,205 @@ +/* + * + * 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 "e2sm_rc_control_service_impl.h" +#include + +using namespace asn1::e2ap; +using namespace asn1::e2sm_rc; +using namespace srsran; + +e2sm_rc_control_service_base::e2sm_rc_control_service_base(uint32_t style_id_) : + logger(srslog::fetch_basic_logger("E2SM-RC")), style_id(style_id_) +{ + if (!get_e2sm_rc_control_style_def(style_id_, control_service_def)) { + logger.error("Control Service Style %i does not exist\n", style_id_); + } +} + +uint32_t e2sm_rc_control_service_base::get_style_type() +{ + return style_id; +} + +bool e2sm_rc_control_service_base::add_e2sm_rc_control_action_executor( + std::unique_ptr config_req_executor) +{ + config_req_executors.emplace(config_req_executor->get_action_id(), std::move(config_req_executor)); + return true; +} + +e2sm_rc_control_service::e2sm_rc_control_service(uint32_t style_id_) : e2sm_rc_control_service_base(style_id_) {} + +bool e2sm_rc_control_service::control_request_supported(const e2_sm_ric_control_request_s& req) +{ + const e2_sm_rc_ctrl_hdr_s& ctrl_hdr = variant_get(req.request_ctrl_hdr); + const e2_sm_rc_ctrl_msg_s& ctrl_msg = variant_get(req.request_ctrl_msg); + + // All styles 1 - 10 use hdr and msg format 1 + if (ctrl_hdr.ric_ctrl_hdr_formats.type().value != + e2_sm_rc_ctrl_hdr_s::ric_ctrl_hdr_formats_c_::types_opts::ctrl_hdr_format1) { + return false; + } + + if (ctrl_msg.ric_ctrl_msg_formats.type().value != + e2_sm_rc_ctrl_msg_s::ric_ctrl_msg_formats_c_::types_opts::ctrl_msg_format1) { + return false; + } + + const e2_sm_rc_ctrl_hdr_format1_s& ctrl_hdr_f1 = ctrl_hdr.ric_ctrl_hdr_formats.ctrl_hdr_format1(); + + if (ctrl_hdr_f1.ric_style_type != style_id) { + return false; + } + // TODO: check if UE supported + // ctrl_hdr_f1.ue_id + + if (ctrl_hdr_f1.ric_ctrl_decision_present) { + // TODO: check if ric_ctrl_decision supported + } + + // If call process id not supported, then it cannot be provided in the request. + if (control_service_def.call_process_id_format == 0) { + if (req.ric_call_process_id_present) { + return false; + } + } + + if (config_req_executors.find(ctrl_hdr_f1.ric_ctrl_action_id) != config_req_executors.end()) { + if (!config_req_executors.at(ctrl_hdr_f1.ric_ctrl_action_id)->ric_control_action_supported(req)) { + return false; + } + } else { + return false; + } + return true; +} + +async_task +e2sm_rc_control_service::execute_control_request(const e2_sm_ric_control_request_s& req) +{ + const e2_sm_rc_ctrl_hdr_format1_s& ctrl_hdr = + variant_get(req.request_ctrl_hdr).ric_ctrl_hdr_formats.ctrl_hdr_format1(); + return config_req_executors[ctrl_hdr.ric_ctrl_action_id]->execute_ric_control_action(req); +} + +e2sm_rc_control_service_style_255::e2sm_rc_control_service_style_255() : e2sm_rc_control_service_base(255) {} + +e2_sm_ric_control_request_s e2sm_rc_control_service_style_255::create_req_f1_from_req_f2( + const e2_sm_rc_ctrl_hdr_format2_s& ctrl_hdr_f2, + const asn1::e2sm_rc::e2_sm_rc_ctrl_msg_format2_style_item_s style, + const asn1::e2sm_rc::e2_sm_rc_ctrl_msg_format2_ctrl_action_item_s action) +{ + e2_sm_ric_control_request_s req_f1; + req_f1.ric_call_process_id_present = false; + req_f1.ric_ctrl_ack_request_present = false; + req_f1.ric_ctrl_ack_request = false; + + e2_sm_rc_ctrl_hdr_format1_s& hdr_f1 = variant_get(req_f1.request_ctrl_hdr) + .ric_ctrl_hdr_formats.set_ctrl_hdr_format1(); + + e2_sm_rc_ctrl_msg_format1_s& msg_f1 = variant_get(req_f1.request_ctrl_msg) + .ric_ctrl_msg_formats.set_ctrl_msg_format1(); + + hdr_f1.ric_style_type = style.indicated_ctrl_style_type; + hdr_f1.ric_ctrl_action_id = action.ric_ctrl_action_id; + + if (ctrl_hdr_f2.ue_id_present) { + hdr_f1.ue_id = ctrl_hdr_f2.ue_id; + } else { + // TODO: what if there is no UE? + hdr_f1.ue_id.set(); // set nulltype + } + + if (ctrl_hdr_f2.ric_ctrl_decision_present) { + hdr_f1.ric_ctrl_decision_present = true; + if (ctrl_hdr_f2.ric_ctrl_decision == e2_sm_rc_ctrl_hdr_format2_s::ric_ctrl_decision_e_::accept) { + hdr_f1.ric_ctrl_decision = e2_sm_rc_ctrl_hdr_format1_s::ric_ctrl_decision_e_::accept; + } else { + hdr_f1.ric_ctrl_decision = e2_sm_rc_ctrl_hdr_format1_s::ric_ctrl_decision_e_::reject; + } + } + msg_f1.ran_p_list = action.ran_p_list.ran_p_list; + + return req_f1; +} + +bool e2sm_rc_control_service_style_255::control_request_supported(const e2_sm_ric_control_request_s& req) +{ + const e2_sm_rc_ctrl_hdr_s& ctrl_hdr = variant_get(req.request_ctrl_hdr); + const e2_sm_rc_ctrl_msg_s& ctrl_msg = variant_get(req.request_ctrl_msg); + + if (ctrl_hdr.ric_ctrl_hdr_formats.type().value != + e2_sm_rc_ctrl_hdr_s::ric_ctrl_hdr_formats_c_::types_opts::ctrl_hdr_format2) { + return false; + } + + if (ctrl_msg.ric_ctrl_msg_formats.type().value != + e2_sm_rc_ctrl_msg_s::ric_ctrl_msg_formats_c_::types_opts::ctrl_msg_format2) { + return false; + } + + const e2_sm_rc_ctrl_hdr_format2_s& ctrl_hdr_f2 = ctrl_hdr.ric_ctrl_hdr_formats.ctrl_hdr_format2(); + const e2_sm_rc_ctrl_msg_format2_s& ctrl_msg_f2 = ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format2(); + + if (ctrl_hdr_f2.ue_id_present) { + // TODO: check if UE supported + // ctrl_hdr_f2.ue_id + } + + if (ctrl_hdr_f2.ric_ctrl_decision_present) { + // TODO: check if ric_ctrl_decision supported + } + + for (auto& style : ctrl_msg_f2.ric_ctrl_style_list) { + if (style.indicated_ctrl_style_type > 10) { + return false; + } + + if (e2sm_rc_control_services.find(style.indicated_ctrl_style_type) == e2sm_rc_control_services.end()) { + return false; + } + + for (auto& action : style.ric_ctrl_action_list) { + // Create a control request with format 1 to match the API of control service styles 1-10. + e2_sm_ric_control_request_s tmp_req_f1 = create_req_f1_from_req_f2(ctrl_hdr_f2, style, action); + + if (!e2sm_rc_control_services.at(style.indicated_ctrl_style_type)->control_request_supported(tmp_req_f1)) { + return false; + } + } + } + return false; +} + +async_task +e2sm_rc_control_service_style_255::execute_control_request(const e2_sm_ric_control_request_s& req) +{ + e2_ric_control_response aggregated_response; + aggregated_response.success = false; + + const e2_sm_rc_ctrl_hdr_format2_s& ctrl_hdr_f2 = + variant_get(req.request_ctrl_hdr).ric_ctrl_hdr_formats.ctrl_hdr_format2(); + const e2_sm_rc_ctrl_msg_format2_s& ctrl_msg_f2 = + variant_get(req.request_ctrl_msg).ric_ctrl_msg_formats.ctrl_msg_format2(); + + for (auto& style : ctrl_msg_f2.ric_ctrl_style_list) { + for (auto& action : style.ric_ctrl_action_list) { + // Create a control request with format 1 to match the API of control service styles 1-10. + e2_sm_ric_control_request_s tmp_req = create_req_f1_from_req_f2(ctrl_hdr_f2, style, action); + // TODO: execute all actions and aggregate the response + } + } + + return launch_async([aggregated_response](coro_context>& ctx) { + CORO_BEGIN(ctx); + CORO_RETURN(aggregated_response); + }); +} \ No newline at end of file diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h new file mode 100644 index 0000000000..43d316ebec --- /dev/null +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h @@ -0,0 +1,109 @@ +/* + * + * 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/e2/e2sm/e2sm.h" +#include + +namespace srsran { + +struct e2sm_rc_control_service_def_t { + uint32_t style_id; + std::string style_name; + uint32_t call_process_id_format; + uint32_t ctrl_hdr_format; + uint32_t ctrl_msg_format; + uint32_t ctrl_outcome_format; +}; + +/// Number of E2SM-RC Control Styles defined in O-RAN.WG3.E2SM-RC-R003-v03.00. +const size_t NOF_E2SM_RC_CTRL_SERVICE_STYLES = 11; + +// E2SM-RC Control Styles defined in O-RAN.WG3.E2SM-RC-R003-v03.00, Table 7.9-2 +inline bool get_e2sm_rc_control_style_def(uint32_t style_id, e2sm_rc_control_service_def_t& control_service_def) +{ + static const std::array style_defs = {{ + {1, "Radio Bearer Control", 1, 1, 1, 1}, + {2, "Radio Resource Allocation Control", 1, 1, 1, 1}, + {3, "Connected Mode Mobility Control", 1, 1, 1, 1}, + {4, "Radio Access Control", 1, 1, 1, 1}, + {5, "Dual Connectivity (DC) Control", 1, 1, 1, 1}, + {6, "Carrier Aggregation (CA) Control", 1, 1, 1, 1}, + {7, "Idle Mode Mobility Control", 1, 1, 1, 1}, + {8, "UE Information And Assignment", 0, 1, 1, 1}, + {9, "Measurement Reporting Configuration Control", 0, 1, 1, 3}, + {10, "Beamforming Configuration Control", 0, 1, 1, 0}, + {255, "Multiple Actions Control", 1, 2, 2, 2}, + }}; + + for (auto& style_def : style_defs) { + if (style_def.style_id == style_id) { + control_service_def = style_def; + return true; + } + } + return false; +} + +class e2sm_rc_control_service_base : public e2sm_control_service +{ +public: + e2sm_rc_control_service_base() = delete; + e2sm_rc_control_service_base(uint32_t style_id_); + virtual ~e2sm_rc_control_service_base() = default; + + /// e2sm_control_service functions. + uint32_t get_style_type() override; + bool add_e2sm_rc_control_action_executor(std::unique_ptr ctrl_act_executor) override; + bool control_request_supported(const e2_sm_ric_control_request_s& req) override = 0; + virtual async_task + execute_control_request(const e2_sm_ric_control_request_s& req) override = 0; + +protected: + srslog::basic_logger& logger; + uint32_t style_id; + e2sm_rc_control_service_def_t control_service_def; + std::map> config_req_executors; +}; + +/// Class for e2sm_rc_control_service styles 1-10. +class e2sm_rc_control_service : public e2sm_rc_control_service_base +{ +public: + e2sm_rc_control_service() = delete; + e2sm_rc_control_service(uint32_t style_id_); + virtual ~e2sm_rc_control_service() = default; + + bool control_request_supported(const e2_sm_ric_control_request_s& req) override; + async_task execute_control_request(const e2_sm_ric_control_request_s& req) override; +}; + +/// Class for e2sm_rc_control_service style 255 (Multiple actions) +class e2sm_rc_control_service_style_255 : public e2sm_rc_control_service_base +{ +public: + e2sm_rc_control_service_style_255(); + virtual ~e2sm_rc_control_service_style_255() = default; + + bool control_request_supported(const e2_sm_ric_control_request_s& req) override; + async_task execute_control_request(const e2_sm_ric_control_request_s& req) override; + +private: + // Helper functions. + e2_sm_ric_control_request_s + create_req_f1_from_req_f2(const asn1::e2sm_rc::e2_sm_rc_ctrl_hdr_format2_s& ctrl_hdr_f2, + const asn1::e2sm_rc::e2_sm_rc_ctrl_msg_format2_style_item_s style, + const asn1::e2sm_rc::e2_sm_rc_ctrl_msg_format2_ctrl_action_item_s action); + + std::map e2sm_rc_control_services; +}; + +} // namespace srsran \ No newline at end of file diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.cpp index c78d35fcb3..2f4d962758 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.cpp @@ -9,6 +9,7 @@ */ #include "e2sm_rc_impl.h" +#include "e2sm_rc_control_service_impl.h" #include "srsran/asn1/asn1_utils.h" #include "srsran/asn1/e2ap/e2sm_rc.h" #include "srsran/e2/e2.h" @@ -44,6 +45,39 @@ std::unique_ptr e2sm_rc_impl::get_e2sm_report_service(const return nullptr; } +bool e2sm_rc_impl::add_e2sm_control_service(std::unique_ptr control_service) +{ + control_services.emplace(control_service->get_style_type(), std::move(control_service)); + return true; +} + +e2sm_control_service* e2sm_rc_impl::get_e2sm_control_service(const e2_sm_ric_control_request_s& request) +{ + const e2_sm_rc_ctrl_hdr_s& ctrl_hdr = variant_get(request.request_ctrl_hdr); + + int64_t ric_style_type = 0; + if (ctrl_hdr.ric_ctrl_hdr_formats.type().value == + e2_sm_rc_ctrl_hdr_s::ric_ctrl_hdr_formats_c_::types_opts::ctrl_hdr_format1) { + e2_sm_rc_ctrl_hdr_format1_s ctrl_hdr_format1 = ctrl_hdr.ric_ctrl_hdr_formats.ctrl_hdr_format1(); + ric_style_type = ctrl_hdr_format1.ric_style_type; + } else if (ctrl_hdr.ric_ctrl_hdr_formats.type().value == + e2_sm_rc_ctrl_hdr_s::ric_ctrl_hdr_formats_c_::types_opts::ctrl_hdr_format2) { + ric_style_type = 255; + } else if (ctrl_hdr.ric_ctrl_hdr_formats.type().value == + e2_sm_rc_ctrl_hdr_s::ric_ctrl_hdr_formats_c_::types_opts::ctrl_hdr_format3) { + e2_sm_rc_ctrl_hdr_format3_s ctrl_hdr_format3 = ctrl_hdr.ric_ctrl_hdr_formats.ctrl_hdr_format3(); + ric_style_type = ctrl_hdr_format3.ric_style_type; + } else { + logger.error("RIC control header format not supported"); + return nullptr; + } + + if (control_services.find(ric_style_type) != control_services.end()) { + return control_services.at(ric_style_type).get(); + } + return nullptr; +} + e2sm_param_configurator* e2sm_rc_impl::get_param_configurator() { return ¶m_configurator; diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.h index 76954b076a..702f1a118b 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.h +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.h @@ -31,8 +31,10 @@ class e2sm_rc_impl : public e2sm_interface bool action_supported(const asn1::e2ap::ri_caction_to_be_setup_item_s& ric_action) override; - virtual std::unique_ptr - get_e2sm_report_service(const srsran::byte_buffer& action_definition) override; + std::unique_ptr get_e2sm_report_service(const srsran::byte_buffer& action_definition) override; + e2sm_control_service* get_e2sm_control_service(const e2_sm_ric_control_request_s& request) override; + + bool add_e2sm_control_service(std::unique_ptr control_service) override; e2sm_param_configurator* get_param_configurator() override; @@ -51,9 +53,10 @@ class e2sm_rc_impl : public e2sm_interface void process_control_message_format3(asn1::e2sm_rc::e2_sm_rc_ctrl_msg_format3_s ctrl_msg, ric_control_config& ctrl_config); - srslog::basic_logger& logger; - e2sm_handler& e2sm_packer; - e2sm_param_configurator& param_configurator; - e2sm_param_provider& param_interface; + srslog::basic_logger& logger; + e2sm_handler& e2sm_packer; + e2sm_param_configurator& param_configurator; + e2sm_param_provider& param_interface; + std::map> control_services; }; } // namespace srsran diff --git a/lib/e2/procedures/e2_ric_control_procedure.cpp b/lib/e2/procedures/e2_ric_control_procedure.cpp index 37fe819ca4..9d516e8969 100644 --- a/lib/e2/procedures/e2_ric_control_procedure.cpp +++ b/lib/e2/procedures/e2_ric_control_procedure.cpp @@ -26,15 +26,34 @@ void e2_ric_control_procedure::operator()(coro_context>& ctx) { ri_cctrl_request_s ctrl_req = request.request; e2sm_interface* e2sm_iface = e2sm_mng.get_e2sm_interface(ctrl_req->ra_nfunction_id.value); + + if (!e2sm_iface) { + logger.error("RAN function ID not supported"); + return; + } + + e2sm_handler& packer = e2sm_iface->get_e2sm_packer(); + e2_sm_ric_control_request_s ric_ctrl_req = packer.handle_packed_ric_control_request(ctrl_req); + e2sm_control_service* control_service = e2sm_iface->get_e2sm_control_service(ric_ctrl_req); + + if (!control_service) { + logger.error("RIC Control Service not supported"); + return; + } + + if (!control_service->control_request_supported(ric_ctrl_req)) { + logger.error("RIC Control Request not supported"); + return; + } + CORO_BEGIN(ctx); - ctrl_config_request = process_request(); - CORO_AWAIT_VALUE(ctrl_config_response, - e2sm_iface->get_param_configurator()->configure_ue_mac_scheduler(ctrl_config_request)); - if (ctrl_config_response.harq_processes_result and ctrl_config_response.max_prb_alloc_result and - ctrl_config_response.min_prb_alloc_result) { - send_e2_ric_control_acknowledge(ctrl_config_request, ctrl_config_response); - } else { - send_e2_ric_control_failure(ctrl_config_request, ctrl_config_response); + CORO_AWAIT_VALUE(response, control_service->execute_control_request(ric_ctrl_req)); + if (ric_ctrl_req.ric_ctrl_ack_request_present and ric_ctrl_req.ric_ctrl_ack_request) { + if (response.success) { + send_e2_ric_control_acknowledge(request, response); + } else { + send_e2_ric_control_failure(request, response); + } } CORO_RETURN(); } @@ -61,8 +80,8 @@ ric_control_config e2_ric_control_procedure::process_request() return ctrl_config; } -void e2_ric_control_procedure::send_e2_ric_control_acknowledge(ric_control_config ctrl_request, - ric_control_config_response ctrl_response) +void e2_ric_control_procedure::send_e2_ric_control_acknowledge(const e2_ric_control_request& ctrl_request, + const e2_ric_control_response& ctrl_response) { e2_message msg; msg.pdu.set_successful_outcome(); @@ -76,8 +95,8 @@ void e2_ric_control_procedure::send_e2_ric_control_acknowledge(ric_control_confi ric_notif.on_new_message(msg); } -void e2_ric_control_procedure::send_e2_ric_control_failure(ric_control_config ctrl_request, - ric_control_config_response ctrl_response) +void e2_ric_control_procedure::send_e2_ric_control_failure(const e2_ric_control_request& ctrl_request, + const e2_ric_control_response& ctrl_response) { e2_message msg; msg.pdu.set_unsuccessful_outcome(); @@ -88,5 +107,6 @@ void e2_ric_control_procedure::send_e2_ric_control_failure(ric_control_config fail->ri_crequest_id = request.request->ri_crequest_id; fail->ri_ccall_process_id_present = false; fail->ri_cctrl_outcome_present = false; + fail->cause->set_misc().value = cause_misc_e::options::unspecified; ric_notif.on_new_message(msg); } diff --git a/lib/e2/procedures/e2_ric_control_procedure.h b/lib/e2/procedures/e2_ric_control_procedure.h index 4e35a9b33b..9fe719df14 100644 --- a/lib/e2/procedures/e2_ric_control_procedure.h +++ b/lib/e2/procedures/e2_ric_control_procedure.h @@ -34,15 +34,15 @@ class e2_ric_control_procedure void operator()(coro_context>& ctx); ric_control_config process_request(); - void send_e2_ric_control_acknowledge(ric_control_config ctrl_request, ric_control_config_response ctrl_response); - void send_e2_ric_control_failure(ric_control_config ctrl_request, ric_control_config_response ctrl_response); + void send_e2_ric_control_acknowledge(const e2_ric_control_request& ctrl_request, + const e2_ric_control_response& ctrl_response); + void send_e2_ric_control_failure(const e2_ric_control_request&, const e2_ric_control_response& ctrl_response); private: srslog::basic_logger& logger; e2_message_notifier& ric_notif; e2sm_manager& e2sm_mng; const e2_ric_control_request request; - ric_control_config ctrl_config_request; - ric_control_config_response ctrl_config_response; + e2_ric_control_response response; }; } // namespace srsran \ No newline at end of file diff --git a/tests/unittests/e2/common/e2_test_helpers.h b/tests/unittests/e2/common/e2_test_helpers.h index 1ec83c0c8d..31273c3ebc 100644 --- a/tests/unittests/e2/common/e2_test_helpers.h +++ b/tests/unittests/e2/common/e2_test_helpers.h @@ -16,6 +16,8 @@ #include "lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.h" #include "lib/e2/e2sm/e2sm_param_provider.h" #include "lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h" +#include "lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h" +#include "lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h" #include "lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.h" #include "srsran/asn1/e2ap/e2ap.h" #include "srsran/asn1/e2ap/e2sm_rc.h" @@ -140,6 +142,72 @@ inline e2_message generate_e2_setup_request(std::string oid) return e2_msg; } +inline e2_message generate_ric_control_request_style2_action6(srslog::basic_logger& logger) +{ + using namespace asn1::e2ap; + e2_message e2_msg; + init_msg_s& initmsg = e2_msg.pdu.set_init_msg(); + initmsg.load_info_obj(ASN1_E2AP_ID_RI_CCTRL); + + ri_cctrl_request_s& ric_control_request = initmsg.value.ri_cctrl_request(); + ric_control_request->ri_ccall_process_id_present = false; + ric_control_request->ri_cctrl_ack_request_present = true; + ric_control_request->ri_cctrl_ack_request.value = ri_cctrl_ack_request_e::options::ack; + + ric_control_request->ra_nfunction_id.value.value = 1; + ric_control_request->ri_crequest_id.value.ric_requestor_id = 3; + ric_control_request->ri_crequest_id.value.ric_instance_id = 0; + + asn1::e2sm_rc::e2_sm_rc_ctrl_hdr_s ctrl_hdr; + ctrl_hdr.ric_ctrl_hdr_formats.set_ctrl_hdr_format1(); + ctrl_hdr.ric_ctrl_hdr_formats.ctrl_hdr_format1().ric_ctrl_decision_present = false; + ctrl_hdr.ric_ctrl_hdr_formats.ctrl_hdr_format1().ric_style_type = 2; + ctrl_hdr.ric_ctrl_hdr_formats.ctrl_hdr_format1().ric_ctrl_action_id = 6; + ctrl_hdr.ric_ctrl_hdr_formats.ctrl_hdr_format1().ue_id.set_gnb_ue_id(); + ctrl_hdr.ric_ctrl_hdr_formats.ctrl_hdr_format1().ue_id.gnb_du_ue_id().gnb_cu_ue_f1ap_id = 4; + + srsran::byte_buffer ctrl_hdr_buff; + asn1::bit_ref bref_msg(ctrl_hdr_buff); + if (ctrl_hdr.pack(bref_msg) != asn1::SRSASN_SUCCESS) { + logger.error("Failed to pack E2SM RC control header\n"); + } + + ric_control_request->ri_cctrl_hdr.value.resize(ctrl_hdr_buff.length()); + std::copy(ctrl_hdr_buff.begin(), ctrl_hdr_buff.end(), ric_control_request->ri_cctrl_hdr.value.begin()); + + asn1::e2sm_rc::e2_sm_rc_ctrl_msg_s ctrl_msg; + ctrl_msg.ric_ctrl_msg_formats.set_ctrl_msg_format1(); + ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format1().ran_p_list.resize(2); + ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format1().ran_p_list[0].ran_param_id = 11; + ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format1() + .ran_p_list[0] + .ran_param_value_type.set_ran_p_choice_elem_false() + .ran_param_value_present = true; + ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format1() + .ran_p_list[0] + .ran_param_value_type.ran_p_choice_elem_false() + .ran_param_value.set_value_int() = 5; + ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format1().ran_p_list[1].ran_param_id = 12; + ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format1() + .ran_p_list[1] + .ran_param_value_type.set_ran_p_choice_elem_false() + .ran_param_value_present = true; + ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format1() + .ran_p_list[1] + .ran_param_value_type.ran_p_choice_elem_false() + .ran_param_value.set_value_int() = 12; + + srsran::byte_buffer ctrl_msg_buff; + asn1::bit_ref bref_msg1(ctrl_msg_buff); + if (ctrl_msg.pack(bref_msg1) != asn1::SRSASN_SUCCESS) { + logger.error("Failed to pack E2SM RC control message\n"); + } + + ric_control_request->ri_cctrl_msg.value.resize(ctrl_msg_buff.length()); + std::copy(ctrl_msg_buff.begin(), ctrl_msg_buff.end(), ric_control_request->ri_cctrl_msg.value.begin()); + return e2_msg; +} + inline e2_message generate_ric_control_request(srslog::basic_logger& logger) { using namespace asn1::e2ap; @@ -624,6 +692,11 @@ class dummy_e2sm_handler : public e2sm_handler e2_sm_kpm_action_definition.action_definition_formats.action_definition_format3().granul_period = 10; return action_def; } + e2_sm_ric_control_request_s handle_packed_ric_control_request(const asn1::e2ap::ri_cctrl_request_s& req) override + { + e2_sm_ric_control_request_s ric_control_request = {}; + return ric_control_request; + } e2_sm_event_trigger_definition_s handle_packed_event_trigger_definition(const srsran::byte_buffer& buf) override { e2_sm_event_trigger_definition_s e2sm_event_trigger_def; @@ -696,6 +769,8 @@ class e2_test_base : public ::testing::Test std::unique_ptr packer; std::unique_ptr e2sm_kpm_iface; std::unique_ptr e2sm_rc_iface; + std::unique_ptr e2sm_rc_control_service_style2; + std::unique_ptr rc_control_action_2_6_executor; std::unique_ptr e2sm_kpm_packer; std::unique_ptr e2sm_rc_packer; std::unique_ptr rc_provider; @@ -850,7 +925,11 @@ class e2_test_setup : public e2_test_base e2sm_rc_packer = std::make_unique(*rc_provider); rc_param_configurator = std::make_unique(); e2sm_rc_iface = std::make_unique(test_logger, *e2sm_rc_packer, *rc_param_configurator, *rc_provider); - e2sm_mngr = std::make_unique(test_logger); + e2sm_rc_control_service_style2 = std::make_unique(2); + rc_control_action_2_6_executor = std::make_unique(*rc_param_configurator); + e2sm_rc_control_service_style2->add_e2sm_rc_control_action_executor(std::move(rc_control_action_2_6_executor)); + e2sm_rc_iface->add_e2sm_control_service(std::move(e2sm_rc_control_service_style2)); + e2sm_mngr = std::make_unique(test_logger); e2sm_mngr->add_e2sm_service("1.3.6.1.4.1.53148.1.2.2.2", std::move(e2sm_kpm_iface)); e2sm_mngr->add_e2sm_service("1.3.6.1.4.1.53148.1.1.2.3", std::move(e2sm_rc_iface)); e2sm_mngr->add_supported_ran_function(1, "1.3.6.1.4.1.53148.1.1.2.3"); diff --git a/tests/unittests/e2/e2_ric_control_procedure_test.cpp b/tests/unittests/e2/e2_ric_control_procedure_test.cpp index 7e7c7c84be..729710f842 100644 --- a/tests/unittests/e2/e2_ric_control_procedure_test.cpp +++ b/tests/unittests/e2/e2_ric_control_procedure_test.cpp @@ -19,7 +19,7 @@ using namespace srsran; TEST_F(e2_test_setup, ric_control_procedure_setup) { - e2_message request_msg = generate_ric_control_request(test_logger); + e2_message request_msg = generate_ric_control_request_style2_action6(test_logger); e2->handle_message(request_msg); asn1::cbit_ref bref(gw->last_pdu); e2_message msg = {}; From d7fcb617388930154bcce2b3358e1f7f679a5e1b Mon Sep 17 00:00:00 2001 From: Piotr Gawlowicz Date: Wed, 22 Nov 2023 13:31:23 +0100 Subject: [PATCH 008/134] e2sm_rc: clean old code --- include/srsran/e2/e2sm/e2sm.h | 11 -- lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.cpp | 15 --- lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.h | 5 - lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.cpp | 112 ------------------ lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.h | 16 --- .../procedures/e2_ric_control_procedure.cpp | 22 ---- lib/e2/procedures/e2_ric_control_procedure.h | 5 +- 7 files changed, 2 insertions(+), 184 deletions(-) diff --git a/include/srsran/e2/e2sm/e2sm.h b/include/srsran/e2/e2sm/e2sm.h index 3aeb3694fa..ae7e76ec7f 100644 --- a/include/srsran/e2/e2sm/e2sm.h +++ b/include/srsran/e2/e2sm/e2sm.h @@ -145,16 +145,5 @@ class e2sm_interface /// \param[in] req is a RIC control action request (with control header and message). /// \return Returns a unique_ptr to the e2sm report service. virtual e2sm_control_service* get_e2sm_control_service(const e2_sm_ric_control_request_s& req) = 0; - /// \brief gets a reference to the param configurator for this service model. - /// \return Returns a reference to the param configurator. - virtual e2sm_param_configurator* get_param_configurator() = 0; - /// \brief processes the control header and returns the control config - /// \param[in] ctrl_header_buff buffer of the control header - /// \param[out] ctrl_config to be sent to the DU - virtual void process_control_header(const srsran::byte_buffer& ctrl_header_buff, ric_control_config& ctrl_config) = 0; - /// \brief processes the control message and returns the control config - /// @param ctrl_msg_buff buffer of the control message - /// @param ctrl_config to be sent to the DU - virtual void process_control_message(const srsran::byte_buffer& ctrl_msg_buff, ric_control_config& ctrl_config) = 0; }; } // namespace srsran diff --git a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.cpp b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.cpp index 3185de7af5..0b5d3e4ab9 100644 --- a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.cpp +++ b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.cpp @@ -250,18 +250,3 @@ e2sm_handler& e2sm_kpm_impl::get_e2sm_packer() { return e2sm_packer; } - -e2sm_param_configurator* e2sm_kpm_impl::get_param_configurator() -{ - return nullptr; -} - -void e2sm_kpm_impl::process_control_header(const srsran::byte_buffer& ctrl_header_buff, ric_control_config& ctrl_config) -{ - logger.warning("Control Service not supported"); -} - -void e2sm_kpm_impl::process_control_message(const srsran::byte_buffer& ctrl_msg_buff, ric_control_config& ctrl_config) -{ - logger.warning("Control Service not supported"); -} diff --git a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.h b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.h index e0eb1a9880..1d0988da0e 100644 --- a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.h +++ b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.h @@ -27,8 +27,6 @@ class e2sm_kpm_impl : public e2sm_interface e2sm_handler& get_e2sm_packer() override; - e2sm_param_configurator* get_param_configurator() override; - bool action_supported(const asn1::e2ap::ri_caction_to_be_setup_item_s& ric_action) override; std::unique_ptr get_e2sm_report_service(const srsran::byte_buffer& action_definition) override; @@ -36,9 +34,6 @@ class e2sm_kpm_impl : public e2sm_interface bool add_e2sm_control_service(std::unique_ptr control_service) override; - void process_control_header(const srsran::byte_buffer& ctrl_header_buff, ric_control_config& ctrl_config) override; - void process_control_message(const srsran::byte_buffer& ctrl_msg_buff, ric_control_config& ctrl_config) override; - private: /// Helper functions to check whether subscription actions are supported. bool process_action_def_meas_info_list(const asn1::e2sm_kpm::meas_info_list_l& meas_info_list, diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.cpp index 2f4d962758..38287f5c4f 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.cpp @@ -12,7 +12,6 @@ #include "e2sm_rc_control_service_impl.h" #include "srsran/asn1/asn1_utils.h" #include "srsran/asn1/e2ap/e2sm_rc.h" -#include "srsran/e2/e2.h" #include "srsran/e2/e2sm/e2sm.h" using namespace asn1::e2ap; @@ -77,114 +76,3 @@ e2sm_control_service* e2sm_rc_impl::get_e2sm_control_service(const e2_sm_ric_con } return nullptr; } - -e2sm_param_configurator* e2sm_rc_impl::get_param_configurator() -{ - return ¶m_configurator; -} - -void e2sm_rc_impl::process_control_header(const srsran::byte_buffer& ctrl_header_buff, ric_control_config& ctrl_config) -{ - e2_sm_rc_ctrl_hdr_s ctrl_hdr; - asn1::cbit_ref bref_ctrl(ctrl_header_buff); - if (ctrl_hdr.unpack(bref_ctrl) != asn1::SRSASN_SUCCESS) { - logger.error("Failed to unpack E2SM RC Action Definition\n"); - } - - if (ctrl_hdr.ric_ctrl_hdr_formats.type().value == - e2_sm_rc_ctrl_hdr_s::ric_ctrl_hdr_formats_c_::types_opts::ctrl_hdr_format1) { - // TODO - } else if (ctrl_hdr.ric_ctrl_hdr_formats.type().value == - e2_sm_rc_ctrl_hdr_s::ric_ctrl_hdr_formats_c_::types_opts::ctrl_hdr_format2) { - e2_sm_rc_ctrl_hdr_format2_s ctrl_hdr_format2 = ctrl_hdr.ric_ctrl_hdr_formats.ctrl_hdr_format2(); - process_control_header_format2(ctrl_hdr_format2, ctrl_config); - } else if (ctrl_hdr.ric_ctrl_hdr_formats.type().value == - e2_sm_rc_ctrl_hdr_s::ric_ctrl_hdr_formats_c_::types_opts::ctrl_hdr_format3) { - // TODO - } else { - logger.error("RIC control header format not supported"); - return; - } -} - -void e2sm_rc_impl::process_control_message(const srsran::byte_buffer& ctrl_msg_buff, ric_control_config& ctrl_config) -{ - e2_sm_rc_ctrl_msg_s ctrl_msg; - asn1::cbit_ref bref_msg(ctrl_msg_buff); - if (ctrl_msg.unpack(bref_msg) != asn1::SRSASN_SUCCESS) { - logger.error("Failed to unpack E2SM RC Action Definition\n"); - } - - if (ctrl_msg.ric_ctrl_msg_formats.type().value == - e2_sm_rc_ctrl_msg_s::ric_ctrl_msg_formats_c_::types_opts::ctrl_msg_format1) { - e2sm_service_provider& rc_provider = param_interface.service_providers.find(1)->second; - process_control_message_format1(ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format1(), - ctrl_config, - rc_provider.style_providers.at(1).action_providers.at(1)); - } else if (ctrl_msg.ric_ctrl_msg_formats.type().value == - e2_sm_rc_ctrl_msg_s::ric_ctrl_msg_formats_c_::types_opts::ctrl_msg_format2) { - process_control_message_format2(ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format2(), ctrl_config); - } else if (ctrl_msg.ric_ctrl_msg_formats.type().value == - e2_sm_rc_ctrl_msg_s::ric_ctrl_msg_formats_c_::types_opts::ctrl_msg_format3) { - process_control_message_format3(ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format3(), ctrl_config); - } else { - logger.error("RIC control message format not supported"); - } -} - -void e2sm_rc_impl::process_control_header_format2(e2_sm_rc_ctrl_hdr_format2_s ctrl_hdr, ric_control_config& ctrl_config) -{ - if (ctrl_hdr.ue_id_present) { - if (ctrl_hdr.ue_id.type().value == ue_id_c::types_opts::gnb_du_ue_id) { - ctrl_config.ue_id = ctrl_hdr.ue_id.gnb_du_ue_id().gnb_cu_ue_f1ap_id; - } else { - logger.error("UE ID not supported"); - } - } -} - -void e2sm_rc_impl::process_control_message_format1(e2_sm_rc_ctrl_msg_format1_s ctrl_msg, - ric_control_config& ctrl_config, - e2sm_action_provider action_provider) -{ - for (auto& ran_p : ctrl_msg.ran_p_list) { - if (action_provider.action_params.count(ran_p.ran_param_id)) { - if (ran_p.ran_param_id == 12) { - ctrl_config.max_prb_alloc = ran_p.ran_param_value_type.ran_p_choice_elem_true().ran_param_value.value_int(); - } else if (ran_p.ran_param_id == 13) { - ctrl_config.min_prb_alloc = ran_p.ran_param_value_type.ran_p_choice_elem_true().ran_param_value.value_int(); - } - } else { - logger.error("Parameter not supported"); - } - } -} - -void e2sm_rc_impl::process_control_message_format2(e2_sm_rc_ctrl_msg_format2_s ctrl_msg, - ric_control_config& ctrl_config) -{ - e2sm_service_provider& rc_provider = param_interface.service_providers.find(1)->second; - for (auto& style : ctrl_msg.ric_ctrl_style_list) { - if (rc_provider.style_providers.count(style.indicated_ctrl_style_type)) { - for (auto& action : style.ric_ctrl_action_list) { - if (rc_provider.style_providers.at(style.indicated_ctrl_style_type) - .action_providers.count(action.ric_ctrl_action_id)) { - process_control_message_format1(action.ran_p_list, - ctrl_config, - rc_provider.style_providers.at(style.indicated_ctrl_style_type) - .action_providers.at(action.ric_ctrl_action_id)); - } else { - logger.error("Action not supported"); - } - } - } else { - logger.error("Style not supported"); - } - } -} - -void e2sm_rc_impl::process_control_message_format3(e2_sm_rc_ctrl_msg_format3_s ctrl_msg, - ric_control_config& ctrl_config) -{ - // TODO -} diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.h index 702f1a118b..76ceaa8018 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.h +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.h @@ -36,23 +36,7 @@ class e2sm_rc_impl : public e2sm_interface bool add_e2sm_control_service(std::unique_ptr control_service) override; - e2sm_param_configurator* get_param_configurator() override; - - void process_control_header(const srsran::byte_buffer& ctrl_header_buff, ric_control_config& ctrl_config) override; - - void process_control_message(const srsran::byte_buffer& ctrl_msg_buff, ric_control_config& ctrl_config) override; - private: - void process_control_header_format2(asn1::e2sm_rc::e2_sm_rc_ctrl_hdr_format2_s ctrl_hdr, - ric_control_config& ctrl_config); - void process_control_message_format1(asn1::e2sm_rc::e2_sm_rc_ctrl_msg_format1_s ctrl_msg, - ric_control_config& ctrl_config, - e2sm_action_provider action_provider); - void process_control_message_format2(asn1::e2sm_rc::e2_sm_rc_ctrl_msg_format2_s ctrl_msg, - ric_control_config& ctrl_config); - void process_control_message_format3(asn1::e2sm_rc::e2_sm_rc_ctrl_msg_format3_s ctrl_msg, - ric_control_config& ctrl_config); - srslog::basic_logger& logger; e2sm_handler& e2sm_packer; e2sm_param_configurator& param_configurator; diff --git a/lib/e2/procedures/e2_ric_control_procedure.cpp b/lib/e2/procedures/e2_ric_control_procedure.cpp index 9d516e8969..d484f3f4b8 100644 --- a/lib/e2/procedures/e2_ric_control_procedure.cpp +++ b/lib/e2/procedures/e2_ric_control_procedure.cpp @@ -58,28 +58,6 @@ void e2_ric_control_procedure::operator()(coro_context>& ctx) CORO_RETURN(); } -ric_control_config e2_ric_control_procedure::process_request() -{ - ri_cctrl_request_s ctrl_req = request.request; - e2_sm_rc_ctrl_outcome_s outcome; - e2sm_interface* e2sm_iface = e2sm_mng.get_e2sm_interface(ctrl_req->ra_nfunction_id.value); - if (!e2sm_iface) { - logger.error("RAN function ID not supported"); - return {}; - } - - ric_control_config ctrl_config; - - if (!(ctrl_req->ri_cctrl_hdr.value.to_number() == 0)) { - e2sm_iface->process_control_header(ctrl_req->ri_cctrl_hdr.value, ctrl_config); - } else { - logger.warning("Control header not present"); - ctrl_config.ue_id = 1; - } - e2sm_iface->process_control_message(ctrl_req->ri_cctrl_msg.value, ctrl_config); - return ctrl_config; -} - void e2_ric_control_procedure::send_e2_ric_control_acknowledge(const e2_ric_control_request& ctrl_request, const e2_ric_control_response& ctrl_response) { diff --git a/lib/e2/procedures/e2_ric_control_procedure.h b/lib/e2/procedures/e2_ric_control_procedure.h index 9fe719df14..dbee6dca81 100644 --- a/lib/e2/procedures/e2_ric_control_procedure.h +++ b/lib/e2/procedures/e2_ric_control_procedure.h @@ -33,9 +33,8 @@ class e2_ric_control_procedure void operator()(coro_context>& ctx); - ric_control_config process_request(); - void send_e2_ric_control_acknowledge(const e2_ric_control_request& ctrl_request, - const e2_ric_control_response& ctrl_response); + void send_e2_ric_control_acknowledge(const e2_ric_control_request& ctrl_request, + const e2_ric_control_response& ctrl_response); void send_e2_ric_control_failure(const e2_ric_control_request&, const e2_ric_control_response& ctrl_response); private: From 9f1322daeb672d04ed377d1fc98de7952bdebd79 Mon Sep 17 00:00:00 2001 From: Piotr Gawlowicz Date: Thu, 23 Nov 2023 10:16:40 +0100 Subject: [PATCH 009/134] e2sm_rc: refactor ran function description generation --- lib/e2/common/e2_entity.cpp | 8 +- lib/e2/common/e2_entity.h | 1 - lib/e2/e2sm/e2sm_param_provider.h | 96 ------------------- lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp | 50 ++++------ lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h | 11 +-- .../e2sm_rc_control_action_du_executor.cpp | 24 ++++- .../e2sm_rc_control_action_du_executor.h | 5 +- .../e2sm_rc/e2sm_rc_control_service_impl.cpp | 39 ++++++++ .../e2sm_rc/e2sm_rc_control_service_impl.h | 2 + lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.cpp | 7 +- lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.h | 8 +- lib/e2/procedures/e2_ric_control_procedure.h | 1 - tests/unittests/e2/common/e2_test_helpers.h | 24 +++-- .../unittests/e2/e2_setup_procedure_test.cpp | 6 +- 14 files changed, 111 insertions(+), 171 deletions(-) delete mode 100644 lib/e2/e2sm/e2sm_param_provider.h diff --git a/lib/e2/common/e2_entity.cpp b/lib/e2/common/e2_entity.cpp index 2b500b8c8f..056440fad6 100644 --- a/lib/e2/common/e2_entity.cpp +++ b/lib/e2/common/e2_entity.cpp @@ -56,15 +56,15 @@ e2_entity::e2_entity(e2ap_configuration& cfg_, e2_du_metrics_iface_.connect_e2_du_meas_provider(std::move(e2sm_kpm_meas_provider)); } if (cfg.e2sm_rc_enabled) { - rc_provider = std::make_unique(); - auto e2sm_rc_packer = std::make_unique(*rc_provider); - auto e2sm_rc_iface = std::make_unique(logger, *e2sm_rc_packer, e2_param_config_, *rc_provider); - // Create e2sm_rc Control Service Style 2 + auto e2sm_rc_packer = std::make_unique(); + auto e2sm_rc_iface = std::make_unique(logger, *e2sm_rc_packer); + // Create e2sm_rc Control Service Style 2. std::unique_ptr rc_control_service_style2 = std::make_unique(2); std::unique_ptr rc_control_action_2_6_executor = std::make_unique(e2_param_config_); rc_control_service_style2->add_e2sm_rc_control_action_executor(std::move(rc_control_action_2_6_executor)); + e2sm_rc_packer->add_e2sm_control_service(rc_control_service_style2.get()); e2sm_rc_iface->add_e2sm_control_service(std::move(rc_control_service_style2)); e2sm_handlers.push_back(std::move(e2sm_rc_packer)); e2sm_mngr->add_e2sm_service(e2sm_rc_asn1_packer::oid, std::move(e2sm_rc_iface)); diff --git a/lib/e2/common/e2_entity.h b/lib/e2/common/e2_entity.h index 39179631a5..dd43748c1f 100644 --- a/lib/e2/common/e2_entity.h +++ b/lib/e2/common/e2_entity.h @@ -66,7 +66,6 @@ class e2_entity final : public e2_interface std::unique_ptr e2sm_mngr = nullptr; std::unique_ptr subscription_mngr = nullptr; std::unique_ptr decorated_e2_iface = nullptr; - std::unique_ptr rc_provider = nullptr; std::vector> e2sm_handlers; }; diff --git a/lib/e2/e2sm/e2sm_param_provider.h b/lib/e2/e2sm/e2sm_param_provider.h deleted file mode 100644 index aadc89226e..0000000000 --- a/lib/e2/e2sm/e2sm_param_provider.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * - * 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/adt/byte_buffer.h" -#include "srsran/asn1/asn1_utils.h" -#include "srsran/asn1/e2ap/e2ap.h" -#include "srsran/asn1/e2ap/e2sm_rc.h" -#include "srsran/e2/e2sm/e2sm.h" -#include -namespace srsran { - -struct action_parameter_t { - uint32_t id; - std::string name; -}; - -class e2sm_action_provider -{ -public: - e2sm_action_provider(std::string name_) : name(name_) {} - e2sm_action_provider(const e2sm_action_provider& other) : name(other.name), action_params(other.action_params) {} - - void add_parameter_support(uint32_t id, std::string param_name) { action_params[id] = {id, param_name}; } - std::string name; - std::map action_params; -}; - -class e2sm_style_provider -{ -public: - e2sm_style_provider(std::string name_) : name(name_) {} - e2sm_style_provider(const e2sm_style_provider& other) : name(other.name), action_providers(other.action_providers) {} - void add_action_provider(uint16_t id, const e2sm_action_provider& provider) - { - action_providers.emplace(id, e2sm_action_provider(provider)); - } - std::string name; - std::map action_providers; -}; - -class e2sm_service_provider -{ -public: - e2sm_service_provider(std::string name_) : name(name_) {} - e2sm_service_provider(const e2sm_service_provider& other) : name(other.name), style_providers(other.style_providers) - { - } - void add_style_provider(uint32_t id, e2sm_style_provider provider) - { - style_providers.emplace(id, e2sm_style_provider(provider)); - } - std::string name; - std::map style_providers; -}; - -class e2sm_param_provider -{ -public: - e2sm_param_provider() - { - // Slice-level PRB quota(6) -> Radio Resource Allocation Control(2) - std::vector action_params2_6; - action_params2_6.push_back({10, "Min PRB Policy Ratio"}); - action_params2_6.push_back({11, "Max PRB Policy Ratio"}); - e2sm_action_provider action_provider6("Slice-level PRB quota"); - for (auto& param : action_params2_6) { - action_provider6.add_parameter_support(param.id, param.name); - } - e2sm_style_provider style_provider2("Radio Resource Allocation Control"); - style_provider2.add_action_provider(6, action_provider6); - - e2sm_service_provider ctrl_provider("Control Service"); - ctrl_provider.add_style_provider(2, style_provider2); - service_providers.emplace(1, ctrl_provider); - } - e2sm_param_provider(const e2sm_param_provider& other) : name(other.name), service_providers(other.service_providers) - { - } - void add_service_provider(uint32_t id, e2sm_service_provider service_provider) - { - service_providers.emplace(id, e2sm_service_provider(service_provider)); - } - std::string name; - std::map service_providers; -}; - -} // namespace srsran diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp index 1a64692d1a..81dc9dc9ed 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp @@ -9,6 +9,7 @@ */ #include "e2sm_rc_asn1_packer.h" +#include "e2sm_rc_control_service_impl.h" using namespace asn1::e2ap; using namespace asn1::e2sm_rc; @@ -20,7 +21,13 @@ const std::string e2sm_rc_asn1_packer::func_description = "RAN Control"; const uint32_t e2sm_rc_asn1_packer::ran_func_id = 3; const uint32_t e2sm_rc_asn1_packer::revision = 0; -e2sm_rc_asn1_packer::e2sm_rc_asn1_packer(e2sm_param_provider& rc_provider_) : rc_provider(rc_provider_) {} +e2sm_rc_asn1_packer::e2sm_rc_asn1_packer() {} + +bool e2sm_rc_asn1_packer::add_e2sm_control_service(e2sm_control_service* control_service) +{ + control_services.emplace(control_service->get_style_type(), control_service); + return true; +} e2_sm_action_definition_s e2sm_rc_asn1_packer::handle_packed_e2sm_action_definition(const srsran::byte_buffer& action_definition) @@ -72,31 +79,6 @@ e2sm_rc_asn1_packer::handle_packed_event_trigger_definition(const srsran::byte_b return e2_sm_event_trigger_definition_s(); } -void e2sm_rc_asn1_packer::populate_control_ran_function_description( - e2sm_service_provider& provider, - e2_sm_rc_ran_function_definition_s& ran_function_description) -{ - ran_function_description.ran_function_definition_ctrl_present = true; - for (auto& style_provider : provider.style_providers) { - ran_function_definition_ctrl_item_s ran_function_definition_ctrl_item; - ran_function_definition_ctrl_item.ric_ctrl_style_type = style_provider.first; - ran_function_definition_ctrl_item.ric_ctrl_style_name.from_string(style_provider.second.name); - for (auto& action_provider : style_provider.second.action_providers) { - ran_function_definition_ctrl_action_item_s ran_function_definition_ctrl_action_item; - ran_function_definition_ctrl_action_item.ric_ctrl_action_id = action_provider.first; - ran_function_definition_ctrl_action_item.ric_ctrl_action_name.from_string(action_provider.second.name); - for (auto& param : action_provider.second.action_params) { - ctrl_action_ran_param_item_s ran_param_item; - ran_param_item.ran_param_id = param.second.id; - ran_param_item.ran_param_name.from_string(param.second.name); - ran_function_definition_ctrl_action_item.ran_ctrl_action_params_list.push_back(ran_param_item); - } - ran_function_definition_ctrl_item.ric_ctrl_action_list.push_back(ran_function_definition_ctrl_action_item); - } - ran_function_description.ran_function_definition_ctrl.ric_ctrl_style_list.push_back( - ran_function_definition_ctrl_item); - } -} asn1::unbounded_octstring e2sm_rc_asn1_packer::pack_ran_function_description() { e2_sm_rc_ran_function_definition_s ran_function_desc; @@ -114,10 +96,18 @@ asn1::unbounded_octstring e2sm_rc_asn1_packer::pack_ran_function_descripti ran_function_desc.ran_function_name.ran_function_e2_sm_o_id.from_string(oid.c_str()); ran_function_desc.ran_function_name.ran_function_description.from_string(func_description.c_str()); ran_function_desc.ext = false; - for (auto& provider : rc_provider.service_providers) { - if (provider.second.name == "Control Service") { - ran_function_desc.ran_function_definition_ctrl_present = true; - populate_control_ran_function_description(provider.second, ran_function_desc); + + for (auto const& x : control_services) { + ran_function_desc.ran_function_definition_ctrl_present = true; + e2sm_rc_control_service_base* control_service = dynamic_cast(x.second); + + if (!control_service) { + continue; + } + + ran_function_definition_ctrl_item_s ran_function_definition_ctrl_item; + if (control_service->fill_ran_function_description(ran_function_definition_ctrl_item)) { + ran_function_desc.ran_function_definition_ctrl.ric_ctrl_style_list.push_back(ran_function_definition_ctrl_item); } } asn1::unbounded_octstring ran_function_description; diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h index 21d2db03ed..73caf22948 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h @@ -10,12 +10,12 @@ #pragma once -#include "../e2sm_param_provider.h" #include "srsran/adt/byte_buffer.h" #include "srsran/asn1/asn1_utils.h" #include "srsran/asn1/e2ap/e2ap.h" #include "srsran/asn1/e2ap/e2sm_rc.h" #include "srsran/e2/e2sm/e2sm.h" +#include namespace srsran { @@ -27,7 +27,7 @@ class e2sm_rc_asn1_packer : public e2sm_handler static const std::string func_description; static const uint32_t ran_func_id; static const uint32_t revision; - e2sm_rc_asn1_packer(e2sm_param_provider& rc_provider); + e2sm_rc_asn1_packer(); /// Receive populated ASN1 struct that needs to be unpacked and forwarded. e2_sm_action_definition_s handle_packed_e2sm_action_definition(const srsran::byte_buffer& action_definition) override; e2_sm_ric_control_request_s handle_packed_ric_control_request(const asn1::e2ap::ri_cctrl_request_s& req) override; @@ -37,10 +37,9 @@ class e2sm_rc_asn1_packer : public e2sm_handler asn1::unbounded_octstring pack_ran_function_description() override; + bool add_e2sm_control_service(e2sm_control_service* control_service); + private: - void populate_control_ran_function_description( - e2sm_service_provider& provider, - asn1::e2sm_rc::e2_sm_rc_ran_function_definition_s& ran_function_description); - e2sm_param_provider& rc_provider; + std::map control_services; }; } // namespace srsran diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp index b0d3d7da98..f1919929eb 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp @@ -15,8 +15,9 @@ using namespace asn1::e2sm_rc; using namespace srsran; e2sm_rc_control_action_du_executor_base::e2sm_rc_control_action_du_executor_base( - e2sm_param_configurator& param_configurator_) : - logger(srslog::fetch_basic_logger("E2SM-RC")), param_configurator(param_configurator_) + e2sm_param_configurator& param_configurator_, + uint32_t action_id_) : + logger(srslog::fetch_basic_logger("E2SM-RC")), action_id(action_id_), param_configurator(param_configurator_) { } @@ -25,13 +26,28 @@ uint32_t e2sm_rc_control_action_du_executor_base::get_action_id() return action_id; } +bool e2sm_rc_control_action_du_executor_base::fill_ran_function_description( + asn1::e2sm_rc::ran_function_definition_ctrl_action_item_s& action_item) +{ + action_item.ric_ctrl_action_id = action_id; + action_item.ric_ctrl_action_name.from_string(action_name); + + for (auto& ran_p : action_params) { + ctrl_action_ran_param_item_s ctrl_action_ran_param_item; + ctrl_action_ran_param_item.ran_param_id = ran_p.first; + ctrl_action_ran_param_item.ran_param_name.from_string(ran_p.second); + action_item.ran_ctrl_action_params_list.push_back(ctrl_action_ran_param_item); + } + + return true; +} + e2sm_rc_control_action_2_6_du_executor::e2sm_rc_control_action_2_6_du_executor( e2sm_param_configurator& param_configurator_) : - e2sm_rc_control_action_du_executor_base(param_configurator_) + e2sm_rc_control_action_du_executor_base(param_configurator_, 6) { // Control Action description: // To control the radio resource management policy for slice-specific PRB quota allocation - action_id = 6; action_name = "Slice-level PRB quota"; action_params.insert({1, "RRM Policy Ratio List"}); action_params.insert({2, "RRM Policy Ratio Group"}); diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h index 7e4ca50500..6e9f2dd45f 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h @@ -21,9 +21,12 @@ namespace srsran { class e2sm_rc_control_action_du_executor_base : public e2sm_control_action_executor { public: - e2sm_rc_control_action_du_executor_base(e2sm_param_configurator& param_configurator_); + e2sm_rc_control_action_du_executor_base() = delete; + e2sm_rc_control_action_du_executor_base(e2sm_param_configurator& param_configurator_, uint32_t action_id_); virtual ~e2sm_rc_control_action_du_executor_base() = default; + bool fill_ran_function_description(asn1::e2sm_rc::ran_function_definition_ctrl_action_item_s& action_item); + /// e2sm_control_request_executor functions. uint32_t get_action_id() override; bool ric_control_action_supported(const e2_sm_ric_control_request_s& req) override = 0; diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp index 73358fe4e2..8889c4a1f7 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp @@ -9,6 +9,7 @@ */ #include "e2sm_rc_control_service_impl.h" +#include "e2sm_rc_control_action_du_executor.h" #include using namespace asn1::e2ap; @@ -23,6 +24,44 @@ e2sm_rc_control_service_base::e2sm_rc_control_service_base(uint32_t style_id_) : } } +bool e2sm_rc_control_service_base::fill_ran_function_description( + asn1::e2sm_rc::ran_function_definition_ctrl_item_s& ctrl_item) +{ + ctrl_item.ric_call_process_id_format_type_present = false; + ctrl_item.ric_ctrl_style_type = style_id; + ctrl_item.ric_ctrl_style_name.from_string(control_service_def.style_name); + + ctrl_item.ric_ctrl_hdr_format_type = control_service_def.ctrl_hdr_format; + ctrl_item.ric_ctrl_msg_format_type = control_service_def.ctrl_msg_format; + if (control_service_def.call_process_id_format) { + ctrl_item.ric_call_process_id_format_type_present = true; + ctrl_item.ric_call_process_id_format_type = control_service_def.call_process_id_format; + } + ctrl_item.ric_ctrl_outcome_format_type = control_service_def.ctrl_outcome_format; + + for (auto const& x : config_req_executors) { + e2sm_rc_control_action_du_executor_base* action_executor = + dynamic_cast(x.second.get()); + + if (!action_executor) { + continue; + } + + ran_function_definition_ctrl_action_item_s ran_function_definition_ctrl_action_item; + if (action_executor->fill_ran_function_description(ran_function_definition_ctrl_action_item)) { + ctrl_item.ric_ctrl_action_list.push_back(ran_function_definition_ctrl_action_item); + }; + + // TODO: fill outcome properly + ctrl_outcome_ran_param_item_s ctrl_outcome_ran_param_item; + ctrl_outcome_ran_param_item.ran_param_id = 1; + ctrl_outcome_ran_param_item.ran_param_name.from_string("test_outcome_ran_param"); + ctrl_item.ran_ctrl_outcome_params_list.push_back(ctrl_outcome_ran_param_item); + } + + return true; +} + uint32_t e2sm_rc_control_service_base::get_style_type() { return style_id; diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h index 43d316ebec..61fdb77ea1 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h @@ -60,6 +60,8 @@ class e2sm_rc_control_service_base : public e2sm_control_service e2sm_rc_control_service_base(uint32_t style_id_); virtual ~e2sm_rc_control_service_base() = default; + bool fill_ran_function_description(asn1::e2sm_rc::ran_function_definition_ctrl_item_s& ctrl_item); + /// e2sm_control_service functions. uint32_t get_style_type() override; bool add_e2sm_rc_control_action_executor(std::unique_ptr ctrl_act_executor) override; diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.cpp index 38287f5c4f..3343c92107 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.cpp @@ -18,11 +18,8 @@ using namespace asn1::e2ap; using namespace asn1::e2sm_rc; using namespace srsran; -e2sm_rc_impl::e2sm_rc_impl(srslog::basic_logger& logger_, - e2sm_handler& e2sm_packer_, - e2sm_param_configurator& param_configurator_, - e2sm_param_provider& param_interface_) : - logger(logger_), e2sm_packer(e2sm_packer_), param_configurator(param_configurator_), param_interface(param_interface_) +e2sm_rc_impl::e2sm_rc_impl(srslog::basic_logger& logger_, e2sm_handler& e2sm_packer_) : + logger(logger_), e2sm_packer(e2sm_packer_) { } diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.h index 76ceaa8018..3fb074a69c 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.h +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.h @@ -10,7 +10,6 @@ #pragma once -#include "../e2sm_param_provider.h" #include "srsran/asn1/asn1_utils.h" #include "srsran/asn1/e2ap/e2sm_rc.h" #include "srsran/e2/e2.h" @@ -22,10 +21,7 @@ namespace srsran { class e2sm_rc_impl : public e2sm_interface { public: - e2sm_rc_impl(srslog::basic_logger& logger_, - e2sm_handler& e2sm_packer_, - e2sm_param_configurator& param_configurator_, - e2sm_param_provider& param_interface_); + e2sm_rc_impl(srslog::basic_logger& logger_, e2sm_handler& e2sm_packer_); e2sm_handler& get_e2sm_packer() override; @@ -39,8 +35,6 @@ class e2sm_rc_impl : public e2sm_interface private: srslog::basic_logger& logger; e2sm_handler& e2sm_packer; - e2sm_param_configurator& param_configurator; - e2sm_param_provider& param_interface; std::map> control_services; }; } // namespace srsran diff --git a/lib/e2/procedures/e2_ric_control_procedure.h b/lib/e2/procedures/e2_ric_control_procedure.h index dbee6dca81..841febe0aa 100644 --- a/lib/e2/procedures/e2_ric_control_procedure.h +++ b/lib/e2/procedures/e2_ric_control_procedure.h @@ -10,7 +10,6 @@ #pragma once #include "../common/e2ap_asn1_utils.h" -#include "../e2sm/e2sm_param_provider.h" #include "srsran/asn1/e2ap/e2ap.h" #include "srsran/asn1/e2ap/e2sm_rc.h" #include "srsran/e2/e2.h" diff --git a/tests/unittests/e2/common/e2_test_helpers.h b/tests/unittests/e2/common/e2_test_helpers.h index 31273c3ebc..4a25abe908 100644 --- a/tests/unittests/e2/common/e2_test_helpers.h +++ b/tests/unittests/e2/common/e2_test_helpers.h @@ -14,7 +14,6 @@ #include "lib/e2/common/e2ap_asn1_packer.h" #include "lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.h" #include "lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.h" -#include "lib/e2/e2sm/e2sm_param_provider.h" #include "lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h" #include "lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h" #include "lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h" @@ -772,8 +771,7 @@ class e2_test_base : public ::testing::Test std::unique_ptr e2sm_rc_control_service_style2; std::unique_ptr rc_control_action_2_6_executor; std::unique_ptr e2sm_kpm_packer; - std::unique_ptr e2sm_rc_packer; - std::unique_ptr rc_provider; + std::unique_ptr e2sm_rc_packer; std::unique_ptr rc_param_configurator; std::unique_ptr e2_subscription_mngr; std::unique_ptr du_metrics; @@ -915,19 +913,19 @@ class e2_test_setup : public e2_test_base cfg = srsran::config_helpers::make_default_e2ap_config(); cfg.e2sm_kpm_enabled = true; - factory = timer_factory{timers, task_worker}; - msg_notifier = std::make_unique(nullptr); - du_metrics = std::make_unique(); - du_meas_provider = std::make_unique(); - e2sm_kpm_packer = std::make_unique(*du_meas_provider); - e2sm_kpm_iface = std::make_unique(test_logger, *e2sm_kpm_packer, *du_meas_provider); - rc_provider = std::make_unique(); - e2sm_rc_packer = std::make_unique(*rc_provider); - rc_param_configurator = std::make_unique(); - e2sm_rc_iface = std::make_unique(test_logger, *e2sm_rc_packer, *rc_param_configurator, *rc_provider); + factory = timer_factory{timers, task_worker}; + msg_notifier = std::make_unique(nullptr); + du_metrics = std::make_unique(); + du_meas_provider = std::make_unique(); + e2sm_kpm_packer = std::make_unique(*du_meas_provider); + e2sm_kpm_iface = std::make_unique(test_logger, *e2sm_kpm_packer, *du_meas_provider); + e2sm_rc_packer = std::make_unique(); + rc_param_configurator = std::make_unique(); + e2sm_rc_iface = std::make_unique(test_logger, *e2sm_rc_packer); e2sm_rc_control_service_style2 = std::make_unique(2); rc_control_action_2_6_executor = std::make_unique(*rc_param_configurator); e2sm_rc_control_service_style2->add_e2sm_rc_control_action_executor(std::move(rc_control_action_2_6_executor)); + e2sm_rc_packer->add_e2sm_control_service(e2sm_rc_control_service_style2.get()); e2sm_rc_iface->add_e2sm_control_service(std::move(e2sm_rc_control_service_style2)); e2sm_mngr = std::make_unique(test_logger); e2sm_mngr->add_e2sm_service("1.3.6.1.4.1.53148.1.2.2.2", std::move(e2sm_kpm_iface)); diff --git a/tests/unittests/e2/e2_setup_procedure_test.cpp b/tests/unittests/e2/e2_setup_procedure_test.cpp index e05ca38878..0c5a746a45 100644 --- a/tests/unittests/e2/e2_setup_procedure_test.cpp +++ b/tests/unittests/e2/e2_setup_procedure_test.cpp @@ -200,12 +200,12 @@ TEST_F(e2_test_setup, e2_sends_correct_rc_ran_function_definition) "Slice-level PRB quota"); ASSERT_EQ(ran_func_def.ran_function_definition_ctrl.ric_ctrl_style_list[0] .ric_ctrl_action_list[0] - .ran_ctrl_action_params_list[0] + .ran_ctrl_action_params_list[9] .ran_param_id, - 10); + 11); ASSERT_EQ(ran_func_def.ran_function_definition_ctrl.ric_ctrl_style_list[0] .ric_ctrl_action_list[0] - .ran_ctrl_action_params_list[0] + .ran_ctrl_action_params_list[9] .ran_param_name.to_string(), "Min PRB Policy Ratio"); From bfefff3d631c75ceb599da59f79a38ab3d9cab54 Mon Sep 17 00:00:00 2001 From: Piotr Gawlowicz Date: Thu, 23 Nov 2023 10:53:28 +0100 Subject: [PATCH 010/134] e2sm_rc: simplify ric_control_procedure execution --- include/srsran/e2/e2sm/e2sm.h | 4 +-- lib/e2/common/e2_impl.cpp | 3 +- lib/e2/common/e2_impl.h | 1 + .../e2sm_rc_control_action_du_executor.cpp | 36 ++++++++++++++----- .../e2sm_rc_control_action_du_executor.h | 12 ++++--- .../e2sm_rc/e2sm_rc_control_service_impl.cpp | 10 ++---- .../e2sm_rc/e2sm_rc_control_service_impl.h | 13 ++++--- .../procedures/e2_ric_control_procedure.cpp | 32 ++++++++--------- lib/e2/procedures/e2_ric_control_procedure.h | 15 +++----- 9 files changed, 68 insertions(+), 58 deletions(-) diff --git a/include/srsran/e2/e2sm/e2sm.h b/include/srsran/e2/e2sm/e2sm.h index ae7e76ec7f..f9513eab39 100644 --- a/include/srsran/e2/e2sm/e2sm.h +++ b/include/srsran/e2/e2sm/e2sm.h @@ -59,7 +59,7 @@ class e2sm_control_action_executor /// \brief trigger execution of the RIC control action. /// \param[in] req is a RIC control action request (with control header and message). /// \return Returns RIC control response. - virtual async_task execute_ric_control_action(const e2_sm_ric_control_request_s& req) = 0; + virtual e2_ric_control_response execute_ric_control_action(const e2_sm_ric_control_request_s& req) = 0; }; class e2sm_report_service @@ -98,7 +98,7 @@ class e2sm_control_service /// \brief trigger execution of the RIC control action. /// \param[in] req is a RIC control action request (with control header and message). /// \return Returns RIC control response. - virtual async_task execute_control_request(const e2_sm_ric_control_request_s& req) = 0; + virtual e2_ric_control_response execute_control_request(const e2_sm_ric_control_request_s& req) = 0; }; class e2sm_handler diff --git a/lib/e2/common/e2_impl.cpp b/lib/e2/common/e2_impl.cpp index 65a806ca47..2df5593d5c 100644 --- a/lib/e2/common/e2_impl.cpp +++ b/lib/e2/common/e2_impl.cpp @@ -32,6 +32,7 @@ e2_impl::e2_impl(e2ap_configuration& cfg_, e2sm_mngr(e2sm_mngr_), subscribe_proc(e2_pdu_notifier_, subscription_mngr_, timers, logger), subscribe_delete_proc(e2_pdu_notifier_, subscription_mngr_, timers, logger), + ric_control_proc(pdu_notifier, e2sm_mngr, logger), events(std::make_unique(timers)), async_tasks(10) { @@ -110,7 +111,7 @@ void e2_impl::handle_ric_control_request(const asn1::e2ap::ri_cctrl_request_s ms logger.info("Received RIC Control Request"); e2_ric_control_request request; request.request = msg; - async_tasks.schedule(request, pdu_notifier, e2sm_mngr, logger); + ric_control_proc.run_e2_ric_control_procedure(request); } void e2_impl::handle_e2_setup_failure(const e2_setup_response_message& msg) diff --git a/lib/e2/common/e2_impl.h b/lib/e2/common/e2_impl.h index ad3cd087c3..250d665393 100644 --- a/lib/e2/common/e2_impl.h +++ b/lib/e2/common/e2_impl.h @@ -102,6 +102,7 @@ class e2_impl final : public e2_interface e2sm_manager& e2sm_mngr; e2_subscription_setup_procedure subscribe_proc; e2_subscription_delete_procedure subscribe_delete_proc; + e2_ric_control_procedure ric_control_proc; std::unique_ptr events; fifo_async_task_scheduler async_tasks; unsigned current_transaction_id = 0; // store current E2AP transaction id diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp index f1919929eb..804d008e41 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp @@ -9,6 +9,7 @@ */ #include "e2sm_rc_control_action_du_executor.h" +#include using namespace asn1::e2ap; using namespace asn1::e2sm_rc; @@ -17,7 +18,10 @@ using namespace srsran; e2sm_rc_control_action_du_executor_base::e2sm_rc_control_action_du_executor_base( e2sm_param_configurator& param_configurator_, uint32_t action_id_) : - logger(srslog::fetch_basic_logger("E2SM-RC")), action_id(action_id_), param_configurator(param_configurator_) + logger(srslog::fetch_basic_logger("E2SM-RC")), + action_id(action_id_), + param_configurator(param_configurator_), + async_tasks(10) { } @@ -77,9 +81,10 @@ bool e2sm_rc_control_action_2_6_du_executor::ric_control_action_supported(const return true; }; -async_task +e2_ric_control_response e2sm_rc_control_action_2_6_du_executor::execute_ric_control_action(const e2_sm_ric_control_request_s& req) { + e2_ric_control_response e2_resp; const e2_sm_rc_ctrl_hdr_format1_s& ctrl_hdr = variant_get(req.request_ctrl_hdr).ric_ctrl_hdr_formats.ctrl_hdr_format1(); const e2_sm_rc_ctrl_msg_format1_s& ctrl_msg = @@ -99,13 +104,26 @@ e2sm_rc_control_action_2_6_du_executor::execute_ric_control_action(const e2_sm_r } } - return launch_async([this](coro_context>& ctx) { + std::promise p; + std::future fut = p.get_future(); + ric_control_config_response ctrl_response; + + async_tasks.schedule([this, &p, &ctrl_response](coro_context>& ctx) { CORO_BEGIN(ctx); - ric_control_config_response ctrl_response; + CORO_AWAIT_VALUE(ctrl_response, param_configurator.configure_ue_mac_scheduler(ctrl_config)); - e2_ric_control_response e2_resp; - e2_resp.success = ctrl_response.harq_processes_result and ctrl_response.max_prb_alloc_result and - ctrl_response.min_prb_alloc_result; - CORO_RETURN(e2_resp); + + // Signal caller thread that the operation is complete. + p.set_value(); + + CORO_RETURN(); }); -}; \ No newline at end of file + + // Block waiting for reconfiguration to complete. + fut.wait(); + + e2_resp.success = + ctrl_response.harq_processes_result and ctrl_response.max_prb_alloc_result and ctrl_response.min_prb_alloc_result; + + return e2_resp; +}; diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h index 6e9f2dd45f..9a3e7fce81 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h @@ -14,6 +14,7 @@ #include "srsran/asn1/asn1_utils.h" #include "srsran/e2/e2.h" #include "srsran/e2/e2sm/e2sm.h" +#include "srsran/support/async/fifo_async_task_scheduler.h" #include namespace srsran { @@ -28,9 +29,9 @@ class e2sm_rc_control_action_du_executor_base : public e2sm_control_action_execu bool fill_ran_function_description(asn1::e2sm_rc::ran_function_definition_ctrl_action_item_s& action_item); /// e2sm_control_request_executor functions. - uint32_t get_action_id() override; - bool ric_control_action_supported(const e2_sm_ric_control_request_s& req) override = 0; - async_task execute_ric_control_action(const e2_sm_ric_control_request_s& req) override = 0; + uint32_t get_action_id() override; + bool ric_control_action_supported(const e2_sm_ric_control_request_s& req) override = 0; + e2_ric_control_response execute_ric_control_action(const e2_sm_ric_control_request_s& req) override = 0; protected: srslog::basic_logger& logger; @@ -38,6 +39,7 @@ class e2sm_rc_control_action_du_executor_base : public e2sm_control_action_execu std::string action_name; std::map action_params; e2sm_param_configurator& param_configurator; + fifo_async_task_scheduler async_tasks; }; class e2sm_rc_control_action_2_6_du_executor : public e2sm_rc_control_action_du_executor_base @@ -47,8 +49,8 @@ class e2sm_rc_control_action_2_6_du_executor : public e2sm_rc_control_action_du_ virtual ~e2sm_rc_control_action_2_6_du_executor() = default; /// e2sm_control_request_executor functions. - bool ric_control_action_supported(const e2_sm_ric_control_request_s& req) override; - async_task execute_ric_control_action(const e2_sm_ric_control_request_s& req) override; + bool ric_control_action_supported(const e2_sm_ric_control_request_s& req) override; + e2_ric_control_response execute_ric_control_action(const e2_sm_ric_control_request_s& req) override; // Helper variables. ric_control_config ctrl_config; diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp index 8889c4a1f7..7596213a14 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp @@ -121,8 +121,7 @@ bool e2sm_rc_control_service::control_request_supported(const e2_sm_ric_control_ return true; } -async_task -e2sm_rc_control_service::execute_control_request(const e2_sm_ric_control_request_s& req) +e2_ric_control_response e2sm_rc_control_service::execute_control_request(const e2_sm_ric_control_request_s& req) { const e2_sm_rc_ctrl_hdr_format1_s& ctrl_hdr = variant_get(req.request_ctrl_hdr).ric_ctrl_hdr_formats.ctrl_hdr_format1(); @@ -218,7 +217,7 @@ bool e2sm_rc_control_service_style_255::control_request_supported(const e2_sm_ri return false; } -async_task +e2_ric_control_response e2sm_rc_control_service_style_255::execute_control_request(const e2_sm_ric_control_request_s& req) { e2_ric_control_response aggregated_response; @@ -237,8 +236,5 @@ e2sm_rc_control_service_style_255::execute_control_request(const e2_sm_ric_contr } } - return launch_async([aggregated_response](coro_context>& ctx) { - CORO_BEGIN(ctx); - CORO_RETURN(aggregated_response); - }); + return aggregated_response; } \ No newline at end of file diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h index 61fdb77ea1..20c96da838 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h @@ -65,9 +65,8 @@ class e2sm_rc_control_service_base : public e2sm_control_service /// e2sm_control_service functions. uint32_t get_style_type() override; bool add_e2sm_rc_control_action_executor(std::unique_ptr ctrl_act_executor) override; - bool control_request_supported(const e2_sm_ric_control_request_s& req) override = 0; - virtual async_task - execute_control_request(const e2_sm_ric_control_request_s& req) override = 0; + bool control_request_supported(const e2_sm_ric_control_request_s& req) override = 0; + virtual e2_ric_control_response execute_control_request(const e2_sm_ric_control_request_s& req) override = 0; protected: srslog::basic_logger& logger; @@ -84,8 +83,8 @@ class e2sm_rc_control_service : public e2sm_rc_control_service_base e2sm_rc_control_service(uint32_t style_id_); virtual ~e2sm_rc_control_service() = default; - bool control_request_supported(const e2_sm_ric_control_request_s& req) override; - async_task execute_control_request(const e2_sm_ric_control_request_s& req) override; + bool control_request_supported(const e2_sm_ric_control_request_s& req) override; + e2_ric_control_response execute_control_request(const e2_sm_ric_control_request_s& req) override; }; /// Class for e2sm_rc_control_service style 255 (Multiple actions) @@ -95,8 +94,8 @@ class e2sm_rc_control_service_style_255 : public e2sm_rc_control_service_base e2sm_rc_control_service_style_255(); virtual ~e2sm_rc_control_service_style_255() = default; - bool control_request_supported(const e2_sm_ric_control_request_s& req) override; - async_task execute_control_request(const e2_sm_ric_control_request_s& req) override; + bool control_request_supported(const e2_sm_ric_control_request_s& req) override; + e2_ric_control_response execute_control_request(const e2_sm_ric_control_request_s& req) override; private: // Helper functions. diff --git a/lib/e2/procedures/e2_ric_control_procedure.cpp b/lib/e2/procedures/e2_ric_control_procedure.cpp index d484f3f4b8..e738ee6369 100644 --- a/lib/e2/procedures/e2_ric_control_procedure.cpp +++ b/lib/e2/procedures/e2_ric_control_procedure.cpp @@ -14,18 +14,18 @@ using namespace srsran; using namespace asn1::e2ap; using namespace asn1::e2sm_rc; -e2_ric_control_procedure::e2_ric_control_procedure(const e2_ric_control_request& request_, - e2_message_notifier& notif_, - e2sm_manager& e2sm_mng_, - srslog::basic_logger& logger_) : - logger(logger_), ric_notif(notif_), e2sm_mng(e2sm_mng_), request(request_) +e2_ric_control_procedure::e2_ric_control_procedure(e2_message_notifier& notif_, + e2sm_manager& e2sm_mng_, + srslog::basic_logger& logger_) : + logger(logger_), ric_notif(notif_), e2sm_mng(e2sm_mng_) { } -void e2_ric_control_procedure::operator()(coro_context>& ctx) +void e2_ric_control_procedure::run_e2_ric_control_procedure(const e2_ric_control_request& request_) { - ri_cctrl_request_s ctrl_req = request.request; - e2sm_interface* e2sm_iface = e2sm_mng.get_e2sm_interface(ctrl_req->ra_nfunction_id.value); + e2_ric_control_response response; + ri_cctrl_request_s ctrl_req = request_.request; + e2sm_interface* e2sm_iface = e2sm_mng.get_e2sm_interface(ctrl_req->ra_nfunction_id.value); if (!e2sm_iface) { logger.error("RAN function ID not supported"); @@ -46,16 +46,14 @@ void e2_ric_control_procedure::operator()(coro_context>& ctx) return; } - CORO_BEGIN(ctx); - CORO_AWAIT_VALUE(response, control_service->execute_control_request(ric_ctrl_req)); + response = control_service->execute_control_request(ric_ctrl_req); if (ric_ctrl_req.ric_ctrl_ack_request_present and ric_ctrl_req.ric_ctrl_ack_request) { if (response.success) { - send_e2_ric_control_acknowledge(request, response); + send_e2_ric_control_acknowledge(request_, response); } else { - send_e2_ric_control_failure(request, response); + send_e2_ric_control_failure(request_, response); } } - CORO_RETURN(); } void e2_ric_control_procedure::send_e2_ric_control_acknowledge(const e2_ric_control_request& ctrl_request, @@ -66,8 +64,8 @@ void e2_ric_control_procedure::send_e2_ric_control_acknowledge(const e2_ric_cont logger.info("Sending E2 RIC Control Acknowledge"); msg.pdu.successful_outcome().load_info_obj(ASN1_E2AP_ID_RI_CCTRL); ri_cctrl_ack_s& ack = msg.pdu.successful_outcome().value.ri_cctrl_ack(); - ack->ra_nfunction_id = request.request->ra_nfunction_id; - ack->ri_crequest_id = request.request->ri_crequest_id; + ack->ra_nfunction_id = ctrl_request.request->ra_nfunction_id; + ack->ri_crequest_id = ctrl_request.request->ri_crequest_id; ack->ri_ccall_process_id_present = false; ack->ri_cctrl_outcome_present = false; ric_notif.on_new_message(msg); @@ -81,8 +79,8 @@ void e2_ric_control_procedure::send_e2_ric_control_failure(const e2_ric_control_ logger.info("Sending E2 RIC Control Failure"); msg.pdu.unsuccessful_outcome().load_info_obj(ASN1_E2AP_ID_RI_CCTRL); ri_cctrl_fail_s& fail = msg.pdu.unsuccessful_outcome().value.ri_cctrl_fail(); - fail->ra_nfunction_id = request.request->ra_nfunction_id; - fail->ri_crequest_id = request.request->ri_crequest_id; + fail->ra_nfunction_id = ctrl_request.request->ra_nfunction_id; + fail->ri_crequest_id = ctrl_request.request->ri_crequest_id; fail->ri_ccall_process_id_present = false; fail->ri_cctrl_outcome_present = false; fail->cause->set_misc().value = cause_misc_e::options::unspecified; diff --git a/lib/e2/procedures/e2_ric_control_procedure.h b/lib/e2/procedures/e2_ric_control_procedure.h index 841febe0aa..aa158b59d0 100644 --- a/lib/e2/procedures/e2_ric_control_procedure.h +++ b/lib/e2/procedures/e2_ric_control_procedure.h @@ -25,22 +25,17 @@ namespace srsran { class e2_ric_control_procedure { public: - e2_ric_control_procedure(const e2_ric_control_request& request_, - e2_message_notifier& notif_, - e2sm_manager& e2sm_mng_, - srslog::basic_logger& logger); + e2_ric_control_procedure(e2_message_notifier& notif_, e2sm_manager& e2sm_mng_, srslog::basic_logger& logger); - void operator()(coro_context>& ctx); + void run_e2_ric_control_procedure(const e2_ric_control_request& request); void send_e2_ric_control_acknowledge(const e2_ric_control_request& ctrl_request, const e2_ric_control_response& ctrl_response); void send_e2_ric_control_failure(const e2_ric_control_request&, const e2_ric_control_response& ctrl_response); private: - srslog::basic_logger& logger; - e2_message_notifier& ric_notif; - e2sm_manager& e2sm_mng; - const e2_ric_control_request request; - e2_ric_control_response response; + srslog::basic_logger& logger; + e2_message_notifier& ric_notif; + e2sm_manager& e2sm_mng; }; } // namespace srsran \ No newline at end of file From 924141a2e5138b661e6f93f01c3d793904a00623 Mon Sep 17 00:00:00 2001 From: Piotr Gawlowicz Date: Thu, 23 Nov 2023 11:03:56 +0100 Subject: [PATCH 011/134] e2sm_rc: add multiple action execution in control style 255 --- lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp index 7596213a14..4aa1b1b02b 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp @@ -232,7 +232,11 @@ e2sm_rc_control_service_style_255::execute_control_request(const e2_sm_ric_contr for (auto& action : style.ric_ctrl_action_list) { // Create a control request with format 1 to match the API of control service styles 1-10. e2_sm_ric_control_request_s tmp_req = create_req_f1_from_req_f2(ctrl_hdr_f2, style, action); - // TODO: execute all actions and aggregate the response + e2_ric_control_response tmp_response; + tmp_response = config_req_executors[action.ric_ctrl_action_id]->execute_ric_control_action(tmp_req); + + // Aggregate RIC control action response. + aggregated_response.success &= tmp_response.success; } } From a907baadda227ae6a8b63c73514b4bb59961a516 Mon Sep 17 00:00:00 2001 From: Piotr Gawlowicz Date: Thu, 23 Nov 2023 12:35:18 +0100 Subject: [PATCH 012/134] e2: add e2_sm_ric_control_response_s that is filled by a control service module --- include/srsran/e2/e2sm/e2sm.h | 24 +++++++-- lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.cpp | 8 +++ lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.h | 1 + lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp | 35 +++++++++++++ lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h | 1 + .../e2sm_rc_control_action_du_executor.cpp | 33 ++++++++++++- .../e2sm_rc_control_action_du_executor.h | 10 ++-- .../e2sm_rc/e2sm_rc_control_service_impl.cpp | 10 ++-- .../e2sm_rc/e2sm_rc_control_service_impl.h | 14 +++--- .../procedures/e2_ric_control_procedure.cpp | 49 +++++++++++++------ tests/unittests/e2/common/e2_test_helpers.h | 5 ++ 11 files changed, 150 insertions(+), 40 deletions(-) diff --git a/include/srsran/e2/e2sm/e2sm.h b/include/srsran/e2/e2sm/e2sm.h index f9513eab39..6d8d06ea14 100644 --- a/include/srsran/e2/e2sm/e2sm.h +++ b/include/srsran/e2/e2sm/e2sm.h @@ -44,6 +44,16 @@ struct e2_sm_ric_control_request_s { bool ric_ctrl_ack_request; }; +struct e2_sm_ric_control_response_s { + e2sm_service_model_t service_model; + bool success; + bool ric_call_process_id_present = false; + bool ric_ctrl_outcome_present = false; + uint64_t ric_call_process_id; + variant ric_ctrl_outcome; + asn1::e2ap::cause_c cause; +}; + /// RIC control action executor maps an control action request to the proper stack functions. class e2sm_control_action_executor { @@ -59,7 +69,7 @@ class e2sm_control_action_executor /// \brief trigger execution of the RIC control action. /// \param[in] req is a RIC control action request (with control header and message). /// \return Returns RIC control response. - virtual e2_ric_control_response execute_ric_control_action(const e2_sm_ric_control_request_s& req) = 0; + virtual e2_sm_ric_control_response_s execute_ric_control_action(const e2_sm_ric_control_request_s& req) = 0; }; class e2sm_report_service @@ -98,7 +108,7 @@ class e2sm_control_service /// \brief trigger execution of the RIC control action. /// \param[in] req is a RIC control action request (with control header and message). /// \return Returns RIC control response. - virtual e2_ric_control_response execute_control_request(const e2_sm_ric_control_request_s& req) = 0; + virtual e2_sm_ric_control_response_s execute_control_request(const e2_sm_ric_control_request_s& req) = 0; }; class e2sm_handler @@ -113,10 +123,14 @@ class e2sm_handler /// \param[in] buf /// \return Returns the E2SM Event Trigger Definition. virtual e2_sm_event_trigger_definition_s handle_packed_event_trigger_definition(const srsran::byte_buffer& buf) = 0; - /// \brief Handle the packed E2SM Event Trigger Definition. - /// \param[in] buf - /// \return Returns the E2SM Event Trigger Definition. + /// \brief Handle the packed E2 RIC Control Request. + /// \param[in] req E2 RIC Control Request. + /// \return Returns the unpacked E2SM RIC Control Request. virtual e2_sm_ric_control_request_s handle_packed_ric_control_request(const asn1::e2ap::ri_cctrl_request_s& req) = 0; + /// \brief Pack the E2SM RIC Control Response. + /// \param[in] response E2SM RIC Control Response. + /// \return Returns the packed E2 RIC Control Response. + virtual e2_ric_control_response pack_ric_control_response(const e2_sm_ric_control_response_s& e2sm_response) = 0; /// @brief Pack the RAN function description. virtual asn1::unbounded_octstring pack_ran_function_description() = 0; }; 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 2d803b9474..d652a2965b 100644 --- a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.cpp +++ b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.cpp @@ -41,6 +41,14 @@ e2sm_kpm_asn1_packer::handle_packed_ric_control_request(const asn1::e2ap::ri_cct return control_request; } +e2_ric_control_response +e2sm_kpm_asn1_packer::pack_ric_control_response(const e2_sm_ric_control_response_s& e2sm_response) +{ + printf("Failure - RIC control not available in e2sm_kpm.\n"); + e2_ric_control_response control_response = {}; + return control_response; +} + e2_sm_event_trigger_definition_s e2sm_kpm_asn1_packer::handle_packed_event_trigger_definition(const srsran::byte_buffer& event_trigger_definition) { diff --git a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.h b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.h index 1cea2f7150..a9a62fdef3 100644 --- a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.h +++ b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.h @@ -33,6 +33,7 @@ class e2sm_kpm_asn1_packer : public e2sm_handler /// Receive populated ASN1 struct that needs to be unpacked and forwarded. e2_sm_action_definition_s handle_packed_e2sm_action_definition(const srsran::byte_buffer& action_definition) override; e2_sm_ric_control_request_s handle_packed_ric_control_request(const asn1::e2ap::ri_cctrl_request_s& req) override; + e2_ric_control_response pack_ric_control_response(const e2_sm_ric_control_response_s& e2sm_response) override; e2_sm_event_trigger_definition_s handle_packed_event_trigger_definition(const srsran::byte_buffer& event_trigger_definition) override; diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp index 81dc9dc9ed..f6d4d8a30c 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp @@ -72,6 +72,41 @@ e2sm_rc_asn1_packer::handle_packed_ric_control_request(const asn1::e2ap::ri_cctr return ric_control_request; }; +e2_ric_control_response +e2sm_rc_asn1_packer::pack_ric_control_response(const e2_sm_ric_control_response_s& e2sm_response) +{ + e2_ric_control_response e2_control_response = {}; + + e2_control_response.success = e2sm_response.success; + + if (e2_control_response.success) { + if (e2sm_response.ric_ctrl_outcome_present) { + e2_control_response.ack->ri_cctrl_outcome_present = true; + srsran::byte_buffer buf; + asn1::bit_ref bref(buf); + if (variant_get(e2sm_response.ric_ctrl_outcome).pack(bref) != asn1::SRSASN_SUCCESS) { + printf("Failed to pack E2SM RC RIC Control Outcome (Ack)\n"); + } + e2_control_response.ack->ri_cctrl_outcome->resize(buf.length()); + std::copy(buf.begin(), buf.end(), e2_control_response.ack->ri_cctrl_outcome->begin()); + } + } else { + if (e2sm_response.ric_ctrl_outcome_present) { + e2_control_response.failure->ri_cctrl_outcome_present = true; + srsran::byte_buffer buf; + asn1::bit_ref bref(buf); + if (variant_get(e2sm_response.ric_ctrl_outcome).pack(bref) != asn1::SRSASN_SUCCESS) { + printf("Failed to pack E2SM RC RIC Control Outcome (Failure)\n"); + } + e2_control_response.failure->ri_cctrl_outcome->resize(buf.length()); + std::copy(buf.begin(), buf.end(), e2_control_response.failure->ri_cctrl_outcome->begin()); + } + e2_control_response.failure->cause.value = e2sm_response.cause; + } + + return e2_control_response; +} + e2_sm_event_trigger_definition_s e2sm_rc_asn1_packer::handle_packed_event_trigger_definition(const srsran::byte_buffer& event_trigger_definition) { diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h index 73caf22948..7e9dd54310 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h @@ -31,6 +31,7 @@ class e2sm_rc_asn1_packer : public e2sm_handler /// Receive populated ASN1 struct that needs to be unpacked and forwarded. e2_sm_action_definition_s handle_packed_e2sm_action_definition(const srsran::byte_buffer& action_definition) override; e2_sm_ric_control_request_s handle_packed_ric_control_request(const asn1::e2ap::ri_cctrl_request_s& req) override; + e2_ric_control_response pack_ric_control_response(const e2_sm_ric_control_response_s& e2sm_response) override; e2_sm_event_trigger_definition_s handle_packed_event_trigger_definition(const srsran::byte_buffer& event_trigger_definition) override; diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp index 804d008e41..c93eba586a 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp @@ -81,10 +81,10 @@ bool e2sm_rc_control_action_2_6_du_executor::ric_control_action_supported(const return true; }; -e2_ric_control_response +e2_sm_ric_control_response_s e2sm_rc_control_action_2_6_du_executor::execute_ric_control_action(const e2_sm_ric_control_request_s& req) { - e2_ric_control_response e2_resp; + e2_sm_ric_control_response_s e2_resp; const e2_sm_rc_ctrl_hdr_format1_s& ctrl_hdr = variant_get(req.request_ctrl_hdr).ric_ctrl_hdr_formats.ctrl_hdr_format1(); const e2_sm_rc_ctrl_msg_format1_s& ctrl_msg = @@ -125,5 +125,34 @@ e2sm_rc_control_action_2_6_du_executor::execute_ric_control_action(const e2_sm_r e2_resp.success = ctrl_response.harq_processes_result and ctrl_response.max_prb_alloc_result and ctrl_response.min_prb_alloc_result; + // Always fill outcome here, it will be decided later whether it should be included in the e2 response. + e2_resp.ric_ctrl_outcome_present = true; + e2_sm_rc_ctrl_outcome_format1_s& ctrl_outcome = variant_get(e2_resp.ric_ctrl_outcome) + .ric_ctrl_outcome_formats.set_ctrl_outcome_format1(); + + // TODO: fill outcome properly + e2_sm_rc_ctrl_outcome_format1_item_s test_outcome; + test_outcome.ran_param_id = 1; + test_outcome.ran_param_value.set_value_int() = 100; + ctrl_outcome.ran_p_list.push_back(test_outcome); + + if (ctrl_config.min_prb_alloc.has_value()) { + e2_sm_rc_ctrl_outcome_format1_item_s min_prb_outcome; + min_prb_outcome.ran_param_id = 11; + min_prb_outcome.ran_param_value.set_value_int() = ctrl_config.min_prb_alloc.value(); + ctrl_outcome.ran_p_list.push_back(min_prb_outcome); + } + + if (ctrl_config.max_prb_alloc.has_value()) { + e2_sm_rc_ctrl_outcome_format1_item_s max_prb_outcome; + max_prb_outcome.ran_param_id = 12; + max_prb_outcome.ran_param_value.set_value_int() = ctrl_config.max_prb_alloc.value(); + ctrl_outcome.ran_p_list.push_back(max_prb_outcome); + } + + if (!e2_resp.success) { + e2_resp.cause.set_misc().value = cause_misc_e::options::unspecified; + } + return e2_resp; }; diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h index 9a3e7fce81..1b6a3568e9 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h @@ -29,9 +29,9 @@ class e2sm_rc_control_action_du_executor_base : public e2sm_control_action_execu bool fill_ran_function_description(asn1::e2sm_rc::ran_function_definition_ctrl_action_item_s& action_item); /// e2sm_control_request_executor functions. - uint32_t get_action_id() override; - bool ric_control_action_supported(const e2_sm_ric_control_request_s& req) override = 0; - e2_ric_control_response execute_ric_control_action(const e2_sm_ric_control_request_s& req) override = 0; + uint32_t get_action_id() override; + bool ric_control_action_supported(const e2_sm_ric_control_request_s& req) override = 0; + e2_sm_ric_control_response_s execute_ric_control_action(const e2_sm_ric_control_request_s& req) override = 0; protected: srslog::basic_logger& logger; @@ -49,8 +49,8 @@ class e2sm_rc_control_action_2_6_du_executor : public e2sm_rc_control_action_du_ virtual ~e2sm_rc_control_action_2_6_du_executor() = default; /// e2sm_control_request_executor functions. - bool ric_control_action_supported(const e2_sm_ric_control_request_s& req) override; - e2_ric_control_response execute_ric_control_action(const e2_sm_ric_control_request_s& req) override; + bool ric_control_action_supported(const e2_sm_ric_control_request_s& req) override; + e2_sm_ric_control_response_s execute_ric_control_action(const e2_sm_ric_control_request_s& req) override; // Helper variables. ric_control_config ctrl_config; diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp index 4aa1b1b02b..0645ea4eb2 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp @@ -121,7 +121,7 @@ bool e2sm_rc_control_service::control_request_supported(const e2_sm_ric_control_ return true; } -e2_ric_control_response e2sm_rc_control_service::execute_control_request(const e2_sm_ric_control_request_s& req) +e2_sm_ric_control_response_s e2sm_rc_control_service::execute_control_request(const e2_sm_ric_control_request_s& req) { const e2_sm_rc_ctrl_hdr_format1_s& ctrl_hdr = variant_get(req.request_ctrl_hdr).ric_ctrl_hdr_formats.ctrl_hdr_format1(); @@ -217,10 +217,10 @@ bool e2sm_rc_control_service_style_255::control_request_supported(const e2_sm_ri return false; } -e2_ric_control_response +e2_sm_ric_control_response_s e2sm_rc_control_service_style_255::execute_control_request(const e2_sm_ric_control_request_s& req) { - e2_ric_control_response aggregated_response; + e2_sm_ric_control_response_s aggregated_response; aggregated_response.success = false; const e2_sm_rc_ctrl_hdr_format2_s& ctrl_hdr_f2 = @@ -231,8 +231,8 @@ e2sm_rc_control_service_style_255::execute_control_request(const e2_sm_ric_contr for (auto& style : ctrl_msg_f2.ric_ctrl_style_list) { for (auto& action : style.ric_ctrl_action_list) { // Create a control request with format 1 to match the API of control service styles 1-10. - e2_sm_ric_control_request_s tmp_req = create_req_f1_from_req_f2(ctrl_hdr_f2, style, action); - e2_ric_control_response tmp_response; + e2_sm_ric_control_request_s tmp_req = create_req_f1_from_req_f2(ctrl_hdr_f2, style, action); + e2_sm_ric_control_response_s tmp_response; tmp_response = config_req_executors[action.ric_ctrl_action_id]->execute_ric_control_action(tmp_req); // Aggregate RIC control action response. diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h index 20c96da838..28804ff5c4 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h @@ -65,8 +65,8 @@ class e2sm_rc_control_service_base : public e2sm_control_service /// e2sm_control_service functions. uint32_t get_style_type() override; bool add_e2sm_rc_control_action_executor(std::unique_ptr ctrl_act_executor) override; - bool control_request_supported(const e2_sm_ric_control_request_s& req) override = 0; - virtual e2_ric_control_response execute_control_request(const e2_sm_ric_control_request_s& req) override = 0; + bool control_request_supported(const e2_sm_ric_control_request_s& req) override = 0; + virtual e2_sm_ric_control_response_s execute_control_request(const e2_sm_ric_control_request_s& req) override = 0; protected: srslog::basic_logger& logger; @@ -83,8 +83,8 @@ class e2sm_rc_control_service : public e2sm_rc_control_service_base e2sm_rc_control_service(uint32_t style_id_); virtual ~e2sm_rc_control_service() = default; - bool control_request_supported(const e2_sm_ric_control_request_s& req) override; - e2_ric_control_response execute_control_request(const e2_sm_ric_control_request_s& req) override; + bool control_request_supported(const e2_sm_ric_control_request_s& req) override; + e2_sm_ric_control_response_s execute_control_request(const e2_sm_ric_control_request_s& req) override; }; /// Class for e2sm_rc_control_service style 255 (Multiple actions) @@ -94,8 +94,8 @@ class e2sm_rc_control_service_style_255 : public e2sm_rc_control_service_base e2sm_rc_control_service_style_255(); virtual ~e2sm_rc_control_service_style_255() = default; - bool control_request_supported(const e2_sm_ric_control_request_s& req) override; - e2_ric_control_response execute_control_request(const e2_sm_ric_control_request_s& req) override; + bool control_request_supported(const e2_sm_ric_control_request_s& req) override; + e2_sm_ric_control_response_s execute_control_request(const e2_sm_ric_control_request_s& req) override; private: // Helper functions. @@ -107,4 +107,4 @@ class e2sm_rc_control_service_style_255 : public e2sm_rc_control_service_base std::map e2sm_rc_control_services; }; -} // namespace srsran \ No newline at end of file +} // namespace srsran diff --git a/lib/e2/procedures/e2_ric_control_procedure.cpp b/lib/e2/procedures/e2_ric_control_procedure.cpp index e738ee6369..845e29d67a 100644 --- a/lib/e2/procedures/e2_ric_control_procedure.cpp +++ b/lib/e2/procedures/e2_ric_control_procedure.cpp @@ -21,11 +21,12 @@ e2_ric_control_procedure::e2_ric_control_procedure(e2_message_notifier& notif_, { } -void e2_ric_control_procedure::run_e2_ric_control_procedure(const e2_ric_control_request& request_) +void e2_ric_control_procedure::run_e2_ric_control_procedure(const e2_ric_control_request& e2_request) { - e2_ric_control_response response; - ri_cctrl_request_s ctrl_req = request_.request; - e2sm_interface* e2sm_iface = e2sm_mng.get_e2sm_interface(ctrl_req->ra_nfunction_id.value); + e2_ric_control_response e2_response; + e2_sm_ric_control_response_s e2sm_response; + ri_cctrl_request_s ctrl_req = e2_request.request; + e2sm_interface* e2sm_iface = e2sm_mng.get_e2sm_interface(ctrl_req->ra_nfunction_id.value); if (!e2sm_iface) { logger.error("RAN function ID not supported"); @@ -46,12 +47,13 @@ void e2_ric_control_procedure::run_e2_ric_control_procedure(const e2_ric_control return; } - response = control_service->execute_control_request(ric_ctrl_req); + e2sm_response = control_service->execute_control_request(ric_ctrl_req); if (ric_ctrl_req.ric_ctrl_ack_request_present and ric_ctrl_req.ric_ctrl_ack_request) { - if (response.success) { - send_e2_ric_control_acknowledge(request_, response); + e2_response = packer.pack_ric_control_response(e2sm_response); + if (e2_response.success) { + send_e2_ric_control_acknowledge(e2_request, e2_response); } else { - send_e2_ric_control_failure(request_, response); + send_e2_ric_control_failure(e2_request, e2_response); } } } @@ -64,10 +66,18 @@ void e2_ric_control_procedure::send_e2_ric_control_acknowledge(const e2_ric_cont logger.info("Sending E2 RIC Control Acknowledge"); msg.pdu.successful_outcome().load_info_obj(ASN1_E2AP_ID_RI_CCTRL); ri_cctrl_ack_s& ack = msg.pdu.successful_outcome().value.ri_cctrl_ack(); - ack->ra_nfunction_id = ctrl_request.request->ra_nfunction_id; ack->ri_crequest_id = ctrl_request.request->ri_crequest_id; + ack->ra_nfunction_id = ctrl_request.request->ra_nfunction_id; ack->ri_ccall_process_id_present = false; - ack->ri_cctrl_outcome_present = false; + if (ctrl_request.request->ri_ccall_process_id_present) { + ack->ri_ccall_process_id_present = true; + ack->ri_ccall_process_id.value = ctrl_request.request->ri_ccall_process_id.value; + } + ack->ri_cctrl_outcome_present = false; + if (ctrl_response.ack->ri_cctrl_outcome_present) { + ack->ri_cctrl_outcome_present = true; + ack->ri_cctrl_outcome = ctrl_response.ack->ri_cctrl_outcome; + } ric_notif.on_new_message(msg); } @@ -78,11 +88,18 @@ void e2_ric_control_procedure::send_e2_ric_control_failure(const e2_ric_control_ msg.pdu.set_unsuccessful_outcome(); logger.info("Sending E2 RIC Control Failure"); msg.pdu.unsuccessful_outcome().load_info_obj(ASN1_E2AP_ID_RI_CCTRL); - ri_cctrl_fail_s& fail = msg.pdu.unsuccessful_outcome().value.ri_cctrl_fail(); - fail->ra_nfunction_id = ctrl_request.request->ra_nfunction_id; - fail->ri_crequest_id = ctrl_request.request->ri_crequest_id; - fail->ri_ccall_process_id_present = false; - fail->ri_cctrl_outcome_present = false; - fail->cause->set_misc().value = cause_misc_e::options::unspecified; + ri_cctrl_fail_s& fail = msg.pdu.unsuccessful_outcome().value.ri_cctrl_fail(); + fail->ri_crequest_id = ctrl_request.request->ri_crequest_id; + fail->ra_nfunction_id = ctrl_request.request->ra_nfunction_id; + if (ctrl_request.request->ri_ccall_process_id_present) { + fail->ri_ccall_process_id_present = true; + fail->ri_ccall_process_id.value = ctrl_request.request->ri_ccall_process_id.value; + } + fail->cause = ctrl_response.failure->cause; + fail->ri_cctrl_outcome_present = false; + if (ctrl_response.ack->ri_cctrl_outcome_present) { + fail->ri_cctrl_outcome_present = true; + fail->ri_cctrl_outcome = ctrl_response.ack->ri_cctrl_outcome; + } ric_notif.on_new_message(msg); } diff --git a/tests/unittests/e2/common/e2_test_helpers.h b/tests/unittests/e2/common/e2_test_helpers.h index 4a25abe908..28a18a764a 100644 --- a/tests/unittests/e2/common/e2_test_helpers.h +++ b/tests/unittests/e2/common/e2_test_helpers.h @@ -696,6 +696,11 @@ class dummy_e2sm_handler : public e2sm_handler e2_sm_ric_control_request_s ric_control_request = {}; return ric_control_request; } + e2_ric_control_response pack_ric_control_response(const e2_sm_ric_control_response_s& e2sm_response) override + { + e2_ric_control_response ric_control_response = {}; + return ric_control_response; + } e2_sm_event_trigger_definition_s handle_packed_event_trigger_definition(const srsran::byte_buffer& buf) override { e2_sm_event_trigger_definition_s e2sm_event_trigger_def; From b1e8be38d4859aaace3039fe6c117be60061749a Mon Sep 17 00:00:00 2001 From: Piotr Gawlowicz Date: Thu, 23 Nov 2023 13:29:04 +0100 Subject: [PATCH 013/134] du,e2: refactor e2sm_param_configurator -> du_configurator --- include/srsran/du_high/du_high.h | 4 ++-- include/srsran/du_manager/du_manager.h | 2 +- include/srsran/e2/e2_factory.h | 3 ++- include/srsran/e2/e2sm/e2sm.h | 1 - include/srsran/e2/e2sm/e2sm_du.h | 11 +++++----- lib/du_high/du_high_impl.cpp | 4 ++-- lib/du_high/du_high_impl.h | 2 +- lib/du_manager/du_manager_impl.cpp | 3 ++- lib/du_manager/du_manager_impl.h | 3 ++- lib/du_manager/du_ue/du_ue_manager.cpp | 3 ++- lib/du_manager/du_ue/du_ue_manager.h | 2 +- .../du_ue_ric_configuration_procedure.cpp | 14 ++++++------- .../du_ue_ric_configuration_procedure.h | 18 ++++++++--------- lib/e2/common/e2_entity.cpp | 4 ++-- lib/e2/common/e2_entity.h | 3 ++- lib/e2/common/e2_factory.cpp | 4 ++-- .../e2sm_rc_control_action_du_executor.cpp | 20 +++++++++---------- .../e2sm_rc_control_action_du_executor.h | 9 +++++---- lib/e2/procedures/e2_ric_control_procedure.h | 1 - .../e2ap/e2ap_integration_test.cpp | 6 +++--- ...du_ue_ric_configuration_procedure_test.cpp | 18 ++++++++--------- tests/unittests/e2/common/e2_test_helpers.h | 19 +++++++++--------- 22 files changed, 79 insertions(+), 75 deletions(-) diff --git a/include/srsran/du_high/du_high.h b/include/srsran/du_high/du_high.h index 1bd4271a5a..c3292c677c 100644 --- a/include/srsran/du_high/du_high.h +++ b/include/srsran/du_high/du_high.h @@ -19,7 +19,7 @@ namespace srsran { -class e2sm_param_configurator; +class du_configurator; /// \brief Interface to DU-high class, which owns and manages the interaction between MAC, RLC and F1 layers. class du_high @@ -48,7 +48,7 @@ class du_high virtual mac_cell_control_information_handler& get_control_info_handler(du_cell_index_t cell_index) = 0; /// Returns handler to configure and control the UEs attached to this DU. - virtual e2sm_param_configurator& get_e2sm_configurator() = 0; + virtual du_configurator& get_du_configurator() = 0; }; } // namespace srsran diff --git a/include/srsran/du_manager/du_manager.h b/include/srsran/du_manager/du_manager.h index ed0fc89ddc..f1c91927f2 100644 --- a/include/srsran/du_manager/du_manager.h +++ b/include/srsran/du_manager/du_manager.h @@ -77,7 +77,7 @@ class du_manager_interface : public du_manager_interface_query, public du_manager_controller, public du_manager_configurator, public du_manager_mac_event_handler, - public e2sm_param_configurator + public du_configurator { public: virtual ~du_manager_interface() = default; diff --git a/include/srsran/e2/e2_factory.h b/include/srsran/e2/e2_factory.h index 34db541916..5f30d735bd 100644 --- a/include/srsran/e2/e2_factory.h +++ b/include/srsran/e2/e2_factory.h @@ -15,6 +15,7 @@ #include "e2ap_configuration.h" #include "e2sm/e2sm_manager.h" #include "subscription/e2_subscription.h" +#include "srsran/e2/e2sm/e2sm_du.h" #include "srsran/f1ap/du/f1ap_du.h" #include "srsran/gateways/sctp_network_gateway.h" #include "srsran/pcap/dlt_pcap.h" @@ -43,7 +44,7 @@ std::unique_ptr create_e2_entity(e2ap_configuration& e2 e2_connection_client* e2_client_, e2_du_metrics_interface& e2_du_metrics_, srs_du::f1ap_ue_id_translator& f1ap_ue_id_translator_, - e2sm_param_configurator& e2_param_config_, + du_configurator& du_configurator_, timer_factory timers_, task_executor& e2_exec_); diff --git a/include/srsran/e2/e2sm/e2sm.h b/include/srsran/e2/e2sm/e2sm.h index 6d8d06ea14..dfdb70d479 100644 --- a/include/srsran/e2/e2sm/e2sm.h +++ b/include/srsran/e2/e2sm/e2sm.h @@ -10,7 +10,6 @@ #pragma once -#include "e2sm_du.h" #include "srsran/adt/optional.h" #include "srsran/adt/variant.h" #include "srsran/asn1/e2ap/e2ap.h" diff --git a/include/srsran/e2/e2sm/e2sm_du.h b/include/srsran/e2/e2sm/e2sm_du.h index 6a66251c41..157a647a4d 100644 --- a/include/srsran/e2/e2sm/e2sm_du.h +++ b/include/srsran/e2/e2sm/e2sm_du.h @@ -15,7 +15,7 @@ namespace srsran { -struct ric_control_config { +struct du_mac_sched_control_config { uint64_t ue_id; optional num_harq_processes; optional num_harq_retransmissions; @@ -23,18 +23,19 @@ struct ric_control_config { optional max_prb_alloc; }; -struct ric_control_config_response { +struct du_mac_sched_control_config_response { bool harq_processes_result; bool min_prb_alloc_result; bool max_prb_alloc_result; }; -class e2sm_param_configurator +class du_configurator { public: - virtual ~e2sm_param_configurator() = default; + virtual ~du_configurator() = default; - virtual async_task configure_ue_mac_scheduler(ric_control_config reconf) = 0; + virtual async_task + configure_ue_mac_scheduler(du_mac_sched_control_config reconf) = 0; }; } // namespace srsran diff --git a/lib/du_high/du_high_impl.cpp b/lib/du_high/du_high_impl.cpp index fac82d4312..5f71f61bae 100644 --- a/lib/du_high/du_high_impl.cpp +++ b/lib/du_high/du_high_impl.cpp @@ -141,7 +141,7 @@ du_high_impl::du_high_impl(const du_high_configuration& config_) : cfg.e2_client, *cfg.e2_du_metric_iface, *f1ap, - get_e2sm_configurator(), + get_du_configurator(), timer_factory{timers, cfg.exec_mapper->du_e2_executor()}, cfg.exec_mapper->du_e2_executor()); } @@ -215,7 +215,7 @@ mac_cell_control_information_handler& du_high_impl::get_control_info_handler(du_ return mac->get_control_info_handler(cell_index); } -e2sm_param_configurator& du_high_impl::get_e2sm_configurator() +du_configurator& du_high_impl::get_du_configurator() { return *du_manager; } diff --git a/lib/du_high/du_high_impl.h b/lib/du_high/du_high_impl.h index 9715059bc8..2b06b5d2ed 100644 --- a/lib/du_high/du_high_impl.h +++ b/lib/du_high/du_high_impl.h @@ -42,7 +42,7 @@ class du_high_impl final : public du_high mac_cell_control_information_handler& get_control_info_handler(du_cell_index_t cell_index) override; - e2sm_param_configurator& get_e2sm_configurator() override; + du_configurator& get_du_configurator() override; private: class layer_connector; diff --git a/lib/du_manager/du_manager_impl.cpp b/lib/du_manager/du_manager_impl.cpp index 07ea3fadcb..13408b5bf0 100644 --- a/lib/du_manager/du_manager_impl.cpp +++ b/lib/du_manager/du_manager_impl.cpp @@ -160,7 +160,8 @@ size_t du_manager_impl::nof_ues() return fut.get(); } -async_task du_manager_impl::configure_ue_mac_scheduler(ric_control_config reconf) +async_task +du_manager_impl::configure_ue_mac_scheduler(du_mac_sched_control_config reconf) { return launch_async(reconf, ue_mng, params); } diff --git a/lib/du_manager/du_manager_impl.h b/lib/du_manager/du_manager_impl.h index 518d03344f..eb80bb4567 100644 --- a/lib/du_manager/du_manager_impl.h +++ b/lib/du_manager/du_manager_impl.h @@ -53,7 +53,8 @@ class du_manager_impl final : public du_manager_interface size_t nof_ues() override; - async_task configure_ue_mac_scheduler(srsran::ric_control_config reconf) override; + async_task + configure_ue_mac_scheduler(srsran::du_mac_sched_control_config reconf) override; private: // DU manager configuration that will be visible to all running procedures diff --git a/lib/du_manager/du_ue/du_ue_manager.cpp b/lib/du_manager/du_ue/du_ue_manager.cpp index 68f07842a2..382ff03c7f 100644 --- a/lib/du_manager/du_ue/du_ue_manager.cpp +++ b/lib/du_manager/du_ue/du_ue_manager.cpp @@ -104,7 +104,8 @@ void du_ue_manager::handle_reestablishment_request(du_ue_index_t new_ue_index, d schedule_async_task(old_ue_index, handle_ue_delete_request(f1ap_ue_delete_request{old_ue_index})); } -async_task du_ue_manager::handle_ue_config_request(const ric_control_config& msg) +async_task +du_ue_manager::handle_ue_config_request(const du_mac_sched_control_config& msg) { return launch_async(msg, *this, cfg); } diff --git a/lib/du_manager/du_ue/du_ue_manager.h b/lib/du_manager/du_ue/du_ue_manager.h index 6404abd227..e30ea6e718 100644 --- a/lib/du_manager/du_ue/du_ue_manager.h +++ b/lib/du_manager/du_ue/du_ue_manager.h @@ -44,7 +44,7 @@ class du_ue_manager final : public du_ue_manager_repository void handle_reestablishment_request(du_ue_index_t new_ue_index, du_ue_index_t old_ue_index); /// \brief Handle the configuration of an existing UE context by RIC request. - async_task handle_ue_config_request(const ric_control_config& msg); + async_task handle_ue_config_request(const du_mac_sched_control_config& msg); /// \brief Force the interruption of all UE activity. async_task stop(); diff --git a/lib/du_manager/procedures/du_ue_ric_configuration_procedure.cpp b/lib/du_manager/procedures/du_ue_ric_configuration_procedure.cpp index 66a59cf947..b27fc592b6 100644 --- a/lib/du_manager/procedures/du_ue_ric_configuration_procedure.cpp +++ b/lib/du_manager/procedures/du_ue_ric_configuration_procedure.cpp @@ -14,14 +14,14 @@ using namespace srsran; using namespace srs_du; -du_ue_ric_configuration_procedure::du_ue_ric_configuration_procedure(const ric_control_config& request_, - du_ue_manager_repository& ue_mng_, - const du_manager_params& du_params_) : +du_ue_ric_configuration_procedure::du_ue_ric_configuration_procedure(const du_mac_sched_control_config& request_, + du_ue_manager_repository& ue_mng_, + const du_manager_params& du_params_) : request(request_), ue_mng(ue_mng_), du_params(du_params_) { } -void du_ue_ric_configuration_procedure::operator()(coro_context>& ctx) +void du_ue_ric_configuration_procedure::operator()(coro_context>& ctx) { CORO_BEGIN(ctx); @@ -36,12 +36,12 @@ void du_ue_ric_configuration_procedure::operator()(coro_context& du_ue_ric_configuration_procedure::dispatch_ue_config_task() +manual_event& du_ue_ric_configuration_procedure::dispatch_ue_config_task() { // Find UE context based on F1AP UE ID. ue = ue_mng.find_f1ap_ue_id(static_cast(request.ue_id)); if (ue == nullptr) { - ric_control_config_response fail{false, false, false}; + du_mac_sched_control_config_response fail{false, false, false}; ue_config_completed.set(fail); return ue_config_completed; } @@ -55,7 +55,7 @@ manual_event& du_ue_ric_configuration_procedure::di CORO_AWAIT_VALUE(const mac_ue_reconfiguration_response result, handle_mac_config()); // Signal completion of UE configuration to external coroutine. - ue_config_completed.set(ric_control_config_response{result.result, result.result, result.result}); + ue_config_completed.set(du_mac_sched_control_config_response{result.result, result.result, result.result}); CORO_RETURN(); })); diff --git a/lib/du_manager/procedures/du_ue_ric_configuration_procedure.h b/lib/du_manager/procedures/du_ue_ric_configuration_procedure.h index aea6b96277..bcc0188507 100644 --- a/lib/du_manager/procedures/du_ue_ric_configuration_procedure.h +++ b/lib/du_manager/procedures/du_ue_ric_configuration_procedure.h @@ -21,27 +21,27 @@ namespace srs_du { class du_ue_ric_configuration_procedure { public: - du_ue_ric_configuration_procedure(const ric_control_config& request_, - du_ue_manager_repository& ue_mng_, - const du_manager_params& du_params_); + du_ue_ric_configuration_procedure(const du_mac_sched_control_config& request_, + du_ue_manager_repository& ue_mng_, + const du_manager_params& du_params_); - void operator()(coro_context>& ctx); + void operator()(coro_context>& ctx); const char* name() const { return "UE RIC configuration"; } private: - manual_event& dispatch_ue_config_task(); + manual_event& dispatch_ue_config_task(); // Task run from within the UE task loop. async_task handle_mac_config(); - const ric_control_config request; - du_ue_manager_repository& ue_mng; - const du_manager_params& du_params; + const du_mac_sched_control_config request; + du_ue_manager_repository& ue_mng; + const du_manager_params& du_params; du_ue* ue = nullptr; - manual_event ue_config_completed; + manual_event ue_config_completed; }; } // namespace srs_du diff --git a/lib/e2/common/e2_entity.cpp b/lib/e2/common/e2_entity.cpp index 056440fad6..6b4e795a9f 100644 --- a/lib/e2/common/e2_entity.cpp +++ b/lib/e2/common/e2_entity.cpp @@ -37,7 +37,7 @@ e2_entity::e2_entity(e2ap_configuration& cfg_, e2_connection_client* e2_client_, e2_du_metrics_interface& e2_du_metrics_iface_, srs_du::f1ap_ue_id_translator& f1ap_ue_id_translator_, - e2sm_param_configurator& e2_param_config_, + du_configurator& du_configurator_, timer_factory timers_, task_executor& task_exec_) : logger(srslog::fetch_basic_logger("E2")), cfg(cfg_), task_exec(task_exec_), main_ctrl_loop(128) @@ -61,7 +61,7 @@ e2_entity::e2_entity(e2ap_configuration& cfg_, // Create e2sm_rc Control Service Style 2. std::unique_ptr rc_control_service_style2 = std::make_unique(2); std::unique_ptr rc_control_action_2_6_executor = - std::make_unique(e2_param_config_); + std::make_unique(du_configurator_); rc_control_service_style2->add_e2sm_rc_control_action_executor(std::move(rc_control_action_2_6_executor)); e2sm_rc_packer->add_e2sm_control_service(rc_control_service_style2.get()); diff --git a/lib/e2/common/e2_entity.h b/lib/e2/common/e2_entity.h index dd43748c1f..f1f0242cd2 100644 --- a/lib/e2/common/e2_entity.h +++ b/lib/e2/common/e2_entity.h @@ -17,6 +17,7 @@ #include "srsran/e2/e2.h" #include "srsran/e2/e2_connection_client.h" #include "srsran/e2/e2ap_configuration.h" +#include "srsran/e2/e2sm/e2sm_du.h" #include "srsran/e2/e2sm/e2sm_factory.h" #include "srsran/e2/e2sm/e2sm_manager.h" #include "srsran/f1ap/du/f1ap_du.h" @@ -37,7 +38,7 @@ class e2_entity final : public e2_interface e2_connection_client* e2_client_, e2_du_metrics_interface& e2_du_metrics_, srs_du::f1ap_ue_id_translator& f1ap_ue_id_translator_, - e2sm_param_configurator& e2_param_config_, + du_configurator& du_configurator_, timer_factory timers_, task_executor& task_exec_); diff --git a/lib/e2/common/e2_factory.cpp b/lib/e2/common/e2_factory.cpp index 735db2354d..70c48a9b9b 100644 --- a/lib/e2/common/e2_factory.cpp +++ b/lib/e2/common/e2_factory.cpp @@ -41,12 +41,12 @@ std::unique_ptr srsran::create_e2_entity(e2ap_configuration& e2_connection_client* e2_client_, e2_du_metrics_interface& e2_du_metrics_, srs_du::f1ap_ue_id_translator& f1ap_ue_id_translator_, - e2sm_param_configurator& e2_param_config_, + du_configurator& du_configurator_, timer_factory timers_, task_executor& e2_exec_) { auto e2_ext = std::make_unique( - e2ap_cfg_, e2_client_, e2_du_metrics_, f1ap_ue_id_translator_, e2_param_config_, timers_, e2_exec_); + e2ap_cfg_, e2_client_, e2_du_metrics_, f1ap_ue_id_translator_, du_configurator_, timers_, e2_exec_); return e2_ext; } diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp index c93eba586a..cc89443e73 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp @@ -15,12 +15,11 @@ using namespace asn1::e2ap; using namespace asn1::e2sm_rc; using namespace srsran; -e2sm_rc_control_action_du_executor_base::e2sm_rc_control_action_du_executor_base( - e2sm_param_configurator& param_configurator_, - uint32_t action_id_) : +e2sm_rc_control_action_du_executor_base::e2sm_rc_control_action_du_executor_base(du_configurator& du_configurator_, + uint32_t action_id_) : logger(srslog::fetch_basic_logger("E2SM-RC")), action_id(action_id_), - param_configurator(param_configurator_), + du_param_configurator(du_configurator_), async_tasks(10) { } @@ -46,9 +45,8 @@ bool e2sm_rc_control_action_du_executor_base::fill_ran_function_description( return true; } -e2sm_rc_control_action_2_6_du_executor::e2sm_rc_control_action_2_6_du_executor( - e2sm_param_configurator& param_configurator_) : - e2sm_rc_control_action_du_executor_base(param_configurator_, 6) +e2sm_rc_control_action_2_6_du_executor::e2sm_rc_control_action_2_6_du_executor(du_configurator& du_configurator_) : + e2sm_rc_control_action_du_executor_base(du_configurator_, 6) { // Control Action description: // To control the radio resource management policy for slice-specific PRB quota allocation @@ -104,14 +102,14 @@ e2sm_rc_control_action_2_6_du_executor::execute_ric_control_action(const e2_sm_r } } - std::promise p; - std::future fut = p.get_future(); - ric_control_config_response ctrl_response; + std::promise p; + std::future fut = p.get_future(); + du_mac_sched_control_config_response ctrl_response; async_tasks.schedule([this, &p, &ctrl_response](coro_context>& ctx) { CORO_BEGIN(ctx); - CORO_AWAIT_VALUE(ctrl_response, param_configurator.configure_ue_mac_scheduler(ctrl_config)); + CORO_AWAIT_VALUE(ctrl_response, du_param_configurator.configure_ue_mac_scheduler(ctrl_config)); // Signal caller thread that the operation is complete. p.set_value(); diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h index 1b6a3568e9..8c3b1b64ed 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h @@ -14,6 +14,7 @@ #include "srsran/asn1/asn1_utils.h" #include "srsran/e2/e2.h" #include "srsran/e2/e2sm/e2sm.h" +#include "srsran/e2/e2sm/e2sm_du.h" #include "srsran/support/async/fifo_async_task_scheduler.h" #include @@ -23,7 +24,7 @@ class e2sm_rc_control_action_du_executor_base : public e2sm_control_action_execu { public: e2sm_rc_control_action_du_executor_base() = delete; - e2sm_rc_control_action_du_executor_base(e2sm_param_configurator& param_configurator_, uint32_t action_id_); + e2sm_rc_control_action_du_executor_base(du_configurator& du_configurator_, uint32_t action_id_); virtual ~e2sm_rc_control_action_du_executor_base() = default; bool fill_ran_function_description(asn1::e2sm_rc::ran_function_definition_ctrl_action_item_s& action_item); @@ -38,14 +39,14 @@ class e2sm_rc_control_action_du_executor_base : public e2sm_control_action_execu uint32_t action_id; std::string action_name; std::map action_params; - e2sm_param_configurator& param_configurator; + du_configurator& du_param_configurator; fifo_async_task_scheduler async_tasks; }; class e2sm_rc_control_action_2_6_du_executor : public e2sm_rc_control_action_du_executor_base { public: - e2sm_rc_control_action_2_6_du_executor(e2sm_param_configurator& param_configurator_); + e2sm_rc_control_action_2_6_du_executor(du_configurator& du_configurator_); virtual ~e2sm_rc_control_action_2_6_du_executor() = default; /// e2sm_control_request_executor functions. @@ -53,7 +54,7 @@ class e2sm_rc_control_action_2_6_du_executor : public e2sm_rc_control_action_du_ e2_sm_ric_control_response_s execute_ric_control_action(const e2_sm_ric_control_request_s& req) override; // Helper variables. - ric_control_config ctrl_config; + du_mac_sched_control_config ctrl_config; }; } // namespace srsran diff --git a/lib/e2/procedures/e2_ric_control_procedure.h b/lib/e2/procedures/e2_ric_control_procedure.h index aa158b59d0..d6d6e2e5bd 100644 --- a/lib/e2/procedures/e2_ric_control_procedure.h +++ b/lib/e2/procedures/e2_ric_control_procedure.h @@ -15,7 +15,6 @@ #include "srsran/e2/e2.h" #include "srsran/e2/e2_event_manager.h" #include "srsran/e2/e2_messages.h" -#include "srsran/e2/e2sm/e2sm_du.h" #include "srsran/e2/e2sm/e2sm_manager.h" #include "srsran/e2/e2sm/e2sm_rc.h" #include "srsran/support/async/async_task.h" diff --git a/tests/integrationtests/e2ap/e2ap_integration_test.cpp b/tests/integrationtests/e2ap/e2ap_integration_test.cpp index 72198c7e5c..96d1d8ea39 100644 --- a/tests/integrationtests/e2ap/e2ap_integration_test.cpp +++ b/tests/integrationtests/e2ap/e2ap_integration_test.cpp @@ -185,9 +185,9 @@ class e2ap_gw_connector_integration_test : public ::testing::Test du_metrics = std::make_unique(); f1ap_ue_id_mapper = std::make_unique(); e2_client = std::make_unique(*epoll_broker, nw_config, *pcap); - rc_param_configurator = std::make_unique(); + du_param_configurator = std::make_unique(); e2ap = create_e2_entity( - cfg, e2_client.get(), *du_metrics, *f1ap_ue_id_mapper, *rc_param_configurator, factory, ctrl_worker); + cfg, e2_client.get(), *du_metrics, *f1ap_ue_id_mapper, *du_param_configurator, factory, ctrl_worker); } e2ap_configuration cfg; @@ -198,7 +198,7 @@ class e2ap_gw_connector_integration_test : public ::testing::Test std::unique_ptr pcap; std::unique_ptr du_metrics; std::unique_ptr f1ap_ue_id_mapper; - std::unique_ptr rc_param_configurator; + std::unique_ptr du_param_configurator; std::unique_ptr e2_client; std::unique_ptr e2ap; srslog::basic_logger& test_logger = srslog::fetch_basic_logger("TEST"); diff --git a/tests/unittests/du_manager/procedures/du_ue_ric_configuration_procedure_test.cpp b/tests/unittests/du_manager/procedures/du_ue_ric_configuration_procedure_test.cpp index 8f09a783d1..6a4fcdb13f 100644 --- a/tests/unittests/du_manager/procedures/du_ue_ric_configuration_procedure_test.cpp +++ b/tests/unittests/du_manager/procedures/du_ue_ric_configuration_procedure_test.cpp @@ -25,26 +25,26 @@ class du_ue_ric_config_tester : public du_manager_proc_tester, public ::testing: test_ue = &create_ue(to_du_ue_index(test_rgen::uniform_int(0, MAX_DU_UE_INDEX))); } - void start_procedure(const ric_control_config& request) + void start_procedure(const du_mac_sched_control_config& request) { proc = launch_async(request, ue_mng, params); proc_launcher.emplace(proc); } - optional proc_result() + optional proc_result() { - return proc_launcher->ready() ? optional{proc_launcher->get()} : nullopt; + return proc_launcher->ready() ? optional{proc_launcher->get()} : nullopt; } - du_ue* test_ue = nullptr; - async_task proc; - optional> proc_launcher; + du_ue* test_ue = nullptr; + async_task proc; + optional> proc_launcher; }; TEST_F(du_ue_ric_config_tester, when_new_ric_config_is_started_then_du_manager_starts_mac_config_and_waits_for_mac_response) { - start_procedure(ric_control_config{(uint64_t)test_ue->f1ap_ue_id, nullopt, nullopt, 5, 10}); + start_procedure(du_mac_sched_control_config{(uint64_t)test_ue->f1ap_ue_id, nullopt, nullopt, 5, 10}); ASSERT_TRUE(mac.last_ue_reconf_msg.has_value()) << "MAC should have received new configuration"; ASSERT_EQ(mac.last_ue_reconf_msg->ue_index, test_ue->ue_index); @@ -59,7 +59,7 @@ TEST_F(du_ue_ric_config_tester, TEST_F(du_ue_ric_config_tester, when_mac_finished_configuration_then_procedure_finishes) { - start_procedure(ric_control_config{(uint64_t)test_ue->f1ap_ue_id, nullopt, nullopt, 5, 10}); + start_procedure(du_mac_sched_control_config{(uint64_t)test_ue->f1ap_ue_id, nullopt, nullopt, 5, 10}); ASSERT_FALSE(proc_result().has_value()) << "The procedure should wait for MAC response"; mac.wait_ue_reconf.result = mac_ue_reconfiguration_response{test_ue->ue_index, true}; @@ -82,7 +82,7 @@ TEST_F(du_ue_ric_config_tester, })); // Start RIC UE config. - start_procedure(ric_control_config{(uint64_t)test_ue->f1ap_ue_id, nullopt, nullopt, 5, 10}); + start_procedure(du_mac_sched_control_config{(uint64_t)test_ue->f1ap_ue_id, nullopt, nullopt, 5, 10}); // Status: RIC config procedure is waiting for previous procedure. ASSERT_FALSE(mac.last_ue_reconf_msg.has_value()) diff --git a/tests/unittests/e2/common/e2_test_helpers.h b/tests/unittests/e2/common/e2_test_helpers.h index 28a18a764a..a7a6c9ac28 100644 --- a/tests/unittests/e2/common/e2_test_helpers.h +++ b/tests/unittests/e2/common/e2_test_helpers.h @@ -740,17 +740,18 @@ class dummy_e2_connection_client final : public e2_connection_client dummy_e2_pdu_notifier* msg_notifier; }; -class dummy_e2sm_param_configurator : public e2sm_param_configurator +class dummy_du_configurator : public du_configurator { public: - dummy_e2sm_param_configurator(){}; - async_task configure_ue_mac_scheduler(ric_control_config reconf) override + dummy_du_configurator(){}; + async_task + configure_ue_mac_scheduler(du_mac_sched_control_config reconf) override { - ric_control_config config; + du_mac_sched_control_config config; config = reconf; - return launch_async([](coro_context>& ctx) { + return launch_async([](coro_context>& ctx) { CORO_BEGIN(ctx); - CORO_RETURN(ric_control_config_response{true, true, true}); + CORO_RETURN(du_mac_sched_control_config_response{true, true, true}); }); } }; @@ -777,7 +778,7 @@ class e2_test_base : public ::testing::Test std::unique_ptr rc_control_action_2_6_executor; std::unique_ptr e2sm_kpm_packer; std::unique_ptr e2sm_rc_packer; - std::unique_ptr rc_param_configurator; + std::unique_ptr rc_param_configurator; std::unique_ptr e2_subscription_mngr; std::unique_ptr du_metrics; std::unique_ptr f1ap_ue_id_mapper; @@ -865,7 +866,7 @@ class e2_entity_test : public e2_test_base du_metrics = std::make_unique(); f1ap_ue_id_mapper = std::make_unique(); factory = timer_factory{timers, task_worker}; - rc_param_configurator = std::make_unique(); + rc_param_configurator = std::make_unique(); e2 = create_e2_entity( cfg, e2_client.get(), *du_metrics, *f1ap_ue_id_mapper, *rc_param_configurator, factory, task_worker); } @@ -925,7 +926,7 @@ class e2_test_setup : public e2_test_base e2sm_kpm_packer = std::make_unique(*du_meas_provider); e2sm_kpm_iface = std::make_unique(test_logger, *e2sm_kpm_packer, *du_meas_provider); e2sm_rc_packer = std::make_unique(); - rc_param_configurator = std::make_unique(); + rc_param_configurator = std::make_unique(); e2sm_rc_iface = std::make_unique(test_logger, *e2sm_rc_packer); e2sm_rc_control_service_style2 = std::make_unique(2); rc_control_action_2_6_executor = std::make_unique(*rc_param_configurator); From 8f454c66c8bf94bbf89afd19d2cca725e3ed5ed1 Mon Sep 17 00:00:00 2001 From: Piotr Gawlowicz Date: Thu, 23 Nov 2023 13:33:08 +0100 Subject: [PATCH 014/134] du,e2: move include/e2/e2sm/e2sm_du.h -> include/du_manager/du_configurator.h --- .../srsran/{e2/e2sm/e2sm_du.h => du_manager/du_configurator.h} | 0 include/srsran/du_manager/du_manager.h | 2 +- include/srsran/e2/e2_factory.h | 2 +- lib/du_manager/procedures/du_ue_ric_configuration_procedure.h | 2 +- lib/e2/common/e2_entity.h | 2 +- lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h | 2 +- 6 files changed, 5 insertions(+), 5 deletions(-) rename include/srsran/{e2/e2sm/e2sm_du.h => du_manager/du_configurator.h} (100%) diff --git a/include/srsran/e2/e2sm/e2sm_du.h b/include/srsran/du_manager/du_configurator.h similarity index 100% rename from include/srsran/e2/e2sm/e2sm_du.h rename to include/srsran/du_manager/du_configurator.h diff --git a/include/srsran/du_manager/du_manager.h b/include/srsran/du_manager/du_manager.h index f1c91927f2..7b686fab5f 100644 --- a/include/srsran/du_manager/du_manager.h +++ b/include/srsran/du_manager/du_manager.h @@ -1,8 +1,8 @@ #pragma once +#include "du_configurator.h" #include "srsran/adt/byte_buffer.h" -#include "srsran/e2/e2sm/e2sm_du.h" #include "srsran/f1ap/du/f1ap_du.h" #include "srsran/ran/du_types.h" #include "srsran/ran/lcid.h" diff --git a/include/srsran/e2/e2_factory.h b/include/srsran/e2/e2_factory.h index 5f30d735bd..c7ec258edb 100644 --- a/include/srsran/e2/e2_factory.h +++ b/include/srsran/e2/e2_factory.h @@ -15,7 +15,7 @@ #include "e2ap_configuration.h" #include "e2sm/e2sm_manager.h" #include "subscription/e2_subscription.h" -#include "srsran/e2/e2sm/e2sm_du.h" +#include "srsran/du_manager/du_configurator.h" #include "srsran/f1ap/du/f1ap_du.h" #include "srsran/gateways/sctp_network_gateway.h" #include "srsran/pcap/dlt_pcap.h" diff --git a/lib/du_manager/procedures/du_ue_ric_configuration_procedure.h b/lib/du_manager/procedures/du_ue_ric_configuration_procedure.h index bcc0188507..403bfa3d17 100644 --- a/lib/du_manager/procedures/du_ue_ric_configuration_procedure.h +++ b/lib/du_manager/procedures/du_ue_ric_configuration_procedure.h @@ -12,7 +12,7 @@ #include "../du_ue/du_ue_manager_repository.h" #include "procedure_logger.h" -#include "srsran/e2/e2sm/e2sm_du.h" +#include "srsran/du_manager/du_configurator.h" #include "srsran/support/async/manual_event.h" namespace srsran { diff --git a/lib/e2/common/e2_entity.h b/lib/e2/common/e2_entity.h index f1f0242cd2..cb973444bc 100644 --- a/lib/e2/common/e2_entity.h +++ b/lib/e2/common/e2_entity.h @@ -14,10 +14,10 @@ #include "procedures/e2_setup_procedure.h" #include "procedures/e2_subscription_setup_procedure.h" #include "srsran/asn1/e2ap/e2ap.h" +#include "srsran/du_manager/du_configurator.h" #include "srsran/e2/e2.h" #include "srsran/e2/e2_connection_client.h" #include "srsran/e2/e2ap_configuration.h" -#include "srsran/e2/e2sm/e2sm_du.h" #include "srsran/e2/e2sm/e2sm_factory.h" #include "srsran/e2/e2sm/e2sm_manager.h" #include "srsran/f1ap/du/f1ap_du.h" diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h index 8c3b1b64ed..dea64b0f5d 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h @@ -12,9 +12,9 @@ #include "srsran/adt/optional.h" #include "srsran/asn1/asn1_utils.h" +#include "srsran/du_manager/du_configurator.h" #include "srsran/e2/e2.h" #include "srsran/e2/e2sm/e2sm.h" -#include "srsran/e2/e2sm/e2sm_du.h" #include "srsran/support/async/fifo_async_task_scheduler.h" #include From 4794ca099200ab8369439d178efa75dfc485417c Mon Sep 17 00:00:00 2001 From: Piotr Gawlowicz Date: Thu, 23 Nov 2023 13:37:19 +0100 Subject: [PATCH 015/134] e2sm_rc: action executor, use local instead of member variable --- lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp | 3 ++- lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h | 3 --- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp index cc89443e73..29da953086 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp @@ -82,6 +82,7 @@ bool e2sm_rc_control_action_2_6_du_executor::ric_control_action_supported(const e2_sm_ric_control_response_s e2sm_rc_control_action_2_6_du_executor::execute_ric_control_action(const e2_sm_ric_control_request_s& req) { + du_mac_sched_control_config ctrl_config; e2_sm_ric_control_response_s e2_resp; const e2_sm_rc_ctrl_hdr_format1_s& ctrl_hdr = variant_get(req.request_ctrl_hdr).ric_ctrl_hdr_formats.ctrl_hdr_format1(); @@ -106,7 +107,7 @@ e2sm_rc_control_action_2_6_du_executor::execute_ric_control_action(const e2_sm_r std::future fut = p.get_future(); du_mac_sched_control_config_response ctrl_response; - async_tasks.schedule([this, &p, &ctrl_response](coro_context>& ctx) { + async_tasks.schedule([this, &p, &ctrl_config, &ctrl_response](coro_context>& ctx) { CORO_BEGIN(ctx); CORO_AWAIT_VALUE(ctrl_response, du_param_configurator.configure_ue_mac_scheduler(ctrl_config)); diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h index dea64b0f5d..b89614faac 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h @@ -52,9 +52,6 @@ class e2sm_rc_control_action_2_6_du_executor : public e2sm_rc_control_action_du_ /// e2sm_control_request_executor functions. bool ric_control_action_supported(const e2_sm_ric_control_request_s& req) override; e2_sm_ric_control_response_s execute_ric_control_action(const e2_sm_ric_control_request_s& req) override; - - // Helper variables. - du_mac_sched_control_config ctrl_config; }; } // namespace srsran From 31bcf68a619973b59330ce054d5da25cb34e0e4e Mon Sep 17 00:00:00 2001 From: Piotr Gawlowicz Date: Fri, 1 Dec 2023 16:02:06 +0100 Subject: [PATCH 016/134] e2sm_rc: use async_task in ric control procedure --- include/srsran/e2/e2sm/e2sm.h | 5 +- lib/e2/common/e2_impl.cpp | 3 +- lib/e2/common/e2_impl.h | 1 - .../e2sm_rc_control_action_du_executor.cpp | 75 +++++++++---------- .../e2sm_rc_control_action_du_executor.h | 18 +++-- .../e2sm_rc/e2sm_rc_control_service_impl.cpp | 30 +++++--- .../e2sm_rc/e2sm_rc_control_service_impl.h | 13 ++-- .../procedures/e2_ric_control_procedure.cpp | 33 ++++---- lib/e2/procedures/e2_ric_control_procedure.h | 19 +++-- 9 files changed, 110 insertions(+), 87 deletions(-) diff --git a/include/srsran/e2/e2sm/e2sm.h b/include/srsran/e2/e2sm/e2sm.h index dfdb70d479..68451a7b3c 100644 --- a/include/srsran/e2/e2sm/e2sm.h +++ b/include/srsran/e2/e2sm/e2sm.h @@ -68,7 +68,8 @@ class e2sm_control_action_executor /// \brief trigger execution of the RIC control action. /// \param[in] req is a RIC control action request (with control header and message). /// \return Returns RIC control response. - virtual e2_sm_ric_control_response_s execute_ric_control_action(const e2_sm_ric_control_request_s& req) = 0; + virtual async_task + execute_ric_control_action(const e2_sm_ric_control_request_s& req) = 0; }; class e2sm_report_service @@ -107,7 +108,7 @@ class e2sm_control_service /// \brief trigger execution of the RIC control action. /// \param[in] req is a RIC control action request (with control header and message). /// \return Returns RIC control response. - virtual e2_sm_ric_control_response_s execute_control_request(const e2_sm_ric_control_request_s& req) = 0; + virtual async_task execute_control_request(const e2_sm_ric_control_request_s& req) = 0; }; class e2sm_handler diff --git a/lib/e2/common/e2_impl.cpp b/lib/e2/common/e2_impl.cpp index 2df5593d5c..65a806ca47 100644 --- a/lib/e2/common/e2_impl.cpp +++ b/lib/e2/common/e2_impl.cpp @@ -32,7 +32,6 @@ e2_impl::e2_impl(e2ap_configuration& cfg_, e2sm_mngr(e2sm_mngr_), subscribe_proc(e2_pdu_notifier_, subscription_mngr_, timers, logger), subscribe_delete_proc(e2_pdu_notifier_, subscription_mngr_, timers, logger), - ric_control_proc(pdu_notifier, e2sm_mngr, logger), events(std::make_unique(timers)), async_tasks(10) { @@ -111,7 +110,7 @@ void e2_impl::handle_ric_control_request(const asn1::e2ap::ri_cctrl_request_s ms logger.info("Received RIC Control Request"); e2_ric_control_request request; request.request = msg; - ric_control_proc.run_e2_ric_control_procedure(request); + async_tasks.schedule(request, pdu_notifier, e2sm_mngr, logger); } void e2_impl::handle_e2_setup_failure(const e2_setup_response_message& msg) diff --git a/lib/e2/common/e2_impl.h b/lib/e2/common/e2_impl.h index 250d665393..ad3cd087c3 100644 --- a/lib/e2/common/e2_impl.h +++ b/lib/e2/common/e2_impl.h @@ -102,7 +102,6 @@ class e2_impl final : public e2_interface e2sm_manager& e2sm_mngr; e2_subscription_setup_procedure subscribe_proc; e2_subscription_delete_procedure subscribe_delete_proc; - e2_ric_control_procedure ric_control_proc; std::unique_ptr events; fifo_async_task_scheduler async_tasks; unsigned current_transaction_id = 0; // store current E2AP transaction id diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp index 29da953086..67df06204e 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp @@ -17,10 +17,7 @@ using namespace srsran; e2sm_rc_control_action_du_executor_base::e2sm_rc_control_action_du_executor_base(du_configurator& du_configurator_, uint32_t action_id_) : - logger(srslog::fetch_basic_logger("E2SM-RC")), - action_id(action_id_), - du_param_configurator(du_configurator_), - async_tasks(10) + logger(srslog::fetch_basic_logger("E2SM-RC")), action_id(action_id_), du_param_configurator(du_configurator_) { } @@ -79,15 +76,28 @@ bool e2sm_rc_control_action_2_6_du_executor::ric_control_action_supported(const return true; }; -e2_sm_ric_control_response_s +async_task e2sm_rc_control_action_2_6_du_executor::execute_ric_control_action(const e2_sm_ric_control_request_s& req) +{ + du_mac_sched_control_config ctrl_config = convert_to_du_config_request(req); + return launch_async( + [this, ctrl_config = std::move(ctrl_config)](coro_context>& ctx) { + CORO_BEGIN(ctx); + du_mac_sched_control_config_response ctrl_response; + CORO_AWAIT_VALUE(ctrl_response, du_param_configurator.configure_ue_mac_scheduler(ctrl_config)); + e2_sm_ric_control_response_s e2_resp = convert_to_e2sm_response(ctrl_config, ctrl_response); + CORO_RETURN(e2_resp); + }); +}; + +du_mac_sched_control_config +e2sm_rc_control_action_2_6_du_executor::convert_to_du_config_request(const e2_sm_ric_control_request_s& e2sm_req_) { du_mac_sched_control_config ctrl_config; - e2_sm_ric_control_response_s e2_resp; const e2_sm_rc_ctrl_hdr_format1_s& ctrl_hdr = - variant_get(req.request_ctrl_hdr).ric_ctrl_hdr_formats.ctrl_hdr_format1(); + variant_get(e2sm_req_.request_ctrl_hdr).ric_ctrl_hdr_formats.ctrl_hdr_format1(); const e2_sm_rc_ctrl_msg_format1_s& ctrl_msg = - variant_get(req.request_ctrl_msg).ric_ctrl_msg_formats.ctrl_msg_format1(); + variant_get(e2sm_req_.request_ctrl_msg).ric_ctrl_msg_formats.ctrl_msg_format1(); ctrl_config.ue_id = ctrl_hdr.ue_id.gnb_du_ue_id().gnb_cu_ue_f1ap_id; @@ -102,31 +112,20 @@ e2sm_rc_control_action_2_6_du_executor::execute_ric_control_action(const e2_sm_r logger.error("Parameter not supported"); } } + return ctrl_config; +} - std::promise p; - std::future fut = p.get_future(); - du_mac_sched_control_config_response ctrl_response; - - async_tasks.schedule([this, &p, &ctrl_config, &ctrl_response](coro_context>& ctx) { - CORO_BEGIN(ctx); - - CORO_AWAIT_VALUE(ctrl_response, du_param_configurator.configure_ue_mac_scheduler(ctrl_config)); - - // Signal caller thread that the operation is complete. - p.set_value(); - - CORO_RETURN(); - }); - - // Block waiting for reconfiguration to complete. - fut.wait(); - - e2_resp.success = - ctrl_response.harq_processes_result and ctrl_response.max_prb_alloc_result and ctrl_response.min_prb_alloc_result; +e2_sm_ric_control_response_s e2sm_rc_control_action_2_6_du_executor::convert_to_e2sm_response( + const du_mac_sched_control_config& du_config_req_, + const du_mac_sched_control_config_response& du_response_) +{ + e2_sm_ric_control_response_s e2sm_response; + e2sm_response.success = + du_response_.harq_processes_result and du_response_.max_prb_alloc_result and du_response_.min_prb_alloc_result; // Always fill outcome here, it will be decided later whether it should be included in the e2 response. - e2_resp.ric_ctrl_outcome_present = true; - e2_sm_rc_ctrl_outcome_format1_s& ctrl_outcome = variant_get(e2_resp.ric_ctrl_outcome) + e2sm_response.ric_ctrl_outcome_present = true; + e2_sm_rc_ctrl_outcome_format1_s& ctrl_outcome = variant_get(e2sm_response.ric_ctrl_outcome) .ric_ctrl_outcome_formats.set_ctrl_outcome_format1(); // TODO: fill outcome properly @@ -135,23 +134,23 @@ e2sm_rc_control_action_2_6_du_executor::execute_ric_control_action(const e2_sm_r test_outcome.ran_param_value.set_value_int() = 100; ctrl_outcome.ran_p_list.push_back(test_outcome); - if (ctrl_config.min_prb_alloc.has_value()) { + if (du_config_req_.min_prb_alloc.has_value()) { e2_sm_rc_ctrl_outcome_format1_item_s min_prb_outcome; min_prb_outcome.ran_param_id = 11; - min_prb_outcome.ran_param_value.set_value_int() = ctrl_config.min_prb_alloc.value(); + min_prb_outcome.ran_param_value.set_value_int() = du_config_req_.min_prb_alloc.value(); ctrl_outcome.ran_p_list.push_back(min_prb_outcome); } - if (ctrl_config.max_prb_alloc.has_value()) { + if (du_config_req_.max_prb_alloc.has_value()) { e2_sm_rc_ctrl_outcome_format1_item_s max_prb_outcome; max_prb_outcome.ran_param_id = 12; - max_prb_outcome.ran_param_value.set_value_int() = ctrl_config.max_prb_alloc.value(); + max_prb_outcome.ran_param_value.set_value_int() = du_config_req_.max_prb_alloc.value(); ctrl_outcome.ran_p_list.push_back(max_prb_outcome); } - if (!e2_resp.success) { - e2_resp.cause.set_misc().value = cause_misc_e::options::unspecified; + if (!e2sm_response.success) { + e2sm_response.cause.set_misc().value = cause_misc_e::options::unspecified; } - return e2_resp; -}; + return e2sm_response; +} diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h index b89614faac..14d8433907 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h @@ -15,7 +15,6 @@ #include "srsran/du_manager/du_configurator.h" #include "srsran/e2/e2.h" #include "srsran/e2/e2sm/e2sm.h" -#include "srsran/support/async/fifo_async_task_scheduler.h" #include namespace srsran { @@ -30,9 +29,10 @@ class e2sm_rc_control_action_du_executor_base : public e2sm_control_action_execu bool fill_ran_function_description(asn1::e2sm_rc::ran_function_definition_ctrl_action_item_s& action_item); /// e2sm_control_request_executor functions. - uint32_t get_action_id() override; - bool ric_control_action_supported(const e2_sm_ric_control_request_s& req) override = 0; - e2_sm_ric_control_response_s execute_ric_control_action(const e2_sm_ric_control_request_s& req) override = 0; + uint32_t get_action_id() override; + bool ric_control_action_supported(const e2_sm_ric_control_request_s& req) override = 0; + async_task + execute_ric_control_action(const e2_sm_ric_control_request_s& req) override = 0; protected: srslog::basic_logger& logger; @@ -40,7 +40,6 @@ class e2sm_rc_control_action_du_executor_base : public e2sm_control_action_execu std::string action_name; std::map action_params; du_configurator& du_param_configurator; - fifo_async_task_scheduler async_tasks; }; class e2sm_rc_control_action_2_6_du_executor : public e2sm_rc_control_action_du_executor_base @@ -50,8 +49,13 @@ class e2sm_rc_control_action_2_6_du_executor : public e2sm_rc_control_action_du_ virtual ~e2sm_rc_control_action_2_6_du_executor() = default; /// e2sm_control_request_executor functions. - bool ric_control_action_supported(const e2_sm_ric_control_request_s& req) override; - e2_sm_ric_control_response_s execute_ric_control_action(const e2_sm_ric_control_request_s& req) override; + bool ric_control_action_supported(const e2_sm_ric_control_request_s& req) override; + async_task execute_ric_control_action(const e2_sm_ric_control_request_s& req) override; + +private: + du_mac_sched_control_config convert_to_du_config_request(const e2_sm_ric_control_request_s& e2sm_req_); + e2_sm_ric_control_response_s convert_to_e2sm_response(const du_mac_sched_control_config& du_config_req_, + const du_mac_sched_control_config_response& du_reponse_); }; } // namespace srsran diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp index 0645ea4eb2..e0c6b7301f 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp @@ -121,7 +121,8 @@ bool e2sm_rc_control_service::control_request_supported(const e2_sm_ric_control_ return true; } -e2_sm_ric_control_response_s e2sm_rc_control_service::execute_control_request(const e2_sm_ric_control_request_s& req) +async_task +e2sm_rc_control_service::execute_control_request(const e2_sm_ric_control_request_s& req) { const e2_sm_rc_ctrl_hdr_format1_s& ctrl_hdr = variant_get(req.request_ctrl_hdr).ric_ctrl_hdr_formats.ctrl_hdr_format1(); @@ -217,9 +218,10 @@ bool e2sm_rc_control_service_style_255::control_request_supported(const e2_sm_ri return false; } -e2_sm_ric_control_response_s +async_task e2sm_rc_control_service_style_255::execute_control_request(const e2_sm_ric_control_request_s& req) { + std::vector> tasks; e2_sm_ric_control_response_s aggregated_response; aggregated_response.success = false; @@ -231,14 +233,24 @@ e2sm_rc_control_service_style_255::execute_control_request(const e2_sm_ric_contr for (auto& style : ctrl_msg_f2.ric_ctrl_style_list) { for (auto& action : style.ric_ctrl_action_list) { // Create a control request with format 1 to match the API of control service styles 1-10. - e2_sm_ric_control_request_s tmp_req = create_req_f1_from_req_f2(ctrl_hdr_f2, style, action); - e2_sm_ric_control_response_s tmp_response; - tmp_response = config_req_executors[action.ric_ctrl_action_id]->execute_ric_control_action(tmp_req); + e2_sm_ric_control_request_s t_req = create_req_f1_from_req_f2(ctrl_hdr_f2, style, action); + uint32_t ric_ctrl_action_id = action.ric_ctrl_action_id; - // Aggregate RIC control action response. - aggregated_response.success &= tmp_response.success; + async_task task = + config_req_executors[ric_ctrl_action_id]->execute_ric_control_action(t_req); + tasks.push_back(std::move(task)); } } - return aggregated_response; -} \ No newline at end of file + return launch_async([tasks = std::move(tasks), aggregated_response = std::move(aggregated_response), i = (unsigned)0]( + coro_context>& ctx) mutable { + e2_sm_ric_control_response_s task_response; + CORO_BEGIN(ctx); + for (; i < tasks.size(); i++) { + CORO_AWAIT_VALUE(task_response, tasks[i]); + // Aggregate RIC control action response. + aggregated_response.success &= task_response.success; + } + CORO_RETURN(aggregated_response); + }); +} diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h index 28804ff5c4..1db57b336a 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h @@ -65,8 +65,9 @@ class e2sm_rc_control_service_base : public e2sm_control_service /// e2sm_control_service functions. uint32_t get_style_type() override; bool add_e2sm_rc_control_action_executor(std::unique_ptr ctrl_act_executor) override; - bool control_request_supported(const e2_sm_ric_control_request_s& req) override = 0; - virtual e2_sm_ric_control_response_s execute_control_request(const e2_sm_ric_control_request_s& req) override = 0; + bool control_request_supported(const e2_sm_ric_control_request_s& req) override = 0; + virtual async_task + execute_control_request(const e2_sm_ric_control_request_s& req) override = 0; protected: srslog::basic_logger& logger; @@ -83,8 +84,8 @@ class e2sm_rc_control_service : public e2sm_rc_control_service_base e2sm_rc_control_service(uint32_t style_id_); virtual ~e2sm_rc_control_service() = default; - bool control_request_supported(const e2_sm_ric_control_request_s& req) override; - e2_sm_ric_control_response_s execute_control_request(const e2_sm_ric_control_request_s& req) override; + bool control_request_supported(const e2_sm_ric_control_request_s& req) override; + async_task execute_control_request(const e2_sm_ric_control_request_s& req) override; }; /// Class for e2sm_rc_control_service style 255 (Multiple actions) @@ -94,8 +95,8 @@ class e2sm_rc_control_service_style_255 : public e2sm_rc_control_service_base e2sm_rc_control_service_style_255(); virtual ~e2sm_rc_control_service_style_255() = default; - bool control_request_supported(const e2_sm_ric_control_request_s& req) override; - e2_sm_ric_control_response_s execute_control_request(const e2_sm_ric_control_request_s& req) override; + bool control_request_supported(const e2_sm_ric_control_request_s& req) override; + async_task execute_control_request(const e2_sm_ric_control_request_s& req) override; private: // Helper functions. diff --git a/lib/e2/procedures/e2_ric_control_procedure.cpp b/lib/e2/procedures/e2_ric_control_procedure.cpp index 845e29d67a..f6534ed287 100644 --- a/lib/e2/procedures/e2_ric_control_procedure.cpp +++ b/lib/e2/procedures/e2_ric_control_procedure.cpp @@ -14,48 +14,47 @@ using namespace srsran; using namespace asn1::e2ap; using namespace asn1::e2sm_rc; -e2_ric_control_procedure::e2_ric_control_procedure(e2_message_notifier& notif_, - e2sm_manager& e2sm_mng_, - srslog::basic_logger& logger_) : - logger(logger_), ric_notif(notif_), e2sm_mng(e2sm_mng_) +e2_ric_control_procedure::e2_ric_control_procedure(const e2_ric_control_request& request_, + e2_message_notifier& notif_, + e2sm_manager& e2sm_mng_, + srslog::basic_logger& logger_) : + logger(logger_), ric_notif(notif_), e2sm_mng(e2sm_mng_), e2_request(request_) { } -void e2_ric_control_procedure::run_e2_ric_control_procedure(const e2_ric_control_request& e2_request) +void e2_ric_control_procedure::operator()(coro_context>& ctx) { - e2_ric_control_response e2_response; - e2_sm_ric_control_response_s e2sm_response; - ri_cctrl_request_s ctrl_req = e2_request.request; - e2sm_interface* e2sm_iface = e2sm_mng.get_e2sm_interface(ctrl_req->ra_nfunction_id.value); + CORO_BEGIN(ctx); + e2sm_iface = e2sm_mng.get_e2sm_interface(e2_request.request->ra_nfunction_id.value); if (!e2sm_iface) { logger.error("RAN function ID not supported"); - return; + CORO_EARLY_RETURN(); } - e2sm_handler& packer = e2sm_iface->get_e2sm_packer(); - e2_sm_ric_control_request_s ric_ctrl_req = packer.handle_packed_ric_control_request(ctrl_req); - e2sm_control_service* control_service = e2sm_iface->get_e2sm_control_service(ric_ctrl_req); + ric_ctrl_req = e2sm_iface->get_e2sm_packer().handle_packed_ric_control_request(e2_request.request); + control_service = e2sm_iface->get_e2sm_control_service(ric_ctrl_req); if (!control_service) { logger.error("RIC Control Service not supported"); - return; + CORO_EARLY_RETURN(); } if (!control_service->control_request_supported(ric_ctrl_req)) { logger.error("RIC Control Request not supported"); - return; + CORO_EARLY_RETURN(); } - e2sm_response = control_service->execute_control_request(ric_ctrl_req); + CORO_AWAIT_VALUE(e2sm_response, control_service->execute_control_request(ric_ctrl_req)); if (ric_ctrl_req.ric_ctrl_ack_request_present and ric_ctrl_req.ric_ctrl_ack_request) { - e2_response = packer.pack_ric_control_response(e2sm_response); + e2_response = e2sm_iface->get_e2sm_packer().pack_ric_control_response(e2sm_response); if (e2_response.success) { send_e2_ric_control_acknowledge(e2_request, e2_response); } else { send_e2_ric_control_failure(e2_request, e2_response); } } + CORO_RETURN(); } void e2_ric_control_procedure::send_e2_ric_control_acknowledge(const e2_ric_control_request& ctrl_request, diff --git a/lib/e2/procedures/e2_ric_control_procedure.h b/lib/e2/procedures/e2_ric_control_procedure.h index d6d6e2e5bd..1a27948c8c 100644 --- a/lib/e2/procedures/e2_ric_control_procedure.h +++ b/lib/e2/procedures/e2_ric_control_procedure.h @@ -24,17 +24,26 @@ namespace srsran { class e2_ric_control_procedure { public: - e2_ric_control_procedure(e2_message_notifier& notif_, e2sm_manager& e2sm_mng_, srslog::basic_logger& logger); + e2_ric_control_procedure(const e2_ric_control_request& request_, + e2_message_notifier& notif_, + e2sm_manager& e2sm_mng_, + srslog::basic_logger& logger); - void run_e2_ric_control_procedure(const e2_ric_control_request& request); + void operator()(coro_context>& ctx); void send_e2_ric_control_acknowledge(const e2_ric_control_request& ctrl_request, const e2_ric_control_response& ctrl_response); void send_e2_ric_control_failure(const e2_ric_control_request&, const e2_ric_control_response& ctrl_response); private: - srslog::basic_logger& logger; - e2_message_notifier& ric_notif; - e2sm_manager& e2sm_mng; + srslog::basic_logger& logger; + e2_message_notifier& ric_notif; + e2sm_manager& e2sm_mng; + const e2_ric_control_request e2_request; + e2_sm_ric_control_response_s e2sm_response; + e2_ric_control_response e2_response; + e2sm_interface* e2sm_iface; + e2_sm_ric_control_request_s ric_ctrl_req; + e2sm_control_service* control_service; }; } // namespace srsran \ No newline at end of file From 98171e58ebe9f19688ce01d2bc339c80b78a53cf Mon Sep 17 00:00:00 2001 From: Piotr Gawlowicz Date: Fri, 1 Dec 2023 16:10:52 +0100 Subject: [PATCH 017/134] e2sm: refactor e2sm stucture names --- include/srsran/e2/e2sm/e2sm.h | 27 ++++++++-------- .../common/e2_subscription_manager_impl.cpp | 2 +- lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.cpp | 19 ++++++----- lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.h | 8 ++--- lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.cpp | 6 ++-- lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.h | 2 +- lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp | 17 +++++----- lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h | 8 ++--- .../e2sm_rc_control_action_du_executor.cpp | 16 +++++----- .../e2sm_rc_control_action_du_executor.h | 17 +++++----- .../e2sm_rc/e2sm_rc_control_service_impl.cpp | 32 +++++++++---------- .../e2sm_rc/e2sm_rc_control_service_impl.h | 16 +++++----- lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.cpp | 2 +- lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.h | 2 +- lib/e2/procedures/e2_ric_control_procedure.h | 4 +-- tests/unittests/e2/common/e2_test_helpers.h | 14 ++++---- 16 files changed, 94 insertions(+), 98 deletions(-) diff --git a/include/srsran/e2/e2sm/e2sm.h b/include/srsran/e2/e2sm/e2sm.h index 68451a7b3c..4b95f232e9 100644 --- a/include/srsran/e2/e2sm/e2sm.h +++ b/include/srsran/e2/e2sm/e2sm.h @@ -22,18 +22,18 @@ namespace srsran { enum e2sm_service_model_t { KPM, RC, UNKNOWN_SM }; -struct e2_sm_event_trigger_definition_s { +struct e2sm_event_trigger_definition { enum e2sm_ric_service_type_t { REPORT, INSERT, POLICY, UNKNOWN }; e2sm_ric_service_type_t ric_service_type; uint64_t report_period; }; -struct e2_sm_action_definition_s { +struct e2sm_action_definition { e2sm_service_model_t service_model; variant action_definition; }; -struct e2_sm_ric_control_request_s { +struct e2sm_ric_control_request { e2sm_service_model_t service_model; bool ric_call_process_id_present = false; bool ric_ctrl_ack_request_present = false; @@ -43,7 +43,7 @@ struct e2_sm_ric_control_request_s { bool ric_ctrl_ack_request; }; -struct e2_sm_ric_control_response_s { +struct e2sm_ric_control_response { e2sm_service_model_t service_model; bool success; bool ric_call_process_id_present = false; @@ -64,12 +64,11 @@ class e2sm_control_action_executor /// \brief check if the requested RIC control action is supported. /// \param[in] req is a RIC control action request (with control header and message). /// \return Returns true if action supported by control action executor. - virtual bool ric_control_action_supported(const e2_sm_ric_control_request_s& req) = 0; + virtual bool ric_control_action_supported(const e2sm_ric_control_request& req) = 0; /// \brief trigger execution of the RIC control action. /// \param[in] req is a RIC control action request (with control header and message). /// \return Returns RIC control response. - virtual async_task - execute_ric_control_action(const e2_sm_ric_control_request_s& req) = 0; + virtual async_task execute_ric_control_action(const e2sm_ric_control_request& req) = 0; }; class e2sm_report_service @@ -104,11 +103,11 @@ class e2sm_control_service /// \brief check if the requested RIC control action is supported. /// \param[in] req is a RIC control action request (with control header and message). /// \return Returns true if the action supported by control service. - virtual bool control_request_supported(const e2_sm_ric_control_request_s& req) = 0; + virtual bool control_request_supported(const e2sm_ric_control_request& req) = 0; /// \brief trigger execution of the RIC control action. /// \param[in] req is a RIC control action request (with control header and message). /// \return Returns RIC control response. - virtual async_task execute_control_request(const e2_sm_ric_control_request_s& req) = 0; + virtual async_task execute_control_request(const e2sm_ric_control_request& req) = 0; }; class e2sm_handler @@ -118,19 +117,19 @@ class e2sm_handler /// \brief Handle the packed E2SM Action Definition. /// \param[in] buf /// \return Returns the unpacked E2SM Action Definition. - virtual e2_sm_action_definition_s handle_packed_e2sm_action_definition(const srsran::byte_buffer& buf) = 0; + virtual e2sm_action_definition handle_packed_e2sm_action_definition(const srsran::byte_buffer& buf) = 0; /// \brief Handle the packed E2SM Event Trigger Definition. /// \param[in] buf /// \return Returns the E2SM Event Trigger Definition. - virtual e2_sm_event_trigger_definition_s handle_packed_event_trigger_definition(const srsran::byte_buffer& buf) = 0; + virtual e2sm_event_trigger_definition handle_packed_event_trigger_definition(const srsran::byte_buffer& buf) = 0; /// \brief Handle the packed E2 RIC Control Request. /// \param[in] req E2 RIC Control Request. /// \return Returns the unpacked E2SM RIC Control Request. - virtual e2_sm_ric_control_request_s handle_packed_ric_control_request(const asn1::e2ap::ri_cctrl_request_s& req) = 0; + virtual e2sm_ric_control_request handle_packed_ric_control_request(const asn1::e2ap::ri_cctrl_request_s& req) = 0; /// \brief Pack the E2SM RIC Control Response. /// \param[in] response E2SM RIC Control Response. /// \return Returns the packed E2 RIC Control Response. - virtual e2_ric_control_response pack_ric_control_response(const e2_sm_ric_control_response_s& e2sm_response) = 0; + virtual e2_ric_control_response pack_ric_control_response(const e2sm_ric_control_response& e2sm_response) = 0; /// @brief Pack the RAN function description. virtual asn1::unbounded_octstring pack_ran_function_description() = 0; }; @@ -158,6 +157,6 @@ class e2sm_interface /// \brief gets a unique_ptr to the e2sm control service for a control msg. /// \param[in] req is a RIC control action request (with control header and message). /// \return Returns a unique_ptr to the e2sm report service. - virtual e2sm_control_service* get_e2sm_control_service(const e2_sm_ric_control_request_s& req) = 0; + virtual e2sm_control_service* get_e2sm_control_service(const e2sm_ric_control_request& req) = 0; }; } // namespace srsran diff --git a/lib/e2/common/e2_subscription_manager_impl.cpp b/lib/e2/common/e2_subscription_manager_impl.cpp index 81cd89fea6..cddef43eb6 100644 --- a/lib/e2/common/e2_subscription_manager_impl.cpp +++ b/lib/e2/common/e2_subscription_manager_impl.cpp @@ -29,7 +29,7 @@ e2_subscription_manager_impl::handle_subscription_setup(const asn1::e2ap::ricsub subscription.subscription_info.request_id.ric_requestor_id = msg->ri_crequest_id.value.ric_requestor_id; subscription.subscription_info.ran_function_id = msg->ra_nfunction_id->value; subscription.subscription_info.request_id.ric_instance_id = msg->ri_crequest_id.value.ric_instance_id; - e2_sm_event_trigger_definition_s event_trigger_def; + e2sm_event_trigger_definition event_trigger_def; if (supported_ran_functions.count(msg->ra_nfunction_id.value)) { e2sm_interface* e2sm = e2sm_mngr.get_e2sm_interface(msg->ra_nfunction_id.value); 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 d652a2965b..a0d405ad63 100644 --- a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.cpp +++ b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.cpp @@ -22,44 +22,43 @@ const uint32_t e2sm_kpm_asn1_packer::revision = 0; e2sm_kpm_asn1_packer::e2sm_kpm_asn1_packer(e2sm_kpm_meas_provider& meas_provider_) : meas_provider(meas_provider_) {} -e2_sm_action_definition_s +e2sm_action_definition e2sm_kpm_asn1_packer::handle_packed_e2sm_action_definition(const srsran::byte_buffer& action_definition) { - e2_sm_action_definition_s action_def; - asn1::cbit_ref bref(action_definition); + e2sm_action_definition action_def; + asn1::cbit_ref bref(action_definition); if (variant_get(action_def.action_definition).unpack(bref) != asn1::SRSASN_SUCCESS) { printf("Failed to unpack E2SM KPM Action Definition\n"); } return action_def; } -e2_sm_ric_control_request_s +e2sm_ric_control_request e2sm_kpm_asn1_packer::handle_packed_ric_control_request(const asn1::e2ap::ri_cctrl_request_s& req) { printf("Failure - RIC control not available in e2sm_kpm.\n"); - e2_sm_ric_control_request_s control_request = {}; + e2sm_ric_control_request control_request = {}; return control_request; } -e2_ric_control_response -e2sm_kpm_asn1_packer::pack_ric_control_response(const e2_sm_ric_control_response_s& e2sm_response) +e2_ric_control_response e2sm_kpm_asn1_packer::pack_ric_control_response(const e2sm_ric_control_response& e2sm_response) { printf("Failure - RIC control not available in e2sm_kpm.\n"); e2_ric_control_response control_response = {}; return control_response; } -e2_sm_event_trigger_definition_s +e2sm_event_trigger_definition e2sm_kpm_asn1_packer::handle_packed_event_trigger_definition(const srsran::byte_buffer& event_trigger_definition) { - e2_sm_event_trigger_definition_s e2sm_event_trigger_def; + e2sm_event_trigger_definition e2sm_event_trigger_def; e2_sm_kpm_event_trigger_definition_s e2sm_kpm_event_trigger_def; asn1::cbit_ref bref(event_trigger_definition); if (e2sm_kpm_event_trigger_def.unpack(bref) != asn1::SRSASN_SUCCESS) { printf("Failed to unpack E2SM KPM Event Trigger Definition\n"); } - e2sm_event_trigger_def.ric_service_type = e2_sm_event_trigger_definition_s::e2sm_ric_service_type_t::REPORT; + e2sm_event_trigger_def.ric_service_type = e2sm_event_trigger_definition::e2sm_ric_service_type_t::REPORT; e2sm_event_trigger_def.report_period = e2sm_kpm_event_trigger_def.event_definition_formats.event_definition_format1().report_period; diff --git a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.h b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.h index a9a62fdef3..08e72f0c59 100644 --- a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.h +++ b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.h @@ -31,11 +31,11 @@ class e2sm_kpm_asn1_packer : public e2sm_handler e2sm_kpm_asn1_packer(e2sm_kpm_meas_provider& meas_provider_); /// Receive populated ASN1 struct that needs to be unpacked and forwarded. - e2_sm_action_definition_s handle_packed_e2sm_action_definition(const srsran::byte_buffer& action_definition) override; - e2_sm_ric_control_request_s handle_packed_ric_control_request(const asn1::e2ap::ri_cctrl_request_s& req) override; - e2_ric_control_response pack_ric_control_response(const e2_sm_ric_control_response_s& e2sm_response) override; + e2sm_action_definition handle_packed_e2sm_action_definition(const srsran::byte_buffer& action_definition) override; + e2sm_ric_control_request handle_packed_ric_control_request(const asn1::e2ap::ri_cctrl_request_s& req) override; + e2_ric_control_response pack_ric_control_response(const e2sm_ric_control_response& e2sm_response) override; - e2_sm_event_trigger_definition_s + e2sm_event_trigger_definition handle_packed_event_trigger_definition(const srsran::byte_buffer& event_trigger_definition) override; asn1::unbounded_octstring pack_ran_function_description() override; diff --git a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.cpp b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.cpp index 0b5d3e4ab9..5498903112 100644 --- a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.cpp +++ b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.cpp @@ -26,7 +26,7 @@ e2sm_kpm_impl::e2sm_kpm_impl(srslog::basic_logger& logger_, bool e2sm_kpm_impl::action_supported(const asn1::e2ap::ri_caction_to_be_setup_item_s& ric_action) { - e2_sm_action_definition_s action_def = + e2sm_action_definition action_def = e2sm_packer.handle_packed_e2sm_action_definition(ric_action.ric_action_definition); e2_sm_kpm_action_definition_s& e2sm_kpm_action_def = @@ -213,7 +213,7 @@ bool e2sm_kpm_impl::process_action_definition_format5(const e2_sm_kpm_action_def std::unique_ptr e2sm_kpm_impl::get_e2sm_report_service(const srsran::byte_buffer& action_definition) { - e2_sm_action_definition_s action_def = e2sm_packer.handle_packed_e2sm_action_definition(action_definition); + e2sm_action_definition action_def = e2sm_packer.handle_packed_e2sm_action_definition(action_definition); e2_sm_kpm_action_definition_s& e2sm_kpm_action_def = variant_get(action_def.action_definition); uint32_t ric_style_type = e2sm_kpm_action_def.ric_style_type; @@ -240,7 +240,7 @@ bool e2sm_kpm_impl::add_e2sm_control_service(std::unique_ptr get_e2sm_report_service(const srsran::byte_buffer& action_definition) override; - e2sm_control_service* get_e2sm_control_service(const e2_sm_ric_control_request_s& request) override; + e2sm_control_service* get_e2sm_control_service(const e2sm_ric_control_request& request) override; bool add_e2sm_control_service(std::unique_ptr control_service) override; diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp index f6d4d8a30c..3c6c03baa5 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp @@ -29,11 +29,11 @@ bool e2sm_rc_asn1_packer::add_e2sm_control_service(e2sm_control_service* control return true; } -e2_sm_action_definition_s +e2sm_action_definition e2sm_rc_asn1_packer::handle_packed_e2sm_action_definition(const srsran::byte_buffer& action_definition) { - e2_sm_action_definition_s action_def; - asn1::cbit_ref bref(action_definition); + e2sm_action_definition action_def; + asn1::cbit_ref bref(action_definition); if (variant_get(action_def.action_definition).unpack(bref) != asn1::SRSASN_SUCCESS) { printf("Failed to unpack E2SM RC Action Definition\n"); @@ -41,10 +41,10 @@ e2sm_rc_asn1_packer::handle_packed_e2sm_action_definition(const srsran::byte_buf return action_def; } -e2_sm_ric_control_request_s +e2sm_ric_control_request e2sm_rc_asn1_packer::handle_packed_ric_control_request(const asn1::e2ap::ri_cctrl_request_s& req) { - e2_sm_ric_control_request_s ric_control_request = {}; + e2sm_ric_control_request ric_control_request = {}; ric_control_request.service_model = e2sm_service_model_t::RC; ric_control_request.ric_call_process_id_present = req->ri_ccall_process_id_present; ric_control_request.ric_ctrl_ack_request_present = req->ri_cctrl_ack_request_present; @@ -72,8 +72,7 @@ e2sm_rc_asn1_packer::handle_packed_ric_control_request(const asn1::e2ap::ri_cctr return ric_control_request; }; -e2_ric_control_response -e2sm_rc_asn1_packer::pack_ric_control_response(const e2_sm_ric_control_response_s& e2sm_response) +e2_ric_control_response e2sm_rc_asn1_packer::pack_ric_control_response(const e2sm_ric_control_response& e2sm_response) { e2_ric_control_response e2_control_response = {}; @@ -107,11 +106,11 @@ e2sm_rc_asn1_packer::pack_ric_control_response(const e2_sm_ric_control_response_ return e2_control_response; } -e2_sm_event_trigger_definition_s +e2sm_event_trigger_definition e2sm_rc_asn1_packer::handle_packed_event_trigger_definition(const srsran::byte_buffer& event_trigger_definition) { // TODO - return e2_sm_event_trigger_definition_s(); + return e2sm_event_trigger_definition(); } asn1::unbounded_octstring e2sm_rc_asn1_packer::pack_ran_function_description() diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h index 7e9dd54310..b3faf37637 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h @@ -29,11 +29,11 @@ class e2sm_rc_asn1_packer : public e2sm_handler static const uint32_t revision; e2sm_rc_asn1_packer(); /// Receive populated ASN1 struct that needs to be unpacked and forwarded. - e2_sm_action_definition_s handle_packed_e2sm_action_definition(const srsran::byte_buffer& action_definition) override; - e2_sm_ric_control_request_s handle_packed_ric_control_request(const asn1::e2ap::ri_cctrl_request_s& req) override; - e2_ric_control_response pack_ric_control_response(const e2_sm_ric_control_response_s& e2sm_response) override; + e2sm_action_definition handle_packed_e2sm_action_definition(const srsran::byte_buffer& action_definition) override; + e2sm_ric_control_request handle_packed_ric_control_request(const asn1::e2ap::ri_cctrl_request_s& req) override; + e2_ric_control_response pack_ric_control_response(const e2sm_ric_control_response& e2sm_response) override; - e2_sm_event_trigger_definition_s + e2sm_event_trigger_definition handle_packed_event_trigger_definition(const srsran::byte_buffer& event_trigger_definition) override; asn1::unbounded_octstring pack_ran_function_description() override; diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp index 67df06204e..0857620b21 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp @@ -63,7 +63,7 @@ e2sm_rc_control_action_2_6_du_executor::e2sm_rc_control_action_2_6_du_executor(d action_params.insert({13, "Dedicated PRB Policy Ratio"}); }; -bool e2sm_rc_control_action_2_6_du_executor::ric_control_action_supported(const e2_sm_ric_control_request_s& req) +bool e2sm_rc_control_action_2_6_du_executor::ric_control_action_supported(const e2sm_ric_control_request& req) { const e2_sm_rc_ctrl_msg_format1_s& ctrl_msg = variant_get(req.request_ctrl_msg).ric_ctrl_msg_formats.ctrl_msg_format1(); @@ -76,22 +76,22 @@ bool e2sm_rc_control_action_2_6_du_executor::ric_control_action_supported(const return true; }; -async_task -e2sm_rc_control_action_2_6_du_executor::execute_ric_control_action(const e2_sm_ric_control_request_s& req) +async_task +e2sm_rc_control_action_2_6_du_executor::execute_ric_control_action(const e2sm_ric_control_request& req) { du_mac_sched_control_config ctrl_config = convert_to_du_config_request(req); return launch_async( - [this, ctrl_config = std::move(ctrl_config)](coro_context>& ctx) { + [this, ctrl_config = std::move(ctrl_config)](coro_context>& ctx) { CORO_BEGIN(ctx); du_mac_sched_control_config_response ctrl_response; CORO_AWAIT_VALUE(ctrl_response, du_param_configurator.configure_ue_mac_scheduler(ctrl_config)); - e2_sm_ric_control_response_s e2_resp = convert_to_e2sm_response(ctrl_config, ctrl_response); + e2sm_ric_control_response e2_resp = convert_to_e2sm_response(ctrl_config, ctrl_response); CORO_RETURN(e2_resp); }); }; du_mac_sched_control_config -e2sm_rc_control_action_2_6_du_executor::convert_to_du_config_request(const e2_sm_ric_control_request_s& e2sm_req_) +e2sm_rc_control_action_2_6_du_executor::convert_to_du_config_request(const e2sm_ric_control_request& e2sm_req_) { du_mac_sched_control_config ctrl_config; const e2_sm_rc_ctrl_hdr_format1_s& ctrl_hdr = @@ -115,11 +115,11 @@ e2sm_rc_control_action_2_6_du_executor::convert_to_du_config_request(const e2_sm return ctrl_config; } -e2_sm_ric_control_response_s e2sm_rc_control_action_2_6_du_executor::convert_to_e2sm_response( +e2sm_ric_control_response e2sm_rc_control_action_2_6_du_executor::convert_to_e2sm_response( const du_mac_sched_control_config& du_config_req_, const du_mac_sched_control_config_response& du_response_) { - e2_sm_ric_control_response_s e2sm_response; + e2sm_ric_control_response e2sm_response; e2sm_response.success = du_response_.harq_processes_result and du_response_.max_prb_alloc_result and du_response_.min_prb_alloc_result; diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h index 14d8433907..917af37644 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h @@ -29,10 +29,9 @@ class e2sm_rc_control_action_du_executor_base : public e2sm_control_action_execu bool fill_ran_function_description(asn1::e2sm_rc::ran_function_definition_ctrl_action_item_s& action_item); /// e2sm_control_request_executor functions. - uint32_t get_action_id() override; - bool ric_control_action_supported(const e2_sm_ric_control_request_s& req) override = 0; - async_task - execute_ric_control_action(const e2_sm_ric_control_request_s& req) override = 0; + uint32_t get_action_id() override; + bool ric_control_action_supported(const e2sm_ric_control_request& req) override = 0; + async_task execute_ric_control_action(const e2sm_ric_control_request& req) override = 0; protected: srslog::basic_logger& logger; @@ -49,13 +48,13 @@ class e2sm_rc_control_action_2_6_du_executor : public e2sm_rc_control_action_du_ virtual ~e2sm_rc_control_action_2_6_du_executor() = default; /// e2sm_control_request_executor functions. - bool ric_control_action_supported(const e2_sm_ric_control_request_s& req) override; - async_task execute_ric_control_action(const e2_sm_ric_control_request_s& req) override; + bool ric_control_action_supported(const e2sm_ric_control_request& req) override; + async_task execute_ric_control_action(const e2sm_ric_control_request& req) override; private: - du_mac_sched_control_config convert_to_du_config_request(const e2_sm_ric_control_request_s& e2sm_req_); - e2_sm_ric_control_response_s convert_to_e2sm_response(const du_mac_sched_control_config& du_config_req_, - const du_mac_sched_control_config_response& du_reponse_); + du_mac_sched_control_config convert_to_du_config_request(const e2sm_ric_control_request& e2sm_req_); + e2sm_ric_control_response convert_to_e2sm_response(const du_mac_sched_control_config& du_config_req_, + const du_mac_sched_control_config_response& du_reponse_); }; } // namespace srsran diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp index e0c6b7301f..f95b7fce0d 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp @@ -76,7 +76,7 @@ bool e2sm_rc_control_service_base::add_e2sm_rc_control_action_executor( e2sm_rc_control_service::e2sm_rc_control_service(uint32_t style_id_) : e2sm_rc_control_service_base(style_id_) {} -bool e2sm_rc_control_service::control_request_supported(const e2_sm_ric_control_request_s& req) +bool e2sm_rc_control_service::control_request_supported(const e2sm_ric_control_request& req) { const e2_sm_rc_ctrl_hdr_s& ctrl_hdr = variant_get(req.request_ctrl_hdr); const e2_sm_rc_ctrl_msg_s& ctrl_msg = variant_get(req.request_ctrl_msg); @@ -121,8 +121,8 @@ bool e2sm_rc_control_service::control_request_supported(const e2_sm_ric_control_ return true; } -async_task -e2sm_rc_control_service::execute_control_request(const e2_sm_ric_control_request_s& req) +async_task +e2sm_rc_control_service::execute_control_request(const e2sm_ric_control_request& req) { const e2_sm_rc_ctrl_hdr_format1_s& ctrl_hdr = variant_get(req.request_ctrl_hdr).ric_ctrl_hdr_formats.ctrl_hdr_format1(); @@ -131,12 +131,12 @@ e2sm_rc_control_service::execute_control_request(const e2_sm_ric_control_request e2sm_rc_control_service_style_255::e2sm_rc_control_service_style_255() : e2sm_rc_control_service_base(255) {} -e2_sm_ric_control_request_s e2sm_rc_control_service_style_255::create_req_f1_from_req_f2( +e2sm_ric_control_request e2sm_rc_control_service_style_255::create_req_f1_from_req_f2( const e2_sm_rc_ctrl_hdr_format2_s& ctrl_hdr_f2, const asn1::e2sm_rc::e2_sm_rc_ctrl_msg_format2_style_item_s style, const asn1::e2sm_rc::e2_sm_rc_ctrl_msg_format2_ctrl_action_item_s action) { - e2_sm_ric_control_request_s req_f1; + e2sm_ric_control_request req_f1; req_f1.ric_call_process_id_present = false; req_f1.ric_ctrl_ack_request_present = false; req_f1.ric_ctrl_ack_request = false; @@ -170,7 +170,7 @@ e2_sm_ric_control_request_s e2sm_rc_control_service_style_255::create_req_f1_fro return req_f1; } -bool e2sm_rc_control_service_style_255::control_request_supported(const e2_sm_ric_control_request_s& req) +bool e2sm_rc_control_service_style_255::control_request_supported(const e2sm_ric_control_request& req) { const e2_sm_rc_ctrl_hdr_s& ctrl_hdr = variant_get(req.request_ctrl_hdr); const e2_sm_rc_ctrl_msg_s& ctrl_msg = variant_get(req.request_ctrl_msg); @@ -208,7 +208,7 @@ bool e2sm_rc_control_service_style_255::control_request_supported(const e2_sm_ri for (auto& action : style.ric_ctrl_action_list) { // Create a control request with format 1 to match the API of control service styles 1-10. - e2_sm_ric_control_request_s tmp_req_f1 = create_req_f1_from_req_f2(ctrl_hdr_f2, style, action); + e2sm_ric_control_request tmp_req_f1 = create_req_f1_from_req_f2(ctrl_hdr_f2, style, action); if (!e2sm_rc_control_services.at(style.indicated_ctrl_style_type)->control_request_supported(tmp_req_f1)) { return false; @@ -218,11 +218,11 @@ bool e2sm_rc_control_service_style_255::control_request_supported(const e2_sm_ri return false; } -async_task -e2sm_rc_control_service_style_255::execute_control_request(const e2_sm_ric_control_request_s& req) +async_task +e2sm_rc_control_service_style_255::execute_control_request(const e2sm_ric_control_request& req) { - std::vector> tasks; - e2_sm_ric_control_response_s aggregated_response; + std::vector> tasks; + e2sm_ric_control_response aggregated_response; aggregated_response.success = false; const e2_sm_rc_ctrl_hdr_format2_s& ctrl_hdr_f2 = @@ -233,18 +233,18 @@ e2sm_rc_control_service_style_255::execute_control_request(const e2_sm_ric_contr for (auto& style : ctrl_msg_f2.ric_ctrl_style_list) { for (auto& action : style.ric_ctrl_action_list) { // Create a control request with format 1 to match the API of control service styles 1-10. - e2_sm_ric_control_request_s t_req = create_req_f1_from_req_f2(ctrl_hdr_f2, style, action); - uint32_t ric_ctrl_action_id = action.ric_ctrl_action_id; + e2sm_ric_control_request t_req = create_req_f1_from_req_f2(ctrl_hdr_f2, style, action); + uint32_t ric_ctrl_action_id = action.ric_ctrl_action_id; - async_task task = + async_task task = config_req_executors[ric_ctrl_action_id]->execute_ric_control_action(t_req); tasks.push_back(std::move(task)); } } return launch_async([tasks = std::move(tasks), aggregated_response = std::move(aggregated_response), i = (unsigned)0]( - coro_context>& ctx) mutable { - e2_sm_ric_control_response_s task_response; + coro_context>& ctx) mutable { + e2sm_ric_control_response task_response; CORO_BEGIN(ctx); for (; i < tasks.size(); i++) { CORO_AWAIT_VALUE(task_response, tasks[i]); diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h index 1db57b336a..a003e1a324 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h @@ -65,9 +65,9 @@ class e2sm_rc_control_service_base : public e2sm_control_service /// e2sm_control_service functions. uint32_t get_style_type() override; bool add_e2sm_rc_control_action_executor(std::unique_ptr ctrl_act_executor) override; - bool control_request_supported(const e2_sm_ric_control_request_s& req) override = 0; - virtual async_task - execute_control_request(const e2_sm_ric_control_request_s& req) override = 0; + bool control_request_supported(const e2sm_ric_control_request& req) override = 0; + virtual async_task + execute_control_request(const e2sm_ric_control_request& req) override = 0; protected: srslog::basic_logger& logger; @@ -84,8 +84,8 @@ class e2sm_rc_control_service : public e2sm_rc_control_service_base e2sm_rc_control_service(uint32_t style_id_); virtual ~e2sm_rc_control_service() = default; - bool control_request_supported(const e2_sm_ric_control_request_s& req) override; - async_task execute_control_request(const e2_sm_ric_control_request_s& req) override; + bool control_request_supported(const e2sm_ric_control_request& req) override; + async_task execute_control_request(const e2sm_ric_control_request& req) override; }; /// Class for e2sm_rc_control_service style 255 (Multiple actions) @@ -95,12 +95,12 @@ class e2sm_rc_control_service_style_255 : public e2sm_rc_control_service_base e2sm_rc_control_service_style_255(); virtual ~e2sm_rc_control_service_style_255() = default; - bool control_request_supported(const e2_sm_ric_control_request_s& req) override; - async_task execute_control_request(const e2_sm_ric_control_request_s& req) override; + bool control_request_supported(const e2sm_ric_control_request& req) override; + async_task execute_control_request(const e2sm_ric_control_request& req) override; private: // Helper functions. - e2_sm_ric_control_request_s + e2sm_ric_control_request create_req_f1_from_req_f2(const asn1::e2sm_rc::e2_sm_rc_ctrl_hdr_format2_s& ctrl_hdr_f2, const asn1::e2sm_rc::e2_sm_rc_ctrl_msg_format2_style_item_s style, const asn1::e2sm_rc::e2_sm_rc_ctrl_msg_format2_ctrl_action_item_s action); diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.cpp index 3343c92107..bc0b532acc 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.cpp @@ -47,7 +47,7 @@ bool e2sm_rc_impl::add_e2sm_control_service(std::unique_ptr(request.request_ctrl_hdr); diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.h index 3fb074a69c..7bbf94ace1 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.h +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.h @@ -28,7 +28,7 @@ class e2sm_rc_impl : public e2sm_interface bool action_supported(const asn1::e2ap::ri_caction_to_be_setup_item_s& ric_action) override; std::unique_ptr get_e2sm_report_service(const srsran::byte_buffer& action_definition) override; - e2sm_control_service* get_e2sm_control_service(const e2_sm_ric_control_request_s& request) override; + e2sm_control_service* get_e2sm_control_service(const e2sm_ric_control_request& request) override; bool add_e2sm_control_service(std::unique_ptr control_service) override; diff --git a/lib/e2/procedures/e2_ric_control_procedure.h b/lib/e2/procedures/e2_ric_control_procedure.h index 1a27948c8c..579c07cc1a 100644 --- a/lib/e2/procedures/e2_ric_control_procedure.h +++ b/lib/e2/procedures/e2_ric_control_procedure.h @@ -40,10 +40,10 @@ class e2_ric_control_procedure e2_message_notifier& ric_notif; e2sm_manager& e2sm_mng; const e2_ric_control_request e2_request; - e2_sm_ric_control_response_s e2sm_response; + e2sm_ric_control_response e2sm_response; e2_ric_control_response e2_response; e2sm_interface* e2sm_iface; - e2_sm_ric_control_request_s ric_ctrl_req; + e2sm_ric_control_request ric_ctrl_req; e2sm_control_service* control_service; }; } // namespace srsran \ No newline at end of file diff --git a/tests/unittests/e2/common/e2_test_helpers.h b/tests/unittests/e2/common/e2_test_helpers.h index a7a6c9ac28..1117c808bf 100644 --- a/tests/unittests/e2/common/e2_test_helpers.h +++ b/tests/unittests/e2/common/e2_test_helpers.h @@ -676,9 +676,9 @@ class dummy_network_gateway_data_handler : public srsran::sctp_network_gateway_d class dummy_e2sm_handler : public e2sm_handler { - e2_sm_action_definition_s handle_packed_e2sm_action_definition(const srsran::byte_buffer& buf) override + e2sm_action_definition handle_packed_e2sm_action_definition(const srsran::byte_buffer& buf) override { - e2_sm_action_definition_s action_def; + e2sm_action_definition action_def; e2_sm_kpm_action_definition_s& e2_sm_kpm_action_definition = variant_get(action_def.action_definition); e2_sm_kpm_action_definition.ric_style_type = 3; @@ -691,19 +691,19 @@ class dummy_e2sm_handler : public e2sm_handler e2_sm_kpm_action_definition.action_definition_formats.action_definition_format3().granul_period = 10; return action_def; } - e2_sm_ric_control_request_s handle_packed_ric_control_request(const asn1::e2ap::ri_cctrl_request_s& req) override + e2sm_ric_control_request handle_packed_ric_control_request(const asn1::e2ap::ri_cctrl_request_s& req) override { - e2_sm_ric_control_request_s ric_control_request = {}; + e2sm_ric_control_request ric_control_request = {}; return ric_control_request; } - e2_ric_control_response pack_ric_control_response(const e2_sm_ric_control_response_s& e2sm_response) override + e2_ric_control_response pack_ric_control_response(const e2sm_ric_control_response& e2sm_response) override { e2_ric_control_response ric_control_response = {}; return ric_control_response; } - e2_sm_event_trigger_definition_s handle_packed_event_trigger_definition(const srsran::byte_buffer& buf) override + e2sm_event_trigger_definition handle_packed_event_trigger_definition(const srsran::byte_buffer& buf) override { - e2_sm_event_trigger_definition_s e2sm_event_trigger_def; + e2sm_event_trigger_definition e2sm_event_trigger_def; e2sm_event_trigger_def.report_period = 10; return e2sm_event_trigger_def; } From ef092d6d6085fdd5c3b8ed3577855bddb152f783 Mon Sep 17 00:00:00 2001 From: Piotr Gawlowicz Date: Mon, 4 Dec 2023 11:02:46 +0100 Subject: [PATCH 018/134] e2sm_rc: check if action supported before executing it --- .../e2sm_rc/e2sm_rc_control_service_impl.cpp | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp index f95b7fce0d..9f6a8c08be 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp @@ -126,6 +126,17 @@ e2sm_rc_control_service::execute_control_request(const e2sm_ric_control_request& { const e2_sm_rc_ctrl_hdr_format1_s& ctrl_hdr = variant_get(req.request_ctrl_hdr).ric_ctrl_hdr_formats.ctrl_hdr_format1(); + + if (config_req_executors.find(ctrl_hdr.ric_ctrl_action_id) == config_req_executors.end()) { + return launch_async([](coro_context>& ctx) { + CORO_BEGIN(ctx); + e2sm_ric_control_response ctrl_response; + ctrl_response.success = false; + ctrl_response.cause.set_ric_request() = cause_ri_crequest_e::options::action_not_supported; + CORO_RETURN(ctrl_response); + }); + } + return config_req_executors[ctrl_hdr.ric_ctrl_action_id]->execute_ric_control_action(req); } @@ -236,12 +247,24 @@ e2sm_rc_control_service_style_255::execute_control_request(const e2sm_ric_contro e2sm_ric_control_request t_req = create_req_f1_from_req_f2(ctrl_hdr_f2, style, action); uint32_t ric_ctrl_action_id = action.ric_ctrl_action_id; - async_task task = - config_req_executors[ric_ctrl_action_id]->execute_ric_control_action(t_req); - tasks.push_back(std::move(task)); + if (config_req_executors.find(ric_ctrl_action_id) != config_req_executors.end()) { + async_task task = + config_req_executors[ric_ctrl_action_id]->execute_ric_control_action(t_req); + tasks.push_back(std::move(task)); + } } } + if (tasks.size() == 0) { + return launch_async([](coro_context>& ctx) { + CORO_BEGIN(ctx); + e2sm_ric_control_response ctrl_response; + ctrl_response.success = false; + ctrl_response.cause.set_ric_request() = cause_ri_crequest_e::options::action_not_supported; + CORO_RETURN(ctrl_response); + }); + } + return launch_async([tasks = std::move(tasks), aggregated_response = std::move(aggregated_response), i = (unsigned)0]( coro_context>& ctx) mutable { e2sm_ric_control_response task_response; From 080b67d71d3b4973651f89ec3402d1d88aa4262e Mon Sep 17 00:00:00 2001 From: yagoda Date: Mon, 4 Dec 2023 14:37:33 +0100 Subject: [PATCH 019/134] e2sm_rc: adding some logic to handle unsuccessful RIC control requests --- .../e2sm_rc_control_action_du_executor.cpp | 22 +++++++++++++++---- .../e2sm_rc_control_action_du_executor.h | 1 + 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp index 0857620b21..1af59c4e9c 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp @@ -41,7 +41,17 @@ bool e2sm_rc_control_action_du_executor_base::fill_ran_function_description( return true; } - +async_task +e2sm_rc_control_action_du_executor_base::return_ctrl_failure(const e2sm_ric_control_request& req) +{ + return launch_async([req](coro_context>& ctx) { + CORO_BEGIN(ctx); + e2sm_ric_control_response e2sm_response; + e2sm_response.success = false; + e2sm_response.cause.set_misc().value = cause_misc_e::options::unspecified; + CORO_RETURN(e2sm_response); + }); +} e2sm_rc_control_action_2_6_du_executor::e2sm_rc_control_action_2_6_du_executor(du_configurator& du_configurator_) : e2sm_rc_control_action_du_executor_base(du_configurator_, 6) { @@ -80,6 +90,9 @@ async_task e2sm_rc_control_action_2_6_du_executor::execute_ric_control_action(const e2sm_ric_control_request& req) { du_mac_sched_control_config ctrl_config = convert_to_du_config_request(req); + if (!ctrl_config.ue_id) { + return return_ctrl_failure(req); + } return launch_async( [this, ctrl_config = std::move(ctrl_config)](coro_context>& ctx) { CORO_BEGIN(ctx); @@ -93,23 +106,24 @@ e2sm_rc_control_action_2_6_du_executor::execute_ric_control_action(const e2sm_ri du_mac_sched_control_config e2sm_rc_control_action_2_6_du_executor::convert_to_du_config_request(const e2sm_ric_control_request& e2sm_req_) { - du_mac_sched_control_config ctrl_config; + du_mac_sched_control_config ctrl_config = {}; const e2_sm_rc_ctrl_hdr_format1_s& ctrl_hdr = variant_get(e2sm_req_.request_ctrl_hdr).ric_ctrl_hdr_formats.ctrl_hdr_format1(); const e2_sm_rc_ctrl_msg_format1_s& ctrl_msg = variant_get(e2sm_req_.request_ctrl_msg).ric_ctrl_msg_formats.ctrl_msg_format1(); - ctrl_config.ue_id = ctrl_hdr.ue_id.gnb_du_ue_id().gnb_cu_ue_f1ap_id; - for (auto& ran_p : ctrl_msg.ran_p_list) { if (action_params.find(ran_p.ran_param_id) != action_params.end()) { if (ran_p.ran_param_id == 11) { ctrl_config.min_prb_alloc = ran_p.ran_param_value_type.ran_p_choice_elem_true().ran_param_value.value_int(); + ctrl_config.ue_id = ctrl_hdr.ue_id.gnb_du_ue_id().gnb_cu_ue_f1ap_id; } else if (ran_p.ran_param_id == 12) { ctrl_config.max_prb_alloc = ran_p.ran_param_value_type.ran_p_choice_elem_true().ran_param_value.value_int(); + ctrl_config.ue_id = ctrl_hdr.ue_id.gnb_du_ue_id().gnb_cu_ue_f1ap_id; } } else { logger.error("Parameter not supported"); + return ctrl_config; } } return ctrl_config; diff --git a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h index 917af37644..f13e3eab88 100644 --- a/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h +++ b/lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h @@ -32,6 +32,7 @@ class e2sm_rc_control_action_du_executor_base : public e2sm_control_action_execu uint32_t get_action_id() override; bool ric_control_action_supported(const e2sm_ric_control_request& req) override = 0; async_task execute_ric_control_action(const e2sm_ric_control_request& req) override = 0; + async_task return_ctrl_failure(const e2sm_ric_control_request& req); protected: srslog::basic_logger& logger; From cc13b0fe8544aeca1cb1564008f8dc715ed1b955 Mon Sep 17 00:00:00 2001 From: yagoda Date: Mon, 4 Dec 2023 14:38:27 +0100 Subject: [PATCH 020/134] e2sm_rc: adding test for unsuccessful RIC control request --- tests/unittests/e2/common/e2_test_helpers.h | 69 ++++++++----------- .../e2/e2_ric_control_procedure_test.cpp | 32 +++++++++ 2 files changed, 60 insertions(+), 41 deletions(-) diff --git a/tests/unittests/e2/common/e2_test_helpers.h b/tests/unittests/e2/common/e2_test_helpers.h index 1117c808bf..c2b4181ae8 100644 --- a/tests/unittests/e2/common/e2_test_helpers.h +++ b/tests/unittests/e2/common/e2_test_helpers.h @@ -207,7 +207,11 @@ inline e2_message generate_ric_control_request_style2_action6(srslog::basic_logg return e2_msg; } -inline e2_message generate_ric_control_request(srslog::basic_logger& logger) +inline e2_message generate_ric_control_request(srslog::basic_logger& logger, + int64_t style_type, + uint64_t action_id, + uint64_t param_id, + uint64_t param_value) { using namespace asn1::e2ap; e2_message e2_msg; @@ -216,17 +220,20 @@ inline e2_message generate_ric_control_request(srslog::basic_logger& logger) ri_cctrl_request_s& ric_control_request = initmsg.value.ri_cctrl_request(); ric_control_request->ri_ccall_process_id_present = false; - ric_control_request->ri_cctrl_ack_request_present = false; + ric_control_request->ri_cctrl_ack_request_present = true; + ric_control_request->ri_cctrl_ack_request.value = ri_cctrl_ack_request_e::options::ack; ric_control_request->ra_nfunction_id.value.value = 1; - ric_control_request->ri_crequest_id.value.ric_instance_id = 2; - ric_control_request->ri_crequest_id.value.ric_requestor_id = 3; + ric_control_request->ri_crequest_id.value.ric_instance_id = 3; + ric_control_request->ri_crequest_id.value.ric_requestor_id = 0; asn1::e2sm_rc::e2_sm_rc_ctrl_hdr_s ctrl_hdr; - ctrl_hdr.ric_ctrl_hdr_formats.set_ctrl_hdr_format2(); - ctrl_hdr.ric_ctrl_hdr_formats.ctrl_hdr_format2().ue_id_present = true; - ctrl_hdr.ric_ctrl_hdr_formats.ctrl_hdr_format2().ue_id.set_gnb_ue_id(); - ctrl_hdr.ric_ctrl_hdr_formats.ctrl_hdr_format2().ue_id.gnb_du_ue_id().gnb_cu_ue_f1ap_id = 4; + ctrl_hdr.ric_ctrl_hdr_formats.set_ctrl_hdr_format1(); + + ctrl_hdr.ric_ctrl_hdr_formats.ctrl_hdr_format1().ric_style_type = style_type; + ctrl_hdr.ric_ctrl_hdr_formats.ctrl_hdr_format1().ric_ctrl_action_id = action_id; + ctrl_hdr.ric_ctrl_hdr_formats.ctrl_hdr_format1().ue_id.set_gnb_ue_id(); + ctrl_hdr.ric_ctrl_hdr_formats.ctrl_hdr_format1().ue_id.gnb_du_ue_id().gnb_cu_ue_f1ap_id = 4; srsran::byte_buffer ctrl_hdr_buff; asn1::bit_ref bref_msg(ctrl_hdr_buff); @@ -238,39 +245,19 @@ inline e2_message generate_ric_control_request(srslog::basic_logger& logger) std::copy(ctrl_hdr_buff.begin(), ctrl_hdr_buff.end(), ric_control_request->ri_cctrl_hdr.value.begin()); asn1::e2sm_rc::e2_sm_rc_ctrl_msg_s ctrl_msg; - ctrl_msg.ric_ctrl_msg_formats.set_ctrl_msg_format2(); - ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format2().ric_ctrl_style_list.resize(1); - ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format2().ric_ctrl_style_list[0].indicated_ctrl_style_type = 1; - ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format2().ric_ctrl_style_list[0].ric_ctrl_action_list.resize(1); - ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format2().ric_ctrl_style_list[0].ric_ctrl_action_list[0].ric_ctrl_action_id = - 1; - - ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format2() - .ric_ctrl_style_list[0] - .ric_ctrl_action_list[0] - .ran_p_list.ran_p_list.resize(1); - ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format2() - .ric_ctrl_style_list[0] - .ric_ctrl_action_list[0] - .ran_p_list.ran_p_list[0] - .ran_param_id = 1; - ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format2() - .ric_ctrl_style_list[0] - .ric_ctrl_action_list[0] - .ran_p_list.ran_p_list[0] - .ran_param_value_type.set_ran_p_choice_elem_true(); - ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format2() - .ric_ctrl_style_list[0] - .ric_ctrl_action_list[0] - .ran_p_list.ran_p_list[0] - .ran_param_value_type.ran_p_choice_elem_true() - .ran_param_value.set_value_int(); - ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format2() - .ric_ctrl_style_list[0] - .ric_ctrl_action_list[0] - .ran_p_list.ran_p_list[0] - .ran_param_value_type.ran_p_choice_elem_true() - .ran_param_value.value_int() = 1; + ctrl_msg.ric_ctrl_msg_formats.set_ctrl_msg_format1(); + ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format1().ran_p_list.resize(1); + ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format1().ran_p_list[0].ran_param_id = param_id; + + ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format1() + .ran_p_list[0] + .ran_param_value_type.set_ran_p_choice_elem_false() + .ran_param_value_present = true; + + ctrl_msg.ric_ctrl_msg_formats.ctrl_msg_format1() + .ran_p_list[0] + .ran_param_value_type.ran_p_choice_elem_false() + .ran_param_value.set_value_int() = param_value; srsran::byte_buffer ctrl_msg_buff; asn1::bit_ref bref_msg1(ctrl_msg_buff); diff --git a/tests/unittests/e2/e2_ric_control_procedure_test.cpp b/tests/unittests/e2/e2_ric_control_procedure_test.cpp index 729710f842..f04df203eb 100644 --- a/tests/unittests/e2/e2_ric_control_procedure_test.cpp +++ b/tests/unittests/e2/e2_ric_control_procedure_test.cpp @@ -32,3 +32,35 @@ TEST_F(e2_test_setup, ric_control_procedure_setup) auto ack = msg.pdu.successful_outcome().value.ri_cctrl_ack(); ASSERT_EQ(ack->ra_nfunction_id.value.value, 1); } + +TEST_F(e2_test_setup, ric_control_procedure_setup2) +{ + e2_message request_msg = generate_ric_control_request(test_logger, 2, 6, 12, 12); + e2->handle_message(request_msg); + asn1::cbit_ref bref(gw->last_pdu); + e2_message msg = {}; + if (msg.pdu.unpack(bref) != asn1::SRSASN_SUCCESS) { + printf("Couldn't unpack E2 PDU"); + } + ASSERT_EQ(msg.pdu.type().value, asn1::e2ap::e2_ap_pdu_c::types_opts::successful_outcome); + ASSERT_EQ(msg.pdu.successful_outcome().value.type(), + asn1::e2ap::e2_ap_elem_procs_o::successful_outcome_c::types_opts::ri_cctrl_ack); + auto ack = msg.pdu.successful_outcome().value.ri_cctrl_ack(); + ASSERT_EQ(ack->ra_nfunction_id.value.value, 1); +} + +TEST_F(e2_test_setup, ric_control_procedure_fail) +{ + e2_message request_msg = generate_ric_control_request(test_logger, 2, 6, 1, 12); + e2->handle_message(request_msg); + asn1::cbit_ref bref(gw->last_pdu); + e2_message msg = {}; + if (msg.pdu.unpack(bref) != asn1::SRSASN_SUCCESS) { + printf("Couldn't unpack E2 PDU"); + } + ASSERT_EQ(msg.pdu.type().value, asn1::e2ap::e2_ap_pdu_c::types_opts::unsuccessful_outcome); + ASSERT_EQ(msg.pdu.unsuccessful_outcome().value.type(), + asn1::e2ap::e2_ap_elem_procs_o::unsuccessful_outcome_c::types_opts::ri_cctrl_fail); + auto ack = msg.pdu.unsuccessful_outcome().value.ri_cctrl_fail(); + ASSERT_EQ(ack->ra_nfunction_id.value.value, 1); +} From da25923eaa367e4dd788d57343546049faee07a4 Mon Sep 17 00:00:00 2001 From: tonigelabertfons Date: Mon, 6 Nov 2023 11:19:37 +0100 Subject: [PATCH 021/134] phy: improve unit test coverage of bit packing functions --- lib/srsvec/bit.cpp | 18 +- tests/unittests/srsvec/CMakeLists.txt | 2 +- tests/unittests/srsvec/srsvec_bit_test.cpp | 196 +++++++++++++++------ 3 files changed, 158 insertions(+), 58 deletions(-) diff --git a/lib/srsvec/bit.cpp b/lib/srsvec/bit.cpp index 17a5dc17ad..dfd2031094 100644 --- a/lib/srsvec/bit.cpp +++ b/lib/srsvec/bit.cpp @@ -179,12 +179,15 @@ void srsran::srsvec::bit_unpack(span unpacked, const bit_buffer& packed uint8_t head_bits = packed.extract(offset, nof_head_bits); // Unpack the head. - unpacked = bit_unpack(unpacked, head_bits, nof_head_bits); + span bit_buf = bit_unpack(unpacked, head_bits, nof_head_bits); } unsigned aligned_offset = divide_ceil(offset, 8) * 8; - const bit_buffer aligned_packed = packed.last(packed.size() - aligned_offset).first(unpacked.size()); - bit_unpack(unpacked, aligned_packed); + const bit_buffer aligned_packed = packed.last(packed.size() - aligned_offset).first(unpacked.size() - nof_head_bits); + std::vector temp_unpacked(aligned_packed.size()); + span unpacked_temp = temp_unpacked; + bit_unpack(unpacked_temp, aligned_packed); + std::copy(unpacked_temp.begin(), unpacked_temp.end(), unpacked.begin() + nof_head_bits); } unsigned srsran::srsvec::bit_pack(span& bits, unsigned nof_bits) @@ -282,9 +285,12 @@ void srsran::srsvec::bit_pack(srsran::bit_buffer& packed, unsigned offset, span< packed.insert(head_bits, offset, nof_head_bits); } - unsigned aligned_offset = divide_ceil(offset, 8) * 8; - bit_buffer aligned_packed = packed.last(packed.size() - aligned_offset).first(unpacked.size()); - bit_pack(aligned_packed, unpacked); + unsigned aligned_offset = divide_ceil(offset, 8) * 8; + if (packed.size() != aligned_offset) { + bit_buffer aligned_packed = packed.last(packed.size() - aligned_offset).first(unpacked.size()); + span unpacked_subspan = unpacked.first(aligned_packed.size()); + bit_pack(aligned_packed, unpacked_subspan); + } } void srsran::srsvec::copy_offset(srsran::bit_buffer& output, span input, unsigned startpos) diff --git a/tests/unittests/srsvec/CMakeLists.txt b/tests/unittests/srsvec/CMakeLists.txt index b89220c499..550724ac70 100644 --- a/tests/unittests/srsvec/CMakeLists.txt +++ b/tests/unittests/srsvec/CMakeLists.txt @@ -15,7 +15,7 @@ target_link_libraries(srsvec_aligned_test srsvec srslog) add_test(srsvec_aligned_test srsvec_aligned_test) add_executable(srsvec_bit_test srsvec_bit_test.cpp) -target_link_libraries(srsvec_bit_test srsvec srslog) +target_link_libraries(srsvec_bit_test srsvec srslog gtest gtest_main) add_test(srsvec_bit_test srsvec_bit_test) add_executable(srsvec_compare_test srsvec_compare_test.cpp) diff --git a/tests/unittests/srsvec/srsvec_bit_test.cpp b/tests/unittests/srsvec/srsvec_bit_test.cpp index 884779fc4a..654a6ee6a9 100644 --- a/tests/unittests/srsvec/srsvec_bit_test.cpp +++ b/tests/unittests/srsvec/srsvec_bit_test.cpp @@ -10,41 +10,62 @@ #include "srsran/srsvec/aligned_vec.h" #include "srsran/srsvec/bit.h" -#include "srsran/support/srsran_test.h" +#include #include static std::mt19937 rgen(0); using namespace srsran; -void test_unpack(unsigned N) +namespace { + +using SrsvecBitParams = std::tuple; + +class SrsvecBitFixture : public ::testing::TestWithParam +{ +protected: + unsigned size; + unsigned nbits; + unsigned offset; + + static void SetUpTestSuite() {} + + void SetUp() override + { + // Get test parameters. + auto params = GetParam(); + size = std::get<0>(params); + nbits = size * 8; + offset = size; + } +}; + +TEST_P(SrsvecBitFixture, SrsvecBitTestUnpack) { - std::uniform_int_distribution dist(0, (1U << N) - 1U); + std::uniform_int_distribution dist(0, (1U << size) - 1U); // Create random value to unpack unsigned value = dist(rgen); // Create destination - srsvec::aligned_vec unpacked(N); + srsvec::aligned_vec unpacked(size); // Unpack - span bit_buf = srsvec::bit_unpack(unpacked, value, N); + span bit_buf = srsvec::bit_unpack(unpacked, value, size); // Make sure the allocate dbvector size remains the same while all bits are taken in bit_buff - TESTASSERT_EQ(unpacked.size(), N); - TESTASSERT(bit_buf.empty()); + ASSERT_EQ(unpacked.size(), size); + ASSERT_TRUE(bit_buf.empty()); // Assert each bit - for (unsigned i = 0; i != N; i++) { - uint8_t gold = (value >> (N - 1 - i)) & 1U; - TESTASSERT_EQ(gold, unpacked[i]); + for (unsigned i = 0; i != size; i++) { + uint8_t gold = (value >> (size - 1 - i)) & 1U; + ASSERT_EQ(gold, unpacked[i]); } } -void test_unpack_vector(unsigned N) +TEST_P(SrsvecBitFixture, SrsvecBitTestUnpackVector) { - unsigned nbytes = N; - unsigned nbits = nbytes * 8; std::uniform_int_distribution dist(0, UINT8_MAX); // Create random value to unpack @@ -64,38 +85,36 @@ void test_unpack_vector(unsigned N) srsvec::bit_unpack(unpacked, packed); // Assert each bit - TESTASSERT_EQ(span(expected), span(unpacked)); + ASSERT_EQ(span(expected), span(unpacked)); } -void test_pack(unsigned N) +TEST_P(SrsvecBitFixture, SrsvecBitTestPack) { std::uniform_int_distribution dist(0, 1U); // Create unpacked data - srsvec::aligned_vec unpacked(N); + srsvec::aligned_vec unpacked(size); for (uint8_t& value : unpacked) { value = dist(rgen); } // Pack span bit_buf = unpacked; - unsigned value = srsvec::bit_pack(bit_buf, N); + unsigned value = srsvec::bit_pack(bit_buf, size); // Make sure the allocate dbvector size remains the same while all bits are taken in bit_buff - TESTASSERT_EQ(unpacked.size(), N); - TESTASSERT(bit_buf.empty()); + ASSERT_EQ(unpacked.size(), size); + ASSERT_TRUE(bit_buf.empty()); // Assert each bit - for (unsigned i = 0; i != N; ++i) { - uint8_t gold = (value >> (N - 1 - i)) & 1U; - TESTASSERT_EQ(gold, unpacked[i]); + for (unsigned i = 0; i != size; ++i) { + uint8_t gold = (value >> (size - 1 - i)) & 1U; + ASSERT_EQ(gold, unpacked[i]); } } -void test_pack_vector(unsigned N) +TEST_P(SrsvecBitFixture, SrsvecBitTestPackVector) { - unsigned nbytes = N; - unsigned nbits = nbytes * 8; std::uniform_int_distribution dist(0, 1U); // Create unpacked data @@ -113,14 +132,52 @@ void test_pack_vector(unsigned N) // Assert each bit for (unsigned i = 0; i != nbits; i++) { uint8_t gold = packed.extract(i, 1); - TESTASSERT_EQ(gold, unpacked[i]); + ASSERT_EQ(gold, unpacked[i]); + } +} + +TEST_P(SrsvecBitFixture, SrsvecBitTestPackFullVector) +{ + std::uniform_int_distribution dist(0, 1U); + + // Create unpacked data + srsvec::aligned_vec unpacked(size); + for (uint8_t& value : unpacked) { + value = dist(rgen); + } + + unsigned packed = srsvec::bit_pack(unpacked); + + for (unsigned i = 0; i < size; i++) { + uint8_t gold = (packed >> (size - 1 - i)) & 1U; + ASSERT_EQ(gold, unpacked[i]); } } -void test_copy_offset_vector(unsigned nof_bytes) +TEST_P(SrsvecBitFixture, SrsvecBitTestPackOffsetVector) { - unsigned nof_bits = nof_bytes * 8; + std::uniform_int_distribution dist(0, 1U); + + // Create unpacked data + srsvec::aligned_vec unpacked(nbits); + for (uint8_t& value : unpacked) { + value = dist(rgen); + } + + // Create destination + dynamic_bit_buffer packed(nbits + offset); + srsran::srsvec::bit_pack(packed, offset, unpacked); + + for (unsigned i = 0; i < (nbits - offset); i++) { + uint8_t expected_bit = unpacked[i]; + uint8_t actual_bit = packed.extract(offset + i, 1); + ASSERT_EQ(expected_bit, actual_bit); + } +} + +TEST_P(SrsvecBitFixture, SrsvecBitTestCopyOffsetVector) +{ std::uniform_int_distribution dist_byte(0, 255U); // Read offsets in bits. @@ -128,11 +185,11 @@ void test_copy_offset_vector(unsigned nof_bytes) for (auto read_offset : read_offsets) { // Determine source buffer dimensions. - unsigned source_nof_bytes = nof_bytes + divide_ceil(read_offset, 8); + unsigned source_nof_bytes = size + divide_ceil(read_offset, 8); // Create source and destination buffers. std::vector source(source_nof_bytes); - dynamic_bit_buffer destination(nof_bits); + dynamic_bit_buffer destination(nbits); // Fill source buffer with random bits. for (auto& byte : source) { @@ -143,7 +200,7 @@ void test_copy_offset_vector(unsigned nof_bytes) srsvec::copy_offset(destination, source, read_offset); // Assert each bit. - for (unsigned i_bit = 0; i_bit != nof_bits; ++i_bit) { + for (unsigned i_bit = 0; i_bit != nbits; ++i_bit) { // Source byte to extract. unsigned i_byte = (i_bit + read_offset) / 8; @@ -153,15 +210,13 @@ void test_copy_offset_vector(unsigned nof_bytes) // Destination buffer bit where the source bit should have been copied. uint8_t copy_bit = destination.extract(i_bit, 1); - TESTASSERT_EQ(source_bit, copy_bit); + ASSERT_EQ(source_bit, copy_bit); } } } -void test_copy_offset_bit_buffers(unsigned nof_bytes) +TEST_P(SrsvecBitFixture, SrsvecBitTestCopyOffsetBitBuffers) { - unsigned nof_bits = nof_bytes * 8; - std::uniform_int_distribution dist(0, 1U); // Read and write offsets. All combinations will be tested. @@ -171,8 +226,8 @@ void test_copy_offset_bit_buffers(unsigned nof_bytes) for (auto read_offset : read_offsets) { for (auto write_offset : write_offsets) { // Determine buffer dimensions. - unsigned source_size = nof_bits + read_offset; - unsigned dest_size = nof_bits + write_offset; + unsigned source_size = nbits + read_offset; + unsigned dest_size = nbits + write_offset; // Create source and destination buffers. dynamic_bit_buffer source(source_size); @@ -184,32 +239,71 @@ void test_copy_offset_bit_buffers(unsigned nof_bytes) } // Copy from source to destination. - srsvec::copy_offset(destination, write_offset, source, read_offset, nof_bits); + srsvec::copy_offset(destination, write_offset, source, read_offset, nbits); // Assert each bit. - for (unsigned i_bit = 0; i_bit != nof_bits; ++i_bit) { + for (unsigned i_bit = 0; i_bit != nbits; ++i_bit) { // Source bit. uint8_t source_bit = source.extract(i_bit + read_offset, 1); // Destination buffer bit where the source bit should have been copied. uint8_t copy_bit = destination.extract(i_bit + write_offset, 1); - TESTASSERT_EQ(source_bit, copy_bit); + ASSERT_EQ(source_bit, copy_bit); } } } } -int main() +TEST_P(SrsvecBitFixture, SrsvecBitTestUnpackVectorWithRemainder) { - std::vector sizes = {1, 5, 7, 19, 23, 32}; - - for (unsigned N : sizes) { - test_unpack(N); - test_unpack_vector(N); - test_pack(N); - test_pack_vector(N); - test_copy_offset_vector(N); - test_copy_offset_bit_buffers(N); + std::uniform_int_distribution dist(0, UINT8_MAX); + + // Create random value to unpack + dynamic_bit_buffer packed(15); + for (uint8_t& value : packed.get_buffer()) { + value = dist(rgen); } -} \ No newline at end of file + + // Create destination + srsvec::aligned_vec unpacked(15); + + // Generate expected values. + srsvec::aligned_vec expected(15); + std::generate(expected.begin(), expected.end(), [&, index = 0]() mutable { return packed.extract(index++, 1); }); + + // Unpack + srsvec::bit_unpack(unpacked, packed); + + // Assert each bit + ASSERT_EQ(span(expected), span(unpacked)); +} + +TEST_P(SrsvecBitFixture, SrsvecBitTestUnpackVectorOffset) +{ + // std::uniform_int_distribution dist(0, (1U << size) - 1U); + std::uniform_int_distribution dist(0, 255U); + + // Create random value to unpack + dynamic_bit_buffer packed(nbits); + for (uint8_t& value : packed.get_buffer()) { + value = dist(rgen); + } + + // Create destination + srsvec::aligned_vec unpacked(nbits - offset); + + // Generate expected values. + srsvec::aligned_vec expected(nbits - offset); + std::generate(expected.begin(), expected.end(), [&, index = offset]() mutable { return packed.extract(index++, 1); }); + + // Unpack + srsvec::bit_unpack(unpacked, packed, offset); + + // Assert each bit + ASSERT_EQ(span(expected), span(unpacked)); +} + +INSTANTIATE_TEST_SUITE_P(SrsvecBitTest, SrsvecBitFixture, ::testing::Combine(::testing::Values(1, 5, 7, 19, 23, 32))); + +} // namespace \ No newline at end of file From 3a2532422315d36a252dde7b7a5edc8f9101aa45 Mon Sep 17 00:00:00 2001 From: tonigelabertfons Date: Tue, 2 Jan 2024 12:10:09 +0100 Subject: [PATCH 022/134] phy: review improved unit test coverage of bit packing functions --- lib/srsvec/bit.cpp | 31 +++++++++++++++------- tests/unittests/srsvec/srsvec_bit_test.cpp | 11 ++++---- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/lib/srsvec/bit.cpp b/lib/srsvec/bit.cpp index dfd2031094..dc1a20c6a7 100644 --- a/lib/srsvec/bit.cpp +++ b/lib/srsvec/bit.cpp @@ -172,6 +172,13 @@ void srsran::srsvec::bit_unpack(span unpacked, const bit_buffer& packed void srsran::srsvec::bit_unpack(span unpacked, const bit_buffer& packed, unsigned offset) { + srsran_assert(unpacked.size() <= packed.size() - offset, + "The unpacked number of bits (i.e.{}) must be equal or lower to the number of packed bits - offset " + "(i.e., {}-{}).", + unpacked.size(), + packed.size(), + offset); + // Calculate the number of bits to align the packed data to byte boundary. unsigned nof_head_bits = std::min((8 - (offset % 8)) % 8, static_cast(unpacked.size())); if (nof_head_bits != 0) { @@ -179,15 +186,14 @@ void srsran::srsvec::bit_unpack(span unpacked, const bit_buffer& packed uint8_t head_bits = packed.extract(offset, nof_head_bits); // Unpack the head. - span bit_buf = bit_unpack(unpacked, head_bits, nof_head_bits); + unpacked = bit_unpack(unpacked, head_bits, nof_head_bits); } - unsigned aligned_offset = divide_ceil(offset, 8) * 8; - const bit_buffer aligned_packed = packed.last(packed.size() - aligned_offset).first(unpacked.size() - nof_head_bits); - std::vector temp_unpacked(aligned_packed.size()); - span unpacked_temp = temp_unpacked; - bit_unpack(unpacked_temp, aligned_packed); - std::copy(unpacked_temp.begin(), unpacked_temp.end(), unpacked.begin() + nof_head_bits); + unsigned aligned_offset = divide_ceil(offset, 8) * 8; + if (packed.size() != aligned_offset) { + const bit_buffer aligned_packed = packed.last(packed.size() - aligned_offset).first(unpacked.size()); + bit_unpack(unpacked, aligned_packed); + } } unsigned srsran::srsvec::bit_pack(span& bits, unsigned nof_bits) @@ -275,6 +281,12 @@ void srsran::srsvec::bit_pack(bit_buffer& packed, span unpacked) void srsran::srsvec::bit_pack(srsran::bit_buffer& packed, unsigned offset, span unpacked) { + srsran_assert( + packed.size() >= unpacked.size() + offset, + "The packed number of bits (i.e.{}) must be equal or higher to the number of packed bits + offset (i.e., {}+{}).", + packed.size(), + unpacked.size(), + offset); // Calculate the number of bits to align the packed data to byte boundary. unsigned nof_head_bits = std::min((8 - (offset % 8)) % 8, static_cast(unpacked.size())); if (nof_head_bits != 0) { @@ -287,9 +299,8 @@ void srsran::srsvec::bit_pack(srsran::bit_buffer& packed, unsigned offset, span< unsigned aligned_offset = divide_ceil(offset, 8) * 8; if (packed.size() != aligned_offset) { - bit_buffer aligned_packed = packed.last(packed.size() - aligned_offset).first(unpacked.size()); - span unpacked_subspan = unpacked.first(aligned_packed.size()); - bit_pack(aligned_packed, unpacked_subspan); + bit_buffer aligned_packed = packed.last(packed.size() - aligned_offset).first(unpacked.size()); + bit_pack(aligned_packed, unpacked); } } diff --git a/tests/unittests/srsvec/srsvec_bit_test.cpp b/tests/unittests/srsvec/srsvec_bit_test.cpp index 654a6ee6a9..0a62ffdac3 100644 --- a/tests/unittests/srsvec/srsvec_bit_test.cpp +++ b/tests/unittests/srsvec/srsvec_bit_test.cpp @@ -19,7 +19,7 @@ using namespace srsran; namespace { -using SrsvecBitParams = std::tuple; +using SrsvecBitParams = unsigned; class SrsvecBitFixture : public ::testing::TestWithParam { @@ -34,7 +34,7 @@ class SrsvecBitFixture : public ::testing::TestWithParam { // Get test parameters. auto params = GetParam(); - size = std::get<0>(params); + size = params; nbits = size * 8; offset = size; } @@ -186,10 +186,11 @@ TEST_P(SrsvecBitFixture, SrsvecBitTestCopyOffsetVector) for (auto read_offset : read_offsets) { // Determine source buffer dimensions. unsigned source_nof_bytes = size + divide_ceil(read_offset, 8); + unsigned source_nof_bits = source_nof_bytes * 8; // Create source and destination buffers. std::vector source(source_nof_bytes); - dynamic_bit_buffer destination(nbits); + dynamic_bit_buffer destination(source_nof_bits - read_offset); // Fill source buffer with random bits. for (auto& byte : source) { @@ -200,7 +201,7 @@ TEST_P(SrsvecBitFixture, SrsvecBitTestCopyOffsetVector) srsvec::copy_offset(destination, source, read_offset); // Assert each bit. - for (unsigned i_bit = 0; i_bit != nbits; ++i_bit) { + for (unsigned i_bit = 0; i_bit != (source_nof_bits - read_offset); ++i_bit) { // Source byte to extract. unsigned i_byte = (i_bit + read_offset) / 8; @@ -304,6 +305,6 @@ TEST_P(SrsvecBitFixture, SrsvecBitTestUnpackVectorOffset) ASSERT_EQ(span(expected), span(unpacked)); } -INSTANTIATE_TEST_SUITE_P(SrsvecBitTest, SrsvecBitFixture, ::testing::Combine(::testing::Values(1, 5, 7, 19, 23, 32))); +INSTANTIATE_TEST_SUITE_P(SrsvecBitTest, SrsvecBitFixture, ::testing::Values(1, 5, 7, 19, 23, 32)); } // namespace \ No newline at end of file From df5d8075d2935cb9a14168f5009c8f009e46bdcb Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 2 Jan 2024 15:15:40 +0100 Subject: [PATCH 023/134] du_high: improve du_high_benchmark to avoid saturation of the buffer pool, avoid saturation of task queues and make threading model better mimic gnb app --- include/srsran/support/async/execute_on.h | 11 +- .../srsran/support/executors/task_worker.h | 4 +- .../benchmarks/du_high/du_high_benchmark.cpp | 225 +++++++++++++----- 3 files changed, 178 insertions(+), 62 deletions(-) diff --git a/include/srsran/support/async/execute_on.h b/include/srsran/support/async/execute_on.h index e829ccaa88..94c2f1b1d8 100644 --- a/include/srsran/support/async/execute_on.h +++ b/include/srsran/support/async/execute_on.h @@ -108,12 +108,13 @@ auto offload_to_executor(DispatchTaskExecutor& dispatch_exec, ResumeTaskExecutor void await_suspend(coro_handle<> suspending_coro) { - continuation = suspending_coro; - dispatch_exec.execute([this]() mutable { - result = task(); - bool dispatched = resume_exec.execute([this]() { continuation.resume(); }); - srsran_assert(dispatched, "Failed to dispatch task"); + continuation = suspending_coro; + bool dispatched1 = dispatch_exec.execute([this]() mutable { + result = task(); + bool dispatched2 = resume_exec.execute([this]() { continuation.resume(); }); + srsran_assert(dispatched2, "Failed to dispatch task"); }); + srsran_assert(dispatched1, "Failed to dispatch task"); } ResultType await_resume() { return result; } diff --git a/include/srsran/support/executors/task_worker.h b/include/srsran/support/executors/task_worker.h index 798ab7e621..9f0db85583 100644 --- a/include/srsran/support/executors/task_worker.h +++ b/include/srsran/support/executors/task_worker.h @@ -129,7 +129,7 @@ class general_task_worker_executor final : public task_executor general_task_worker_executor(general_task_worker& worker_) : worker(&worker_) {} - bool execute(unique_task task) override + SRSRAN_NODISCARD bool execute(unique_task task) override { if (can_run_task_inline()) { // Same thread. Run task right away. @@ -139,7 +139,7 @@ class general_task_worker_executor final : public task_executor return defer(std::move(task)); } - bool defer(unique_task task) override { return worker->push_task(std::move(task)); } + SRSRAN_NODISCARD bool defer(unique_task task) override { return worker->push_task(std::move(task)); } /// Determine whether the caller is in the same thread as the worker this executor adapts. bool can_run_task_inline() const { return worker->get_id() == std::this_thread::get_id(); } diff --git a/tests/benchmarks/du_high/du_high_benchmark.cpp b/tests/benchmarks/du_high/du_high_benchmark.cpp index 60f932d742..dfe7437edf 100644 --- a/tests/benchmarks/du_high/du_high_benchmark.cpp +++ b/tests/benchmarks/du_high/du_high_benchmark.cpp @@ -20,6 +20,7 @@ #include "srsran/f1u/du/f1u_gateway.h" #include "srsran/support/benchmark_utils.h" #include "srsran/support/event_tracing.h" +#include "srsran/support/executors/priority_task_worker.h" #include "srsran/support/executors/task_worker.h" #include "srsran/support/test_utils.h" @@ -34,10 +35,16 @@ struct bench_params { unsigned nof_ues = 1; /// \brief Set duplex mode (FDD or TDD) to use for benchmark. duplex_mode dplx_mode = duplex_mode::FDD; - /// \brief Set size of the DL buffer status to push for DL Tx. Setting this value to 0 will disable DL Tx. - unsigned dl_buffer_state_bytes = 1500; + /// \brief Set the number of bytes pushed to the DU DL F1-U interface per slot. + /// + /// Setting this value to 0 will disable DL Tx. + /// If the air interface cannot keep up with the DL F1-U PDU rate, the F1-U will be throttled, to avoid depleting + /// the buffer pool. + unsigned dl_bytes_per_slot = 1500; /// \brief Set size of the UL Buffer status report to push for UL Tx. Setting this value to 0 will disable UL Tx. unsigned ul_bsr_bytes = 0; + /// \brief Logical cores used by the "du_cell" thread. + std::vector du_cell_cores = {0, 1}; }; static void usage(const char* prog, const bench_params& params) @@ -48,19 +55,20 @@ static void usage(const char* prog, const bench_params& params) fmt::print("\t-R Repetitions [Default {}]\n", params.nof_repetitions); fmt::print("\t-U Nof. DU UEs [Default {}]\n", params.nof_ues); fmt::print("\t-D Duplex mode (FDD/TDD) [Default {}]\n", to_string(params.dplx_mode)); - fmt::print( - "\t-d Size of the DL buffer status to push for DL Tx. Setting this value to 0 will disable DL Tx. [Default {}]\n", - params.dl_buffer_state_bytes); + fmt::print("\t-d Number of bytes pushed to the DU DL F1-U interface every slot. Setting this value to 0 will " + "disable DL Tx. [Default {}]\n", + params.dl_bytes_per_slot); fmt::print("\t-u Size of the UL Buffer status report to push for UL Tx. Setting this value to 0 will disable UL Tx. " "[Default {}]\n", params.ul_bsr_bytes); + fmt::print("\t-c \"du_cell\" cores that the benchmark should use [Default 0,1]\n"); fmt::print("\t-h Show this message\n"); } static void parse_args(int argc, char** argv, bench_params& params) { int opt = 0; - while ((opt = getopt(argc, argv, "R:U:D:d:u:h")) != -1) { + while ((opt = getopt(argc, argv, "R:U:D:d:u:c:h")) != -1) { switch (opt) { case 'R': params.nof_repetitions = std::strtol(optarg, nullptr, 10); @@ -80,11 +88,24 @@ static void parse_args(int argc, char** argv, bench_params& params) break; } case 'd': - params.dl_buffer_state_bytes = std::strtol(optarg, nullptr, 10); + params.dl_bytes_per_slot = std::strtol(optarg, nullptr, 10); break; case 'u': params.ul_bsr_bytes = std::strtol(optarg, nullptr, 10); break; + case 'c': { + std::string optstr{optarg}; + if (optstr.find(",") != std::string::npos) { + size_t pos = optstr.find(","); + while (pos != std::string::npos) { + params.du_cell_cores.push_back(std::strtol(optstr.substr(0, pos).c_str(), nullptr, 10)); + optstr = optstr.substr(pos + 1); + pos = optstr.find(","); + } + } else { + params.du_cell_cores = {(unsigned)std::strtol(optstr.c_str(), nullptr, 10)}; + } + } break; case 'h': default: usage(argv[0], params); @@ -93,6 +114,21 @@ static void parse_args(int argc, char** argv, bench_params& params) } } +class dummy_metrics_handler : public scheduler_ue_metrics_notifier +{ +public: + void report_metrics(span ue_metrics) override + { + unsigned sum_dl_bs = 0; + for (const auto& ue : ue_metrics) { + sum_dl_bs += ue.dl_bs; + } + tot_dl_bs.store(sum_dl_bs, std::memory_order_relaxed); + } + + std::atomic tot_dl_bs{0}; +}; + /// \brief Simulator of the CU-CP from the perspective of the DU. This class should reply to the F1AP messages /// that the DU sends in order for the DU normal operation to proceed. class cu_cp_simulator : public srs_du::f1c_connection_client @@ -232,24 +268,70 @@ class cu_up_simulator : public f1u_du_gateway /// \brief Instantiation of the DU-high workers and executors for the benchmark. struct du_high_single_cell_worker_manager { - static const uint32_t task_worker_queue_size = 10000; + using ue_worker_type = + priority_task_worker; + static const uint32_t task_worker_queue_size = 100000; + + explicit du_high_single_cell_worker_manager(span du_cell_cores) : + ctrl_worker("du_ctrl", + task_worker_queue_size, + os_thread_realtime_priority::max() - 1, + get_other_affinity_mask(du_cell_cores)), + cell_worker("du_cell", + task_worker_queue_size, + os_thread_realtime_priority::max(), + get_du_cell_affinity_mask(du_cell_cores)), + ue_worker("du_ue", + {task_worker_queue_size, task_worker_queue_size}, + std::chrono::microseconds{500}, + os_thread_realtime_priority::max() - 2, + get_other_affinity_mask(du_cell_cores)), + ue_ctrl_exec(make_priority_task_worker_executor(ue_worker)), + dl_exec(make_priority_task_worker_executor(ue_worker)), + ul_exec(make_priority_task_worker_executor(ue_worker)) + { + } void stop() { ctrl_worker.stop(); - dl_worker.stop(); - ul_worker.stop(); + cell_worker.stop(); + ue_worker.stop(); + } + + static os_sched_affinity_bitmask get_du_cell_affinity_mask(span du_cell_cores) + { + os_sched_affinity_bitmask mask; + for (auto core : du_cell_cores) { + mask.set(core); + } + return mask; } - task_worker ctrl_worker{"CTRL", task_worker_queue_size}; - task_worker dl_worker{"DU-DL#0", task_worker_queue_size}; - task_worker ul_worker{"DU-UL#0", task_worker_queue_size}; - task_worker_executor ctrl_exec{ctrl_worker}; - task_worker_executor dl_exec{dl_worker}; - task_worker_executor ul_exec{ul_worker}; - du_high_executor_mapper_impl du_high_exec_mapper{ - std::make_unique(std::initializer_list{&dl_exec}), - std::make_unique(std::initializer_list{&ul_exec}), + static os_sched_affinity_bitmask get_other_affinity_mask(span du_cell_cores) + { + os_sched_affinity_bitmask mask; + for (unsigned i = 0; i != mask.size(); ++i) { + if (std::find(du_cell_cores.begin(), du_cell_cores.end(), i) == du_cell_cores.end()) { + mask.set(i); + } + } + return mask; + } + + task_worker ctrl_worker; + task_worker cell_worker; + ue_worker_type ue_worker; + task_worker_executor ctrl_exec{ctrl_worker}; + task_worker_executor cell_exec{cell_worker}; + priority_task_worker_executor ue_ctrl_exec; + priority_task_worker_executor dl_exec; + priority_task_worker_executor ul_exec; + du_high_executor_mapper_impl du_high_exec_mapper{ + std::make_unique(std::initializer_list{&cell_exec}), + std::make_unique(std::initializer_list{&ue_ctrl_exec}, + std::initializer_list{&ul_exec}, + std::initializer_list{&dl_exec}), ctrl_exec, ctrl_exec, ctrl_exec}; @@ -322,11 +404,18 @@ class phy_simulator : public mac_result_notifier, public mac_cell_result_notifie /// \brief TestBench for the DU-high. class du_high_bench { + static const unsigned DL_PDU_SIZE = 1500; + public: du_high_bench(unsigned dl_buffer_state_bytes_, unsigned ul_bsr_bytes_, + span du_cell_cores, const cell_config_builder_params& builder_params = {}) : - params(builder_params), dl_buffer_state_bytes(dl_buffer_state_bytes_), ul_bsr_bytes(ul_bsr_bytes_) + params(builder_params), + dl_buffer_state_bytes(dl_buffer_state_bytes_), + nof_dl_pdus_per_slot(divide_ceil(dl_buffer_state_bytes, DL_PDU_SIZE)), + workers(du_cell_cores), + ul_bsr_bytes(ul_bsr_bytes_) { // Set slot point based on the SCS. next_sl_tx = slot_point{to_numerology_value(params.scs_common), 0}; @@ -342,19 +431,20 @@ class du_high_bench bsr_mac_subpdu.append(lbsr_buff_sz); // Instantiate a DU-high object. - cfg.gnb_du_id = 1; - cfg.gnb_du_name = fmt::format("srsgnb{}", cfg.gnb_du_id); - cfg.du_bind_addr = fmt::format("127.0.0.{}", cfg.gnb_du_id); - cfg.exec_mapper = &workers.du_high_exec_mapper; - cfg.f1c_client = &sim_cu_cp; - cfg.f1u_gw = &sim_cu_up; - cfg.phy_adapter = &sim_phy; - cfg.timers = &timers; - cfg.cells = {config_helpers::make_default_du_cell_config(params)}; - cfg.sched_cfg = config_helpers::make_default_scheduler_expert_config(); - cfg.qos = config_helpers::make_default_du_qos_config_list(1000); - cfg.mac_p = &mac_pcap; - cfg.rlc_p = &rlc_pcap; + cfg.gnb_du_id = 1; + cfg.gnb_du_name = fmt::format("srsgnb{}", cfg.gnb_du_id); + cfg.du_bind_addr = fmt::format("127.0.0.{}", cfg.gnb_du_id); + cfg.exec_mapper = &workers.du_high_exec_mapper; + cfg.f1c_client = &sim_cu_cp; + cfg.f1u_gw = &sim_cu_up; + cfg.phy_adapter = &sim_phy; + cfg.timers = &timers; + cfg.cells = {config_helpers::make_default_du_cell_config(params)}; + cfg.sched_cfg = config_helpers::make_default_scheduler_expert_config(); + cfg.qos = config_helpers::make_default_du_qos_config_list(1000); + cfg.mac_p = &mac_pcap; + cfg.rlc_p = &rlc_pcap; + cfg.sched_ue_metrics_notifier = &metrics_handler; // Increase nof. PUCCH resources to accommodate more UEs. cfg.cells[0].pucch_cfg.nof_sr_resources = 30; @@ -368,7 +458,7 @@ class du_high_bench du_hi = std::make_unique(cfg); // Create PDCP PDU. - pdcp_pdu.append(test_rgen::random_vector(dl_buffer_state_bytes)); + pdcp_pdu.append(test_rgen::random_vector(DL_PDU_SIZE)); // Create MAC PDU. mac_pdu.append( test_rgen::random_vector(buff_size_field_to_bytes(lbsr_buff_sz, srsran::bsr_format::LONG_BSR))); @@ -499,14 +589,27 @@ class du_high_bench // \brief Push a DL PDUs to DU-high via F1-U interface. void push_pdcp_pdus() { - // Early return. + static uint32_t pdcp_sn = 0; + if (dl_buffer_state_bytes == 0) { + // Early return. + return; + } + if (metrics_handler.tot_dl_bs > 1e5) { + // Saturation of the DU DL detected. We throttle the F1-U interface to avoid depleting the byte buffer pool. return; } - for (const auto& du_notif : sim_cu_up.du_notif_list) { - for (unsigned i = 0; i != 10; ++i) { - du_notif->on_new_sdu(pdcp_tx_pdu{.buf = pdcp_pdu.copy(), .pdcp_sn = 0}); + while (not workers.dl_exec.defer([this]() { + for (const auto& du_notif : sim_cu_up.du_notif_list) { + for (unsigned i = 0; i != nof_dl_pdus_per_slot; ++i) { + pdcp_sn = (pdcp_sn + 1) % (1U << 18U); + du_notif->on_new_sdu(pdcp_tx_pdu{.buf = pdcp_pdu.deep_copy(), .pdcp_sn = pdcp_sn}); + } } + })) { + // keep trying to push new PDUs. + // This also serves as a way to slow down the slot indication rate, to better capture a RT deployment. + std::this_thread::sleep_for(std::chrono::microseconds{500}); } } @@ -715,9 +818,15 @@ class du_high_bench } } - unsigned tx_rx_delay = 4; - cell_config_builder_params params; - du_high_configuration cfg{}; + const unsigned tx_rx_delay = 4; + cell_config_builder_params params; + du_high_configuration cfg{}; + /// Size of the DL buffer status to push for DL Tx. + unsigned dl_buffer_state_bytes; + const unsigned nof_dl_pdus_per_slot; + + srslog::basic_logger& test_logger = srslog::fetch_basic_logger("TEST"); + dummy_metrics_handler metrics_handler; cu_cp_simulator sim_cu_cp; cu_up_simulator sim_cu_up; phy_simulator sim_phy; @@ -752,8 +861,6 @@ class du_high_bench // NOTE: LBSR buffer size is populated in the constructor. byte_buffer bsr_mac_subpdu{0x3e, 0x02, 0x02}; - /// Size of the DL buffer status to push for DL Tx. - unsigned dl_buffer_state_bytes; /// Size of the UL Buffer status report to push for UL Tx. unsigned ul_bsr_bytes; }; @@ -765,7 +872,7 @@ static cell_config_builder_params generate_custom_cell_config_builder_params(dup params.scs_common = dplx_mode == duplex_mode::FDD ? subcarrier_spacing::kHz15 : subcarrier_spacing::kHz30; params.dl_arfcn = dplx_mode == duplex_mode::FDD ? 530000 : 520002; params.band = band_helper::get_band_from_dl_arfcn(params.dl_arfcn); - params.channel_bw_mhz = bs_channel_bandwidth_fr1::MHz20; + params.channel_bw_mhz = bs_channel_bandwidth_fr1::MHz100; const unsigned nof_crbs = band_helper::get_n_rbs_from_bw( params.channel_bw_mhz, params.scs_common, band_helper::get_freq_range(*params.band)); static const uint8_t ss0_idx = 0; @@ -797,15 +904,21 @@ static cell_config_builder_params generate_custom_cell_config_builder_params(dup } /// \brief Benchmark DU-high with DL and/or UL only traffic using an RLC UM bearer. -void benchmark_dl_ul_only_rlc_um(benchmarker& bm, - unsigned nof_ues, - duplex_mode dplx_mode, - unsigned dl_buffer_state_bytes, - unsigned ul_bsr_bytes) +void benchmark_dl_ul_only_rlc_um(benchmarker& bm, + unsigned nof_ues, + duplex_mode dplx_mode, + unsigned dl_buffer_state_bytes, + unsigned ul_bsr_bytes, + span du_cell_cores) { - auto benchname = fmt::format("DL and/or UL, {} UE, RLC UM", nof_ues); + auto benchname = fmt::format("{}{}{}, {} UEs, RLC UM", + dl_buffer_state_bytes > 0 ? "DL" : "", + std::min(dl_buffer_state_bytes, ul_bsr_bytes) > 0 ? "+" : "", + ul_bsr_bytes > 0 ? "UL" : "", + nof_ues); test_delimit_logger test_delim(benchname.c_str()); - du_high_bench bench{dl_buffer_state_bytes, ul_bsr_bytes, generate_custom_cell_config_builder_params(dplx_mode)}; + du_high_bench bench{ + dl_buffer_state_bytes, ul_bsr_bytes, du_cell_cores, generate_custom_cell_config_builder_params(dplx_mode)}; for (unsigned ue_count = 0; ue_count < nof_ues; ++ue_count) { bench.add_ue(to_du_ue_index(ue_count)); } @@ -831,7 +944,7 @@ void benchmark_dl_ul_only_rlc_um(benchmarker& bm, srslog::flush(); const unsigned sim_time_msec = bench.slot_count / get_nof_slots_per_subframe(bench.cfg.cells[0].scs_common); - fmt::print("Stats: slots={}, #PDSCHs={}, dl_bitrate={:.2} Mbps, #PUSCHs={}, ul_bitrate={:.2} Mbps\n", + fmt::print("\nStats: slots={}, #PDSCHs={}, dl_bitrate={:.3} Mbps, #PUSCHs={}, ul_bitrate={:.3} Mbps\n", bench.slot_count, bench.sim_phy.nof_dl_grants, bench.sim_phy.nof_dl_bytes * 8 * 1.0e-6 / (sim_time_msec * 1.0e-3), @@ -841,10 +954,11 @@ void benchmark_dl_ul_only_rlc_um(benchmarker& bm, int main(int argc, char** argv) { - static const std::size_t byte_buffer_nof_segments = 1048576; - static const std::size_t byte_buffer_segment_size = 1024; + static const std::size_t byte_buffer_nof_segments = 1U << 18U; + static const std::size_t byte_buffer_segment_size = 2048; // Set DU-high logging. + srslog::fetch_basic_logger("TEST").set_level(srslog::basic_levels::warning); srslog::fetch_basic_logger("RLC").set_level(srslog::basic_levels::warning); srslog::fetch_basic_logger("MAC", true).set_level(srslog::basic_levels::warning); srslog::fetch_basic_logger("SCHED", true).set_level(srslog::basic_levels::warning); @@ -864,7 +978,8 @@ int main(int argc, char** argv) benchmarker bm("DU-High", params.nof_repetitions); // Run scenarios. - benchmark_dl_ul_only_rlc_um(bm, params.nof_ues, params.dplx_mode, params.dl_buffer_state_bytes, params.ul_bsr_bytes); + benchmark_dl_ul_only_rlc_um( + bm, params.nof_ues, params.dplx_mode, params.dl_bytes_per_slot, params.ul_bsr_bytes, params.du_cell_cores); // Output results. bm.print_percentiles_time(); From 2d47831473fb55aa3ad9a4136f4edc5d73d94184 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 2 Jan 2024 17:52:00 +0100 Subject: [PATCH 024/134] du_high: output number of pdus per slot in du_high_benchmark and fix dl buffer state updates --- .../ue_scheduling/ue_cell_grid_allocator.cpp | 6 +- .../benchmarks/du_high/du_high_benchmark.cpp | 170 +++++++++++++----- 2 files changed, 124 insertions(+), 52 deletions(-) diff --git a/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp b/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp index 338b8c4154..12f191960e 100644 --- a/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp +++ b/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp @@ -156,9 +156,9 @@ alloc_outcome ue_cell_grid_allocator::allocate_dl_grant(const ue_pdsch_grant& gr } // 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.warning("ue={} rnti={}: Failed to allocate PDSCH. Cause: No space available in scheduler output list", - u.ue_index, - u.crnti); + logger.info("ue={} rnti={}: Failed to allocate PDSCH. Cause: No space available in scheduler output list", + u.ue_index, + u.crnti); return alloc_outcome::skip_slot; } diff --git a/tests/benchmarks/du_high/du_high_benchmark.cpp b/tests/benchmarks/du_high/du_high_benchmark.cpp index dfe7437edf..92391c6cd0 100644 --- a/tests/benchmarks/du_high/du_high_benchmark.cpp +++ b/tests/benchmarks/du_high/du_high_benchmark.cpp @@ -126,6 +126,8 @@ class dummy_metrics_handler : public scheduler_ue_metrics_notifier tot_dl_bs.store(sum_dl_bs, std::memory_order_relaxed); } + // This metric is used by benchmark to determine whether to push more traffic to DU F1-U. Therefore, it needs to be + // protected. std::atomic tot_dl_bs{0}; }; @@ -337,6 +339,31 @@ struct du_high_single_cell_worker_manager { ctrl_exec}; }; +/// \brief Metrics collected from the results passed by the MAC to the lower layers. +struct phy_metrics { + unsigned slot_count = 0; + unsigned slot_dl_count = 0; + unsigned nof_dl_grants = 0; + uint64_t nof_dl_bytes = 0; + unsigned slot_ul_count = 0; + unsigned nof_ul_grants = 0; + uint64_t nof_ul_bytes = 0; + + unsigned total_subframes_elapsed(subcarrier_spacing scs) { return slot_count / get_nof_slots_per_subframe(scs); } + + double dl_Mbps(subcarrier_spacing scs) + { + unsigned sim_time_msec = total_subframes_elapsed(scs); + return nof_dl_bytes * 8 * 1.0e-6 / (sim_time_msec * 1.0e-3); + } + + double ul_Mbps(subcarrier_spacing scs) + { + unsigned sim_time_msec = total_subframes_elapsed(scs); + return nof_ul_bytes * 8 * 1.0e-6 / (sim_time_msec * 1.0e-3); + } +}; + /// \brief Emulator of the PHY, FAPI and UE from the perspective of the DU-high. This class should be able to provide /// the required UE signalling (e.g. HARQ ACKs) for the DU-high normal operation. class phy_simulator : public mac_result_notifier, public mac_cell_result_notifier @@ -350,14 +377,13 @@ class phy_simulator : public mac_result_notifier, public mac_cell_result_notifie mac_dl_sched_result slot_dl_result; mac_ul_sched_result slot_ul_result; + mac_dl_data_result slot_dl_data_result; - unsigned nof_dl_grants = 0; - uint64_t nof_dl_bytes = 0; + phy_metrics metrics; - unsigned nof_ul_grants = 0; - uint64_t nof_ul_bytes = 0; + void reset_metrics() { metrics = {}; } - void clear_previous_scheduler_results() + void new_slot() { slot_dl_result.dl_res = nullptr; slot_ul_result.ul_res = nullptr; @@ -368,14 +394,7 @@ class phy_simulator : public mac_result_notifier, public mac_cell_result_notifie void on_new_downlink_scheduler_results(const mac_dl_sched_result& dl_res) override { slot_dl_result = dl_res; } /// Notifies scheduled PDSCH PDUs. - void on_new_downlink_data(const mac_dl_data_result& dl_data) override - { - // Save the number of DL grants and bytes transmitted. - nof_dl_grants += dl_data.ue_pdus.size(); - for (const auto& pdu : dl_data.ue_pdus) { - nof_dl_bytes += pdu.pdu.size(); - } - } + void on_new_downlink_data(const mac_dl_data_result& dl_data) override { slot_dl_data_result = dl_data; } /// Notifies slot scheduled PUCCH/PUSCH grants. void on_new_uplink_scheduler_results(const mac_ul_sched_result& ul_res) override { slot_ul_result = ul_res; } @@ -399,12 +418,48 @@ class phy_simulator : public mac_result_notifier, public mac_cell_result_notifie } slot_ended = false; } + + void process_results() + { + metrics.slot_count++; + process_dl_results(); + process_ul_results(); + } + +private: + void process_dl_results() + { + if (slot_dl_result.dl_res == nullptr or slot_dl_result.dl_res->nof_dl_symbols == 0) { + // Early return. + return; + } + + metrics.slot_dl_count++; + metrics.nof_dl_grants += slot_dl_data_result.ue_pdus.size(); + for (const auto& pdu : slot_dl_data_result.ue_pdus) { + metrics.nof_dl_bytes += pdu.pdu.size(); + } + } + + void process_ul_results() + { + if (slot_ul_result.ul_res == nullptr or slot_ul_result.ul_res->nof_ul_symbols == 0) { + // Early return. + return; + } + + metrics.slot_ul_count++; + metrics.nof_ul_grants += slot_ul_result.ul_res->puschs.size(); + for (const ul_sched_info& pusch : slot_ul_result.ul_res->puschs) { + metrics.nof_ul_bytes += pusch.pusch_cfg.tb_size_bytes; + } + } }; /// \brief TestBench for the DU-high. class du_high_bench { - static const unsigned DL_PDU_SIZE = 1500; + static const unsigned MAX_DL_PDU_SIZE = 1500; public: du_high_bench(unsigned dl_buffer_state_bytes_, @@ -413,7 +468,6 @@ class du_high_bench const cell_config_builder_params& builder_params = {}) : params(builder_params), dl_buffer_state_bytes(dl_buffer_state_bytes_), - nof_dl_pdus_per_slot(divide_ceil(dl_buffer_state_bytes, DL_PDU_SIZE)), workers(du_cell_cores), ul_bsr_bytes(ul_bsr_bytes_) { @@ -458,7 +512,7 @@ class du_high_bench du_hi = std::make_unique(cfg); // Create PDCP PDU. - pdcp_pdu.append(test_rgen::random_vector(DL_PDU_SIZE)); + pdcp_pdu.append(test_rgen::random_vector(MAX_DL_PDU_SIZE)); // Create MAC PDU. mac_pdu.append( test_rgen::random_vector(buff_size_field_to_bytes(lbsr_buff_sz, srsran::bsr_format::LONG_BSR))); @@ -484,7 +538,7 @@ class du_high_bench void run_slot() { // Clear results. - sim_phy.clear_previous_scheduler_results(); + sim_phy.new_slot(); // Push slot indication to DU-high. du_hi->get_slot_handler(to_du_cell_index(0)).handle_slot_indication(next_sl_tx); @@ -509,7 +563,6 @@ class du_high_bench void process_results() { - // Process PUCCH grants. process_pucch_grants(); // Send any pending UCI indications. @@ -551,9 +604,11 @@ class du_high_bench ++crc_ind; } + // Process PHY metrics. + sim_phy.process_results(); + // Advance slot. ++next_sl_tx; - ++slot_count; } /// \brief Add a UE to the DU-high and wait for the DU-high to finish the setup of the UE. @@ -589,8 +644,6 @@ class du_high_bench // \brief Push a DL PDUs to DU-high via F1-U interface. void push_pdcp_pdus() { - static uint32_t pdcp_sn = 0; - if (dl_buffer_state_bytes == 0) { // Early return. return; @@ -600,15 +653,34 @@ class du_high_bench return; } while (not workers.dl_exec.defer([this]() { - for (const auto& du_notif : sim_cu_up.du_notif_list) { + static std::array pdcp_sn_list{0}; + const unsigned nof_dl_pdus_per_slot = divide_ceil(dl_buffer_state_bytes, MAX_DL_PDU_SIZE); + const unsigned last_dl_pdu_size = dl_buffer_state_bytes % MAX_DL_PDU_SIZE; + + // Forward DL buffer occupancy updates to all bearers. + for (unsigned bearer_idx = 0; bearer_idx != sim_cu_up.du_notif_list.size(); ++bearer_idx) { + const auto& du_notif = sim_cu_up.du_notif_list[bearer_idx]; for (unsigned i = 0; i != nof_dl_pdus_per_slot; ++i) { - pdcp_sn = (pdcp_sn + 1) % (1U << 18U); - du_notif->on_new_sdu(pdcp_tx_pdu{.buf = pdcp_pdu.deep_copy(), .pdcp_sn = pdcp_sn}); + // Update PDCP SN. + 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()) { + 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. + pdu_copy.resize(last_dl_pdu_size); + } + du_notif->on_new_sdu(pdcp_tx_pdu{.buf = std::move(pdu_copy), .pdcp_sn = pdcp_sn_list[bearer_idx]}); } } })) { // keep trying to push new PDUs. - // This also serves as a way to slow down the slot indication rate, to better capture a RT deployment. + // Sleeping in the test main thread will also slow down the rate at which slot indications reach the MAC. This + // is ok because in a real RT deployment the slot indication rate is limited by the radio. std::this_thread::sleep_for(std::chrono::microseconds{500}); } } @@ -641,8 +713,9 @@ class du_high_bench // Forward positive SRs to scheduler only if UL is enabled for the benchmark, PUCCH grant is for SR and nof. // UL grants is 0 or scheduler stops allocating UL grants. if (ul_bsr_bytes != 0 and pucch.format_1.sr_bits != sr_nof_bits::no_sr and - (sim_phy.nof_ul_grants == 0 or - (sim_phy.nof_ul_grants == sim_phy.nof_ul_grants + sim_phy.slot_ul_result.ul_res->puschs.size()))) { + (sim_phy.metrics.nof_ul_grants == 0 or + (sim_phy.metrics.nof_ul_grants == + sim_phy.metrics.nof_ul_grants + sim_phy.slot_ul_result.ul_res->puschs.size()))) { f1.sr_info.emplace(); f1.sr_info->sr_detected = true; } @@ -659,8 +732,9 @@ class du_high_bench // Forward positive SRs to scheduler only if UL is enabled for the benchmark, PUCCH grant is for SR and nof. // UL grants is 0 or scheduler stops allocating UL grants. if (ul_bsr_bytes != 0 and pucch.format_2.sr_bits != sr_nof_bits::no_sr and - (sim_phy.nof_ul_grants == 0 or - (sim_phy.nof_ul_grants == sim_phy.nof_ul_grants + sim_phy.slot_ul_result.ul_res->puschs.size()))) { + (sim_phy.metrics.nof_ul_grants == 0 or + (sim_phy.metrics.nof_ul_grants == + sim_phy.metrics.nof_ul_grants + sim_phy.slot_ul_result.ul_res->puschs.size()))) { f2.sr_info.emplace(); f2.sr_info->resize(sr_nof_bits_to_uint(pucch.format_2.sr_bits)); f2.sr_info->fill(0, sr_nof_bits_to_uint(pucch.format_2.sr_bits), true); @@ -697,9 +771,6 @@ class du_high_bench return; } - // Update nof. PUSCH grants scheduled. - sim_phy.nof_ul_grants += sim_phy.slot_ul_result.ul_res->puschs.size(); - // Forwards UCI to the DU-High given the scheduled PUSCHs. mac_uci_indication_message uci_ind{}; uci_ind.sl_rx = sim_phy.slot_ul_result.slot; @@ -710,9 +781,6 @@ class du_high_bench for (const ul_sched_info& pusch : sim_phy.slot_ul_result.ul_res->puschs) { unsigned payload_len = std::min(mac_pdu.length(), static_cast(pusch.pusch_cfg.tb_size_bytes)); - // Update nof. UL bytes scheduled. - sim_phy.nof_ul_bytes += payload_len; - // 1 Byte for LCID and other fields and 1/2 Byte(s) for payload length. static const uint8_t mac_header_size = payload_len > 255 ? 3 : 2; // Early return. @@ -822,8 +890,7 @@ class du_high_bench cell_config_builder_params params; du_high_configuration cfg{}; /// Size of the DL buffer status to push for DL Tx. - unsigned dl_buffer_state_bytes; - const unsigned nof_dl_pdus_per_slot; + unsigned dl_buffer_state_bytes; srslog::basic_logger& test_logger = srslog::fetch_basic_logger("TEST"); dummy_metrics_handler metrics_handler; @@ -834,7 +901,6 @@ class du_high_bench du_high_single_cell_worker_manager workers; std::unique_ptr du_hi; slot_point next_sl_tx{0, 0}; - unsigned slot_count = 0; null_mac_pcap mac_pcap; null_rlc_pcap rlc_pcap; @@ -869,10 +935,11 @@ class du_high_bench static cell_config_builder_params generate_custom_cell_config_builder_params(duplex_mode dplx_mode) { cell_config_builder_params params{}; - params.scs_common = dplx_mode == duplex_mode::FDD ? subcarrier_spacing::kHz15 : subcarrier_spacing::kHz30; - params.dl_arfcn = dplx_mode == duplex_mode::FDD ? 530000 : 520002; - params.band = band_helper::get_band_from_dl_arfcn(params.dl_arfcn); - params.channel_bw_mhz = bs_channel_bandwidth_fr1::MHz100; + params.scs_common = dplx_mode == duplex_mode::FDD ? subcarrier_spacing::kHz15 : subcarrier_spacing::kHz30; + params.dl_arfcn = dplx_mode == duplex_mode::FDD ? 530000 : 520002; + params.band = band_helper::get_band_from_dl_arfcn(params.dl_arfcn); + params.channel_bw_mhz = + dplx_mode == duplex_mode::FDD ? srsran::bs_channel_bandwidth_fr1::MHz20 : bs_channel_bandwidth_fr1::MHz100; const unsigned nof_crbs = band_helper::get_n_rbs_from_bw( params.channel_bw_mhz, params.scs_common, band_helper::get_freq_range(*params.band)); static const uint8_t ss0_idx = 0; @@ -923,6 +990,9 @@ void benchmark_dl_ul_only_rlc_um(benchmarker& bm, bench.add_ue(to_du_ue_index(ue_count)); } + // Start of the benchmark. Reset metrics collected so far. + bench.sim_phy.reset_metrics(); + // Run benchmark. bm.new_measure( benchname, @@ -943,13 +1013,15 @@ void benchmark_dl_ul_only_rlc_um(benchmarker& bm, bench.stop(); srslog::flush(); - const unsigned sim_time_msec = bench.slot_count / get_nof_slots_per_subframe(bench.cfg.cells[0].scs_common); - fmt::print("\nStats: slots={}, #PDSCHs={}, dl_bitrate={:.3} Mbps, #PUSCHs={}, ul_bitrate={:.3} Mbps\n", - bench.slot_count, - bench.sim_phy.nof_dl_grants, - bench.sim_phy.nof_dl_bytes * 8 * 1.0e-6 / (sim_time_msec * 1.0e-3), - bench.sim_phy.nof_ul_grants, - bench.sim_phy.nof_ul_bytes * 8 * 1.0e-6 / (sim_time_msec * 1.0e-3)); + fmt::print("\nStats: #slots={}, #PDSCHs={}, #PDSCHs-per-slot={:.3}, dl_bitrate={:.3} Mbps, #PUSCHs={}, " + "#PUSCHs-per-slot={:.3}, ul_bitrate={:.3} Mbps\n", + bench.sim_phy.metrics.slot_count, + bench.sim_phy.metrics.nof_dl_grants, + bench.sim_phy.metrics.nof_dl_grants / (double)bench.sim_phy.metrics.slot_dl_count, + bench.sim_phy.metrics.dl_Mbps(bench.cfg.cells[0].scs_common), + bench.sim_phy.metrics.nof_ul_grants, + bench.sim_phy.metrics.nof_ul_grants / (double)bench.sim_phy.metrics.slot_ul_count, + bench.sim_phy.metrics.ul_Mbps(bench.cfg.cells[0].scs_common)); } int main(int argc, char** argv) From 62c450f4caf18d014853e854ab7ae0bb1a822fa5 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 2 Jan 2024 19:48:09 +0100 Subject: [PATCH 025/134] du_high: add the ability to set the max rb grant size for the UE DL grants --- .../benchmarks/du_high/du_high_benchmark.cpp | 61 ++++++++++++------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/tests/benchmarks/du_high/du_high_benchmark.cpp b/tests/benchmarks/du_high/du_high_benchmark.cpp index 92391c6cd0..794d4b1d1f 100644 --- a/tests/benchmarks/du_high/du_high_benchmark.cpp +++ b/tests/benchmarks/du_high/du_high_benchmark.cpp @@ -43,15 +43,17 @@ struct bench_params { unsigned dl_bytes_per_slot = 1500; /// \brief Set size of the UL Buffer status report to push for UL Tx. Setting this value to 0 will disable UL Tx. unsigned ul_bsr_bytes = 0; + /// \brief Maximum number of RBs per UE DL grant per slot. + unsigned max_dl_rb_grant = MAX_NOF_PRBS; /// \brief Logical cores used by the "du_cell" thread. std::vector du_cell_cores = {0, 1}; }; static void usage(const char* prog, const bench_params& params) { - fmt::print( - "Usage: {} [-R repetitions] [-U nof. ues] [-D Duplex mode] [-d DL Tx bytes] [-u UL Tx bytes] [-s silent]\n", - prog); + fmt::print("Usage: {} [-R repetitions] [-U nof. ues] [-D Duplex mode] [-d DL bytes per slot] [-u UL BSR] [-r Max RBs " + "per UE DL grant]\n", + prog); fmt::print("\t-R Repetitions [Default {}]\n", params.nof_repetitions); fmt::print("\t-U Nof. DU UEs [Default {}]\n", params.nof_ues); fmt::print("\t-D Duplex mode (FDD/TDD) [Default {}]\n", to_string(params.dplx_mode)); @@ -61,6 +63,7 @@ static void usage(const char* prog, const bench_params& params) fmt::print("\t-u Size of the UL Buffer status report to push for UL Tx. Setting this value to 0 will disable UL Tx. " "[Default {}]\n", params.ul_bsr_bytes); + fmt::print("\t-r Max RBs per UE DL grant per slot [Default 275]\n"); fmt::print("\t-c \"du_cell\" cores that the benchmark should use [Default 0,1]\n"); fmt::print("\t-h Show this message\n"); } @@ -68,7 +71,7 @@ static void usage(const char* prog, const bench_params& params) static void parse_args(int argc, char** argv, bench_params& params) { int opt = 0; - while ((opt = getopt(argc, argv, "R:U:D:d:u:c:h")) != -1) { + while ((opt = getopt(argc, argv, "R:U:D:d:u:r:c:h")) != -1) { switch (opt) { case 'R': params.nof_repetitions = std::strtol(optarg, nullptr, 10); @@ -93,6 +96,9 @@ static void parse_args(int argc, char** argv, bench_params& params) case 'u': params.ul_bsr_bytes = std::strtol(optarg, nullptr, 10); break; + case 'r': + params.max_dl_rb_grant = std::strtol(optarg, nullptr, 10); + break; case 'c': { std::string optstr{optarg}; if (optstr.find(",") != std::string::npos) { @@ -464,6 +470,7 @@ class du_high_bench public: du_high_bench(unsigned dl_buffer_state_bytes_, unsigned ul_bsr_bytes_, + unsigned max_nof_rbs_per_dl_grant, span du_cell_cores, const cell_config_builder_params& builder_params = {}) : params(builder_params), @@ -485,20 +492,21 @@ class du_high_bench bsr_mac_subpdu.append(lbsr_buff_sz); // Instantiate a DU-high object. - cfg.gnb_du_id = 1; - cfg.gnb_du_name = fmt::format("srsgnb{}", cfg.gnb_du_id); - cfg.du_bind_addr = fmt::format("127.0.0.{}", cfg.gnb_du_id); - cfg.exec_mapper = &workers.du_high_exec_mapper; - cfg.f1c_client = &sim_cu_cp; - cfg.f1u_gw = &sim_cu_up; - cfg.phy_adapter = &sim_phy; - cfg.timers = &timers; - cfg.cells = {config_helpers::make_default_du_cell_config(params)}; - cfg.sched_cfg = config_helpers::make_default_scheduler_expert_config(); - cfg.qos = config_helpers::make_default_du_qos_config_list(1000); - cfg.mac_p = &mac_pcap; - cfg.rlc_p = &rlc_pcap; - cfg.sched_ue_metrics_notifier = &metrics_handler; + cfg.gnb_du_id = 1; + cfg.gnb_du_name = fmt::format("srsgnb{}", cfg.gnb_du_id); + cfg.du_bind_addr = fmt::format("127.0.0.{}", cfg.gnb_du_id); + cfg.exec_mapper = &workers.du_high_exec_mapper; + cfg.f1c_client = &sim_cu_cp; + cfg.f1u_gw = &sim_cu_up; + cfg.phy_adapter = &sim_phy; + cfg.timers = &timers; + cfg.cells = {config_helpers::make_default_du_cell_config(params)}; + cfg.sched_cfg = config_helpers::make_default_scheduler_expert_config(); + cfg.sched_cfg.ue.pdsch_nof_rbs = {1, max_nof_rbs_per_dl_grant}; + cfg.qos = config_helpers::make_default_du_qos_config_list(1000); + cfg.mac_p = &mac_pcap; + cfg.rlc_p = &rlc_pcap; + cfg.sched_ue_metrics_notifier = &metrics_handler; // Increase nof. PUCCH resources to accommodate more UEs. cfg.cells[0].pucch_cfg.nof_sr_resources = 30; @@ -976,6 +984,7 @@ void benchmark_dl_ul_only_rlc_um(benchmarker& bm, duplex_mode dplx_mode, unsigned dl_buffer_state_bytes, unsigned ul_bsr_bytes, + unsigned max_nof_rbs_per_dl_grant, span du_cell_cores) { auto benchname = fmt::format("{}{}{}, {} UEs, RLC UM", @@ -984,8 +993,11 @@ void benchmark_dl_ul_only_rlc_um(benchmarker& bm, ul_bsr_bytes > 0 ? "UL" : "", nof_ues); test_delimit_logger test_delim(benchname.c_str()); - du_high_bench bench{ - dl_buffer_state_bytes, ul_bsr_bytes, du_cell_cores, generate_custom_cell_config_builder_params(dplx_mode)}; + du_high_bench bench{dl_buffer_state_bytes, + ul_bsr_bytes, + max_nof_rbs_per_dl_grant, + du_cell_cores, + generate_custom_cell_config_builder_params(dplx_mode)}; for (unsigned ue_count = 0; ue_count < nof_ues; ++ue_count) { bench.add_ue(to_du_ue_index(ue_count)); } @@ -1050,8 +1062,13 @@ int main(int argc, char** argv) benchmarker bm("DU-High", params.nof_repetitions); // Run scenarios. - benchmark_dl_ul_only_rlc_um( - bm, params.nof_ues, params.dplx_mode, params.dl_bytes_per_slot, params.ul_bsr_bytes, params.du_cell_cores); + benchmark_dl_ul_only_rlc_um(bm, + params.nof_ues, + params.dplx_mode, + params.dl_bytes_per_slot, + params.ul_bsr_bytes, + params.max_dl_rb_grant, + params.du_cell_cores); // Output results. bm.print_percentiles_time(); From a410a5c810eceec7d9373ada03ede70051237eff Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 2 Jan 2024 22:32:19 +0100 Subject: [PATCH 026/134] du_high: set main test thread to max priority to not be interfered by stressors --- .../benchmarks/du_high/du_high_benchmark.cpp | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/tests/benchmarks/du_high/du_high_benchmark.cpp b/tests/benchmarks/du_high/du_high_benchmark.cpp index 794d4b1d1f..cae564f828 100644 --- a/tests/benchmarks/du_high/du_high_benchmark.cpp +++ b/tests/benchmarks/du_high/du_high_benchmark.cpp @@ -23,6 +23,7 @@ #include "srsran/support/executors/priority_task_worker.h" #include "srsran/support/executors/task_worker.h" #include "srsran/support/test_utils.h" +#include using namespace srsran; using namespace srs_du; @@ -283,16 +284,16 @@ struct du_high_single_cell_worker_manager { explicit du_high_single_cell_worker_manager(span du_cell_cores) : ctrl_worker("du_ctrl", task_worker_queue_size, - os_thread_realtime_priority::max() - 1, + os_thread_realtime_priority::max() - 20, get_other_affinity_mask(du_cell_cores)), cell_worker("du_cell", task_worker_queue_size, - os_thread_realtime_priority::max(), + os_thread_realtime_priority::max() - 10, get_du_cell_affinity_mask(du_cell_cores)), ue_worker("du_ue", {task_worker_queue_size, task_worker_queue_size}, std::chrono::microseconds{500}, - os_thread_realtime_priority::max() - 2, + os_thread_realtime_priority::max() - 50, get_other_affinity_mask(du_cell_cores)), ue_ctrl_exec(make_priority_task_worker_executor(ue_worker)), dl_exec(make_priority_task_worker_executor(ue_worker)), @@ -1036,6 +1037,36 @@ void benchmark_dl_ul_only_rlc_um(benchmarker& bm, bench.sim_phy.metrics.ul_Mbps(bench.cfg.cells[0].scs_common)); } +/// \brief Configure main thread priority and affinity to avoid interference from other processes (including stressors). +static void configure_main_thread(span du_cell_cores) +{ + pthread_t self = pthread_self(); + + int prio_level = ::sched_get_priority_max(SCHED_FIFO); + if (prio_level == -1) { + fmt::print("Warning: Unable to get the max thread priority. Falling back to normal priority."); + return; + } + // set priority to -1 less than RT to avoid interfering with kernel. + ::sched_param sch{prio_level - 1}; + if (::pthread_setschedparam(self, SCHED_FIFO, &sch)) { + fmt::print("Warning: Unable to set the test thread priority to max. Falling back to normal priority."); + return; + } + + // Set main test thread to use same cores as du_cell. + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + for (unsigned i : du_cell_cores) { + CPU_SET(i, &cpuset); + } + int ret; + if ((ret = pthread_setaffinity_np(self, sizeof(cpuset), &cpuset)) != 0) { + fmt::print("Warning: Unable to set affinity for test thread. Cause: '{}'\n", strerror(ret)); + return; + } +} + int main(int argc, char** argv) { static const std::size_t byte_buffer_nof_segments = 1U << 18U; @@ -1058,6 +1089,9 @@ int main(int argc, char** argv) // Setup size of byte buffer pool. init_byte_buffer_segment_pool(byte_buffer_nof_segments, byte_buffer_segment_size); + // Configure main thread. + configure_main_thread(params.du_cell_cores); + // Start benchmarker. benchmarker bm("DU-High", params.nof_repetitions); From a17c8802ca25073745998d9aa205564fb076d2f4 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 3 Jan 2024 09:49:28 +0100 Subject: [PATCH 027/134] support: fix thread affinity computation when main thread affinity is changed --- lib/support/unique_thread.cpp | 9 +++++++-- tests/benchmarks/du_high/du_high_benchmark.cpp | 13 +++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/support/unique_thread.cpp b/lib/support/unique_thread.cpp index b42b44db77..330a8890dd 100644 --- a/lib/support/unique_thread.cpp +++ b/lib/support/unique_thread.cpp @@ -16,13 +16,18 @@ using namespace srsran; -size_t srsran::compute_host_nof_hardware_threads() -{ +// Compute number of host CPUs, statically, before any framework (e.g. DPDK) affects the affinities of the main thread. +static const size_t nof_host_cpus = []() -> size_t { cpu_set_t cpuset; if (sched_getaffinity(0, sizeof(cpuset), &cpuset) == 0) { return std::max(1, CPU_COUNT(&cpuset)); } return std::max(1U, std::thread::hardware_concurrency()); +}(); + +size_t srsran::compute_host_nof_hardware_threads() +{ + return nof_host_cpus; } /// Sets thread OS scheduling real-time priority. diff --git a/tests/benchmarks/du_high/du_high_benchmark.cpp b/tests/benchmarks/du_high/du_high_benchmark.cpp index cae564f828..50c209ea22 100644 --- a/tests/benchmarks/du_high/du_high_benchmark.cpp +++ b/tests/benchmarks/du_high/du_high_benchmark.cpp @@ -1082,6 +1082,13 @@ int main(int argc, char** argv) srslog::fetch_basic_logger("DU-MNG").set_level(srslog::basic_levels::warning); srslog::init(); + std::string tracing_filename = ""; + if (not tracing_filename.empty()) { + fmt::print("Opening event tracer...\n"); + open_trace_file(tracing_filename); + fmt::print("Event tracer opened successfully\n"); + } + // Parses benchmark parameters. bench_params params{}; parse_args(argc, argv, params); @@ -1104,6 +1111,12 @@ int main(int argc, char** argv) params.max_dl_rb_grant, params.du_cell_cores); + if (not tracing_filename.empty()) { + fmt::print("Closing event tracer...\n"); + close_trace_file(); + fmt::print("Event tracer closed successfully\n"); + } + // Output results. bm.print_percentiles_time(); } From b6fd803620d9859e454cfa992f071cf1d151fc5c Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 3 Jan 2024 12:18:51 +0100 Subject: [PATCH 028/134] du_high: improve du_high_benchmark, in particular, make du_cell better match the type of worker used in the gnb app --- .../benchmarks/du_high/du_high_benchmark.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tests/benchmarks/du_high/du_high_benchmark.cpp b/tests/benchmarks/du_high/du_high_benchmark.cpp index 50c209ea22..556079842b 100644 --- a/tests/benchmarks/du_high/du_high_benchmark.cpp +++ b/tests/benchmarks/du_high/du_high_benchmark.cpp @@ -277,6 +277,8 @@ class cu_up_simulator : public f1u_du_gateway /// \brief Instantiation of the DU-high workers and executors for the benchmark. struct du_high_single_cell_worker_manager { + using cell_worker_type = + priority_task_worker; using ue_worker_type = priority_task_worker; static const uint32_t task_worker_queue_size = 100000; @@ -287,7 +289,8 @@ struct du_high_single_cell_worker_manager { os_thread_realtime_priority::max() - 20, get_other_affinity_mask(du_cell_cores)), cell_worker("du_cell", - task_worker_queue_size, + {8, task_worker_queue_size}, + std::chrono::microseconds{10}, os_thread_realtime_priority::max() - 10, get_du_cell_affinity_mask(du_cell_cores)), ue_worker("du_ue", @@ -295,6 +298,8 @@ struct du_high_single_cell_worker_manager { std::chrono::microseconds{500}, os_thread_realtime_priority::max() - 50, get_other_affinity_mask(du_cell_cores)), + slot_exec(make_priority_task_worker_executor(cell_worker)), + cell_exec(make_priority_task_worker_executor(cell_worker)), ue_ctrl_exec(make_priority_task_worker_executor(ue_worker)), dl_exec(make_priority_task_worker_executor(ue_worker)), ul_exec(make_priority_task_worker_executor(ue_worker)) @@ -308,7 +313,7 @@ struct du_high_single_cell_worker_manager { ue_worker.stop(); } - static os_sched_affinity_bitmask get_du_cell_affinity_mask(span du_cell_cores) + static os_sched_affinity_bitmask get_du_cell_affinity_mask(span du_cell_cores) { os_sched_affinity_bitmask mask; for (auto core : du_cell_cores) { @@ -317,7 +322,7 @@ struct du_high_single_cell_worker_manager { return mask; } - static os_sched_affinity_bitmask get_other_affinity_mask(span du_cell_cores) + static os_sched_affinity_bitmask get_other_affinity_mask(span du_cell_cores) { os_sched_affinity_bitmask mask; for (unsigned i = 0; i != mask.size(); ++i) { @@ -329,15 +334,17 @@ struct du_high_single_cell_worker_manager { } task_worker ctrl_worker; - task_worker cell_worker; + cell_worker_type cell_worker; ue_worker_type ue_worker; task_worker_executor ctrl_exec{ctrl_worker}; - task_worker_executor cell_exec{cell_worker}; + priority_task_worker_executor slot_exec; + priority_task_worker_executor cell_exec; priority_task_worker_executor ue_ctrl_exec; priority_task_worker_executor dl_exec; priority_task_worker_executor ul_exec; du_high_executor_mapper_impl du_high_exec_mapper{ - std::make_unique(std::initializer_list{&cell_exec}), + std::make_unique(std::initializer_list{&cell_exec}, + std::initializer_list{&slot_exec}), std::make_unique(std::initializer_list{&ue_ctrl_exec}, std::initializer_list{&ul_exec}, std::initializer_list{&dl_exec}), From 8c81270beb75910f2b1bcca9be30b85a93afb4a1 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 3 Jan 2024 14:20:09 +0100 Subject: [PATCH 029/134] support: add 99.99%-quantile to the benchmarker --- include/srsran/support/benchmark_utils.h | 13 ++++++++++--- tests/benchmarks/du_high/du_high_benchmark.cpp | 14 +++++++++----- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/include/srsran/support/benchmark_utils.h b/include/srsran/support/benchmark_utils.h index 6fe78ee630..389ea10b3b 100644 --- a/include/srsran/support/benchmark_utils.h +++ b/include/srsran/support/benchmark_utils.h @@ -115,7 +115,7 @@ class benchmarker void print_percentile_header(unsigned descr_width, unsigned percentile_width, const std::string& units) const { fmt::print("\"{}\" performance for {} repetitions. All values are in {}.\n" - " {:<{}}|{:^{}}|{:^{}}|{:^{}}|{:^{}}|{:^{}}|{:^{}}|\n", + " {:<{}}|{:^{}}|{:^{}}|{:^{}}|{:^{}}|{:^{}}|{:^{}}|{:^{}}|\n", title, nof_repetitions, units, @@ -131,6 +131,8 @@ class benchmarker percentile_width, "99.9th", percentile_width, + "99.99th", + percentile_width, "Worst", percentile_width); } @@ -181,7 +183,7 @@ class benchmarker print_percentile_header(descr_width, percentile_width, units); for (const benchmark_result& result : benchmark_results) { - fmt::print(" {:{}}|{:{}.1f}|{:{}.1f}|{:{}.1f}|{:{}.1f}|{:{}.1f}|{:{}.1f}|\n", + fmt::print(" {:{}}|{:{}.1f}|{:{}.1f}|{:{}.1f}|{:{}.1f}|{:{}.1f}|{:{}.1f}|{:{}.1f}|\n", result.description, descr_width, result.measurements[static_cast(nof_repetitions * 0.5)] * scaling, @@ -194,6 +196,8 @@ class benchmarker percentile_width, result.measurements[static_cast(nof_repetitions * 0.999)] * scaling, percentile_width, + result.measurements[static_cast(nof_repetitions * 0.9999)] * scaling, + percentile_width, result.measurements.back() * scaling, percentile_width); } @@ -214,7 +218,7 @@ class benchmarker print_percentile_header(descr_width, percentile_width, "mega" + units + " per second"); for (const benchmark_result& result : benchmark_results) { fmt::print( - " {:{}}|{:{}.1f}|{:{}.1f}|{:{}.1f}|{:{}.1f}|{:{}.1f}|{:{}.1f}|\n", + " {:{}}|{:{}.1f}|{:{}.1f}|{:{}.1f}|{:{}.1f}|{:{}.1f}|{:{}.1f}|{:{}.1f}|\n", result.description, descr_width, convert_to_throughput(result.measurements[static_cast(nof_repetitions * 0.5)], result.size) * scaling, @@ -230,6 +234,9 @@ class benchmarker convert_to_throughput(result.measurements[static_cast(nof_repetitions * 0.999)], result.size) * scaling, percentile_width, + convert_to_throughput(result.measurements[static_cast(nof_repetitions * 0.9999)], result.size) * + scaling, + percentile_width, convert_to_throughput(result.measurements.back(), result.size) * scaling, percentile_width); } diff --git a/tests/benchmarks/du_high/du_high_benchmark.cpp b/tests/benchmarks/du_high/du_high_benchmark.cpp index 556079842b..f00d8b133e 100644 --- a/tests/benchmarks/du_high/du_high_benchmark.cpp +++ b/tests/benchmarks/du_high/du_high_benchmark.cpp @@ -365,13 +365,13 @@ struct phy_metrics { unsigned total_subframes_elapsed(subcarrier_spacing scs) { return slot_count / get_nof_slots_per_subframe(scs); } - double dl_Mbps(subcarrier_spacing scs) + double dl_mbps(subcarrier_spacing scs) { unsigned sim_time_msec = total_subframes_elapsed(scs); return nof_dl_bytes * 8 * 1.0e-6 / (sim_time_msec * 1.0e-3); } - double ul_Mbps(subcarrier_spacing scs) + double ul_mbps(subcarrier_spacing scs) { unsigned sim_time_msec = total_subframes_elapsed(scs); return nof_ul_bytes * 8 * 1.0e-6 / (sim_time_msec * 1.0e-3); @@ -660,11 +660,15 @@ class du_high_bench // \brief Push a DL PDUs to DU-high via F1-U interface. void push_pdcp_pdus() { + // Value of DL Buffer Occupancy at which we consider that the DU DL is saturated, and there is no point in pushing + // more PDUs. + static const size_t SATURATION_DL_BS_BYTES = 1e5; + if (dl_buffer_state_bytes == 0) { // Early return. return; } - if (metrics_handler.tot_dl_bs > 1e5) { + if (metrics_handler.tot_dl_bs > SATURATION_DL_BS_BYTES) { // Saturation of the DU DL detected. We throttle the F1-U interface to avoid depleting the byte buffer pool. return; } @@ -1038,10 +1042,10 @@ void benchmark_dl_ul_only_rlc_um(benchmarker& bm, bench.sim_phy.metrics.slot_count, bench.sim_phy.metrics.nof_dl_grants, bench.sim_phy.metrics.nof_dl_grants / (double)bench.sim_phy.metrics.slot_dl_count, - bench.sim_phy.metrics.dl_Mbps(bench.cfg.cells[0].scs_common), + bench.sim_phy.metrics.dl_mbps(bench.cfg.cells[0].scs_common), bench.sim_phy.metrics.nof_ul_grants, bench.sim_phy.metrics.nof_ul_grants / (double)bench.sim_phy.metrics.slot_ul_count, - bench.sim_phy.metrics.ul_Mbps(bench.cfg.cells[0].scs_common)); + bench.sim_phy.metrics.ul_mbps(bench.cfg.cells[0].scs_common)); } /// \brief Configure main thread priority and affinity to avoid interference from other processes (including stressors). From b8e4ee07a08def4da4182450dfd860347fcd3f6f Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 3 Jan 2024 14:33:16 +0100 Subject: [PATCH 030/134] du_high: add comment explaining the details of the du_high_benchmark --- tests/benchmarks/du_high/du_high_benchmark.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/benchmarks/du_high/du_high_benchmark.cpp b/tests/benchmarks/du_high/du_high_benchmark.cpp index f00d8b133e..2c481495aa 100644 --- a/tests/benchmarks/du_high/du_high_benchmark.cpp +++ b/tests/benchmarks/du_high/du_high_benchmark.cpp @@ -9,7 +9,23 @@ */ /// \file -/// \brief Benchmarks of the DU-high latency. +/// \brief Benchmarks for the DU-high latency. +/// +/// In this benchmark, we emulate the behaviors of the CU-CP, CU-UP and PHY in order to simulate a realistic deployment +/// of the instantiated DU-high class. However, there are some simplifications: +/// - the PHY is emulated by a single thread, rather than by separate threads for DL PHY, UL PHY, and slot indications. +/// In practice, this may lead to less contention faced by the notifications of the PHY that reach the MAC. +/// - metrics handlers and E2 agents are instantiated separately from the DU-high class. If these entities have blocking +/// calls, such as mutexes, they may introduce additional latency. +/// - Complicated CU-CP procedures (e.g. reconfig) and their impact on the MAC latency are left out of this benchmark. +/// - The UP traffic is continuous rather than bursty. +/// - The activity of higher priority threads, namely DL PHY and RU threads are not emulated. This will mean that +/// the DU-high threads will be preempted less often than in a real deployment. To circumvent it, we can run a parallel +/// stress job in the same machine. For instance, to run stressors that solely interfere with the gnb_ue and gnb_ctrl +/// threads (and not with the du_cell thread), one can run: +/// > sudo stress-ng --cpu 6 --taskset 2-7 --sched fifo --sched-prio 97 -l 90 +/// which will instantiate 6 threads running in cores 2-7 (assuming du_cell is pinned to 0-1), with high priority +/// and a CPU load of 90%. #include "lib/du_high/du_high_executor_strategies.h" #include "lib/du_high/du_high_impl.h" From 017afbd4e084d64011f1b80454e38558d9a81300 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 3 Jan 2024 16:26:16 +0100 Subject: [PATCH 031/134] sched: The sched event lists need to be initially resized to avoid mallocs in the scheduler thread --- lib/scheduler/support/slot_event_list.h | 6 ++++++ lib/scheduler/ue_scheduling/ue_event_manager.cpp | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/lib/scheduler/support/slot_event_list.h b/lib/scheduler/support/slot_event_list.h index 4e429305b2..c98bfedfa8 100644 --- a/lib/scheduler/support/slot_event_list.h +++ b/lib/scheduler/support/slot_event_list.h @@ -25,6 +25,12 @@ template class slot_event_list { public: + void reserve(unsigned cap) + { + pending_events.reserve(cap); + current_events.reserve(cap); + } + void slot_indication() { current_events.clear(); diff --git a/lib/scheduler/ue_scheduling/ue_event_manager.cpp b/lib/scheduler/ue_scheduling/ue_event_manager.cpp index 39fdab815e..021a2551dd 100644 --- a/lib/scheduler/ue_scheduling/ue_event_manager.cpp +++ b/lib/scheduler/ue_scheduling/ue_event_manager.cpp @@ -99,6 +99,11 @@ class ue_event_manager::ue_dl_buffer_occupancy_manager final : public scheduler_ slot_event_list pending_evs; }; +// Initial capacity for the common event list, in order to avoid std::vector reallocations. We should the max nof UEs +// as a conservative estimate of the number of events per slot. +static const size_t INITIAL_COMMON_EVENT_LIST_SIZE = MAX_NOF_DU_UES; +static const size_t INITIAL_CELL_EVENT_LIST_SIZE = MAX_NOF_DU_UES; + ue_event_manager::ue_event_manager(ue_repository& ue_db_, scheduler_metrics_handler& metrics_handler_, scheduler_event_logger& ev_logger_) : @@ -108,6 +113,10 @@ ue_event_manager::ue_event_manager(ue_repository& ue_db_, logger(srslog::fetch_basic_logger("SCHED")), dl_bo_mng(std::make_unique(*this)) { + common_events.reserve(INITIAL_COMMON_EVENT_LIST_SIZE); + for (auto& cell : cell_specific_events) { + cell.reserve(INITIAL_CELL_EVENT_LIST_SIZE); + } } ue_event_manager::~ue_event_manager() {} From 48e30c1d80e3ebfc36f1d721465447151b28dd2d Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 3 Jan 2024 19:00:10 +0100 Subject: [PATCH 032/134] sched: fix comment --- lib/scheduler/ue_scheduling/ue_event_manager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/scheduler/ue_scheduling/ue_event_manager.cpp b/lib/scheduler/ue_scheduling/ue_event_manager.cpp index 021a2551dd..548342c86e 100644 --- a/lib/scheduler/ue_scheduling/ue_event_manager.cpp +++ b/lib/scheduler/ue_scheduling/ue_event_manager.cpp @@ -99,8 +99,8 @@ class ue_event_manager::ue_dl_buffer_occupancy_manager final : public scheduler_ slot_event_list pending_evs; }; -// Initial capacity for the common event list, in order to avoid std::vector reallocations. We should the max nof UEs -// as a conservative estimate of the number of events per slot. +// Initial capacity for the common and cell event lists, in order to avoid std::vector reallocations. We use the max +// nof UEs as a conservative estimate of the expected number of events per slot. static const size_t INITIAL_COMMON_EVENT_LIST_SIZE = MAX_NOF_DU_UES; static const size_t INITIAL_CELL_EVENT_LIST_SIZE = MAX_NOF_DU_UES; From ecb863bb8543056ed27990b382682249c06d58d5 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 21 Dec 2023 11:23:04 +0100 Subject: [PATCH 033/134] sched: while handling error indication, ensure the DL HARQs that expect mroe than one ACK get correctly flushed --- lib/scheduler/ue_scheduling/harq_process.cpp | 13 +++++++++++- .../ue_scheduling/ue_scheduler_impl.cpp | 20 ++++++++++--------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/lib/scheduler/ue_scheduling/harq_process.cpp b/lib/scheduler/ue_scheduling/harq_process.cpp index 90d72d88d0..1375320878 100644 --- a/lib/scheduler/ue_scheduling/harq_process.cpp +++ b/lib/scheduler/ue_scheduling/harq_process.cpp @@ -432,9 +432,20 @@ int harq_entity::ul_crc_info(harq_id_t h_id, bool ack, slot_point pusch_slot) void harq_entity::dl_ack_info_cancelled(slot_point uci_slot) { + // Maximum number of UCI indications that a HARQ process can expect. + static constexpr size_t MAX_ACKS_PER_HARQ = 4; + for (dl_harq_process& h_dl : dl_harqs) { if (not h_dl.empty() and h_dl.slot_ack() == uci_slot) { - h_dl.ack_info(0, mac_harq_ack_report_status::dtx, nullopt); + dl_harq_process::status_update ret = dl_harq_process::status_update::no_update; + for (unsigned count = 0; count != MAX_ACKS_PER_HARQ and ret == dl_harq_process::status_update::no_update; + ++count) { + ret = h_dl.ack_info(0, mac_harq_ack_report_status::dtx, nullopt); + } + if (ret == dl_harq_process::status_update::no_update) { + dl_h_logger.warning(h_dl.id, "DL HARQ in some invalid state. Resetting it..."); + h_dl.reset(); + } } } } diff --git a/lib/scheduler/ue_scheduling/ue_scheduler_impl.cpp b/lib/scheduler/ue_scheduling/ue_scheduler_impl.cpp index 56e9a38db2..baa584abbb 100644 --- a/lib/scheduler/ue_scheduling/ue_scheduler_impl.cpp +++ b/lib/scheduler/ue_scheduling/ue_scheduler_impl.cpp @@ -214,15 +214,17 @@ void ue_scheduler_impl::handle_error_indication(slot_point // - The lower layers will not attempt to decode the PUSCH and will not send any CRC indication. ul_harq_process& h_ul = u->get_pcell().harqs.ul_harq(grant.pusch_cfg.harq_id); - if (h_ul.tb().nof_retxs == 0) { - // Given that the PUSCH grant was discarded before it reached the PHY, the "new_data" flag was not handled - // and the UL softbuffer was not reset. To avoid mixing different TBs in the softbuffer, it is important to - // reset the UL HARQ process. - h_ul.reset(); - } else { - // To avoid a long UL HARQ timeout window (due to lack of CRC indication), it is important to force a NACK in - // the UL HARQ process. - h_ul.crc_info(false); + if (not h_ul.empty()) { + if (h_ul.tb().nof_retxs == 0) { + // Given that the PUSCH grant was discarded before it reached the PHY, the "new_data" flag was not handled + // and the UL softbuffer was not reset. To avoid mixing different TBs in the softbuffer, it is important to + // reset the UL HARQ process. + h_ul.reset(); + } else { + // To avoid a long UL HARQ timeout window (due to lack of CRC indication), it is important to force a NACK in + // the UL HARQ process. + h_ul.crc_info(false); + } } // - The lower layers will not attempt to decode any UCI in the PUSCH and will not send any UCI indication. From 2d93f1df6d476bd6969dacf77acd6d1a37568f34 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 3 Jan 2024 21:27:11 +0100 Subject: [PATCH 034/134] sched: improve comment explaining constant --- lib/scheduler/ue_scheduling/harq_process.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/scheduler/ue_scheduling/harq_process.cpp b/lib/scheduler/ue_scheduling/harq_process.cpp index 1375320878..3324991660 100644 --- a/lib/scheduler/ue_scheduling/harq_process.cpp +++ b/lib/scheduler/ue_scheduling/harq_process.cpp @@ -432,7 +432,8 @@ int harq_entity::ul_crc_info(harq_id_t h_id, bool ack, slot_point pusch_slot) void harq_entity::dl_ack_info_cancelled(slot_point uci_slot) { - // Maximum number of UCI indications that a HARQ process can expect. + // Maximum number of UCI indications that a HARQ process can expect. We set this conservative limit to account for + // the state when SR, HARQ-ACK+SR, common PUCCH are scheduled. static constexpr size_t MAX_ACKS_PER_HARQ = 4; for (dl_harq_process& h_dl : dl_harqs) { @@ -443,7 +444,7 @@ void harq_entity::dl_ack_info_cancelled(slot_point uci_slot) ret = h_dl.ack_info(0, mac_harq_ack_report_status::dtx, nullopt); } if (ret == dl_harq_process::status_update::no_update) { - dl_h_logger.warning(h_dl.id, "DL HARQ in some invalid state. Resetting it..."); + dl_h_logger.warning(h_dl.id, "DL HARQ in an invalid state. Resetting it..."); h_dl.reset(); } } From 2395d0b8aff3771a567d258d2adb7116d5a4b3d5 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 4 Jan 2024 10:54:49 +0100 Subject: [PATCH 035/134] sched: pre-reserve ue buffer state manager vectors --- lib/scheduler/support/slot_event_list.h | 1 + lib/scheduler/ue_scheduling/ue_event_manager.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/scheduler/support/slot_event_list.h b/lib/scheduler/support/slot_event_list.h index c98bfedfa8..e1e42cbc24 100644 --- a/lib/scheduler/support/slot_event_list.h +++ b/lib/scheduler/support/slot_event_list.h @@ -27,6 +27,7 @@ class slot_event_list public: void reserve(unsigned cap) { + std::lock_guard lock(mutex); pending_events.reserve(cap); current_events.reserve(cap); } diff --git a/lib/scheduler/ue_scheduling/ue_event_manager.cpp b/lib/scheduler/ue_scheduling/ue_event_manager.cpp index 548342c86e..9fad3200cf 100644 --- a/lib/scheduler/ue_scheduling/ue_event_manager.cpp +++ b/lib/scheduler/ue_scheduling/ue_event_manager.cpp @@ -29,6 +29,7 @@ class ue_event_manager::ue_dl_buffer_occupancy_manager final : public scheduler_ public: ue_dl_buffer_occupancy_manager(ue_event_manager& parent_) : parent(parent_) { + pending_evs.reserve(NOF_BEARER_KEYS); std::fill(ue_dl_bo_table.begin(), ue_dl_bo_table.end(), -1); } @@ -61,7 +62,7 @@ class ue_event_manager::ue_dl_buffer_occupancy_manager final : public scheduler_ dl_bo.ue_index = get_ue_index(key); dl_bo.lcid = get_lcid(key); // > Extract last DL BO value for the respective bearer and reset BO table position. - dl_bo.bs = ue_dl_bo_table[key].exchange(-1, std::memory_order_acq_rel); + dl_bo.bs = ue_dl_bo_table[key].exchange(-1, std::memory_order_release); if (dl_bo.bs < 0) { parent.logger.warning( "ue={} lcid={}: Invalid DL buffer occupancy value: {}", dl_bo.ue_index, dl_bo.lcid, dl_bo.bs); From f66f4ee2e796d1b37b7c9c27623ae1b28d1c7a7e Mon Sep 17 00:00:00 2001 From: yagoda Date: Thu, 23 Nov 2023 23:23:49 +0100 Subject: [PATCH 036/134] NTN: adding option to auto-ack all transmitted packets for case where delay is too long for a functional MAC HARQ --- apps/gnb/gnb_appconfig_translators.cpp | 6 ++++-- include/srsran/scheduler/config/scheduler_expert_config.h | 2 ++ lib/scheduler/ue_scheduling/ue_event_manager.cpp | 2 -- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/gnb/gnb_appconfig_translators.cpp b/apps/gnb/gnb_appconfig_translators.cpp index 2fc4e16694..06968f02b6 100644 --- a/apps/gnb/gnb_appconfig_translators.cpp +++ b/apps/gnb/gnb_appconfig_translators.cpp @@ -1656,8 +1656,10 @@ scheduler_expert_config srsran::generate_scheduler_expert_config(const gnb_appco out_cfg.ue.olla_dl_target_bler = pdsch.olla_target_bler; out_cfg.ue.olla_cqi_inc = pdsch.olla_cqi_inc; out_cfg.ue.olla_max_cqi_offset = pdsch.olla_max_cqi_offset; - - const pusch_appconfig& pusch = cell.pusch_cfg; + const pusch_appconfig& pusch = cell.pusch_cfg; + if (config.ntn_cfg.has_value()) { + out_cfg.ue.auto_ack_harq = true; + } out_cfg.ue.ul_mcs = {pusch.min_ue_mcs, pusch.max_ue_mcs}; out_cfg.ue.pusch_rv_sequence.assign(pusch.rv_sequence.begin(), pusch.rv_sequence.end()); out_cfg.ue.initial_ul_dc_offset = pusch.dc_offset; diff --git a/include/srsran/scheduler/config/scheduler_expert_config.h b/include/srsran/scheduler/config/scheduler_expert_config.h index 27c4e3cf6e..b4f870838e 100644 --- a/include/srsran/scheduler/config/scheduler_expert_config.h +++ b/include/srsran/scheduler/config/scheduler_expert_config.h @@ -77,6 +77,8 @@ struct scheduler_ue_expert_config { uint8_t dl_harq_la_cqi_drop_threshold{2}; /// Threshold for drop in nof. layers of the first HARQ transmission above which HARQ retransmission is cancelled. uint8_t dl_harq_la_ri_drop_threshold{1}; + // Automatic HARQ acknowledgement (used for NTN cases with no HARQ feedback) + bool auto_ack_harq{false}; }; /// \brief System Information scheduling statically configurable expert parameters. diff --git a/lib/scheduler/ue_scheduling/ue_event_manager.cpp b/lib/scheduler/ue_scheduling/ue_event_manager.cpp index 9fad3200cf..9b6abe7e80 100644 --- a/lib/scheduler/ue_scheduling/ue_event_manager.cpp +++ b/lib/scheduler/ue_scheduling/ue_event_manager.cpp @@ -283,7 +283,6 @@ void ue_event_manager::handle_harq_ind(ue_cell& ue // Update UE HARQ state with received HARQ-ACK. dl_harq_process::dl_ack_info_result result = ue_cc.handle_dl_ack_info(uci_sl, harq_bits[harq_idx], harq_idx, pucch_snr); - if (result.h_id != INVALID_HARQ_ID) { // Respective HARQ was found. const units::bytes tbs{result.tbs_bytes}; @@ -291,7 +290,6 @@ void ue_event_manager::handle_harq_ind(ue_cell& ue // Log Event. ev_logger.enqueue(scheduler_event_logger::harq_ack_event{ ue_cc.ue_index, ue_cc.rnti(), ue_cc.cell_index, uci_sl, result.h_id, harq_bits[harq_idx], tbs}); - if (result.update == dl_harq_process::status_update::acked or result.update == dl_harq_process::status_update::nacked) { // In case the HARQ process is not waiting for more HARQ-ACK bits. Notify metrics handler with HARQ outcome. From 915e3887e33f9f2de108b64c49b8cfcf839536a1 Mon Sep 17 00:00:00 2001 From: yagoda Date: Wed, 29 Nov 2023 14:48:43 +0100 Subject: [PATCH 037/134] NTN: changing epheremis parameters to WGS84 compliant --- apps/gnb/gnb_appconfig_translators.cpp | 6 ++++++ configs/geo_ntn.yml | 7 +++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/apps/gnb/gnb_appconfig_translators.cpp b/apps/gnb/gnb_appconfig_translators.cpp index 06968f02b6..27a92019bb 100644 --- a/apps/gnb/gnb_appconfig_translators.cpp +++ b/apps/gnb/gnb_appconfig_translators.cpp @@ -419,6 +419,12 @@ static sib19_info create_sib19_info(const gnb_appconfig& config) sib19.cell_specific_koffset = config.ntn_cfg.value().cell_specific_koffset; sib19.ephemeris_info = config.ntn_cfg.value().ephemeris_info; + // These values are provided to the config in ECEF coordinates, but the scheduler expects them in WGS84 with a step + // level of 1.3m + sib19.ephemeris_info.value().position_x /= 1.3; + sib19.ephemeris_info.value().position_y /= 1.3; + sib19.ephemeris_info.value().position_z /= 1.3; + if (config.ntn_cfg.value().distance_threshold.has_value()) { sib19.distance_thres = config.ntn_cfg.value().distance_threshold.value(); } diff --git a/configs/geo_ntn.yml b/configs/geo_ntn.yml index a83283c3b6..22b532bbc8 100644 --- a/configs/geo_ntn.yml +++ b/configs/geo_ntn.yml @@ -2,13 +2,12 @@ ntn: cell_specific_koffset: 260 # sets the maximum possible channel delay ephemeris_info: # ephemeris information for the satellite - pos_x: 23508375 - pos_y: 2211019 - pos_z: 22224489 + pos_x: 4819456 #23508375 + pos_y: 453281 #2211019 + pos_z: 7183667 #22224489 vel_x: 0 vel_y: 0 vel_z: 0 - cell_cfg: sib: # system information block 19 scheduling, SIB19 is the NTN information block si_window_length: 5 From cf476af4f04fd47f80cd5ae7ff740d58a01cfd4b Mon Sep 17 00:00:00 2001 From: yagoda Date: Wed, 29 Nov 2023 15:13:27 +0100 Subject: [PATCH 038/134] NTN: removing unnecessary cell-specific K offset from the PUCCH scheduling --- lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp | 9 ++++----- lib/scheduler/uci_scheduling/uci_allocator_impl.cpp | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp index 0132812c37..234130ae3a 100644 --- a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp +++ b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp @@ -93,10 +93,9 @@ optional pucch_allocator_impl::alloc_common_pucch_harq_ack_ue(cell_res const pdcch_dl_information& dci_info) { // Get the slot allocation grid considering the PDSCH delay (k0) and the PUCCH delay wrt PDSCH (k1). - cell_slot_resource_allocator& pucch_slot_alloc = slot_alloc[k0 + k1 + slot_alloc.cfg.ntn_cs_koffset]; + cell_slot_resource_allocator& pucch_slot_alloc = slot_alloc[k0 + k1]; - if (pucch_slot_alloc.result.ul.pucchs.full() or - pucch_common_alloc_grid[slot_alloc[k0 + k1 + slot_alloc.cfg.ntn_cs_koffset].slot.to_uint()].full()) { + if (pucch_slot_alloc.result.ul.pucchs.full() or pucch_common_alloc_grid[slot_alloc[k0 + k1].slot.to_uint()].full()) { return nullopt; } @@ -122,7 +121,7 @@ optional pucch_allocator_impl::alloc_common_pucch_harq_ack_ue(cell_res fill_pucch_harq_common_grant(pucch_info, tcrnti, pucch_res.value()); unsigned pucch_res_indicator = pucch_res.value().pucch_res_indicator; - pucch_common_alloc_grid[slot_alloc[k0 + k1 + slot_alloc.cfg.ntn_cs_koffset].slot.to_uint()].emplace_back(tcrnti); + pucch_common_alloc_grid[slot_alloc[k0 + k1].slot.to_uint()].emplace_back(tcrnti); logger.debug("tc-rnti={}: PUCCH HARQ-ACK common with res_ind={} allocated for slot={}", tcrnti, @@ -154,7 +153,7 @@ optional pucch_allocator_impl::alloc_ded_pucch_harq_ack_ue(cell_resour // be performed by the caller. // Get the slot allocation grid considering the PDSCH delay (k0) and the PUCCH delay wrt PDSCH (k1). - cell_slot_resource_allocator& pucch_slot_alloc = res_alloc[k0 + k1 + res_alloc.cfg.ntn_cs_koffset]; + cell_slot_resource_allocator& pucch_slot_alloc = res_alloc[k0 + k1]; auto& pucchs = pucch_slot_alloc.result.ul.pucchs; diff --git a/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp b/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp index 65fe401b04..28cd230361 100644 --- a/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp +++ b/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp @@ -100,7 +100,7 @@ optional uci_allocator_impl::alloc_uci_harq_ue_helper(cell_resou unsigned k1, const pdcch_dl_information* fallback_dci_info) { - cell_slot_resource_allocator& slot_alloc = res_alloc[k0 + k1 + res_alloc.cfg.ntn_cs_koffset]; + cell_slot_resource_allocator& slot_alloc = res_alloc[k0 + k1]; // Get existing PUSCH grant, if any, for a given UE's RNTI. auto& puschs = slot_alloc.result.ul.puschs; From 16b64183dd3f487128664edf3cb31f4694a67fbc Mon Sep 17 00:00:00 2001 From: yagoda Date: Wed, 29 Nov 2023 16:17:21 +0100 Subject: [PATCH 039/134] NTN: adapting HARQ processes for large delay scenarios, adding ntn harq entity --- lib/scheduler/ue_scheduling/harq_process.cpp | 19 ++++++- lib/scheduler/ue_scheduling/harq_process.h | 50 ++++++++++++++++++- lib/scheduler/ue_scheduling/ue.cpp | 1 + lib/scheduler/ue_scheduling/ue_cell.cpp | 4 +- .../ue_scheduling/ue_cell_grid_allocator.cpp | 6 ++- 5 files changed, 73 insertions(+), 7 deletions(-) diff --git a/lib/scheduler/ue_scheduling/harq_process.cpp b/lib/scheduler/ue_scheduling/harq_process.cpp index 3324991660..cd260648fb 100644 --- a/lib/scheduler/ue_scheduling/harq_process.cpp +++ b/lib/scheduler/ue_scheduling/harq_process.cpp @@ -368,11 +368,14 @@ harq_entity::harq_entity(rnti_t rnti_, unsigned nof_dl_harq_procs, unsigned nof_ul_harq_procs, ue_harq_timeout_notifier timeout_notif, + unsigned ntn_cs_koffset, unsigned max_ack_wait_in_slots) : rnti(rnti_), logger(srslog::fetch_basic_logger("SCHED")), dl_h_logger(logger, rnti_, to_du_cell_index(0), true), - ul_h_logger(logger, rnti_, to_du_cell_index(0), false) + ul_h_logger(logger, rnti_, to_du_cell_index(0), false), + nop_timeout_notifier(), + ntn_harq(ntn_cs_koffset) { // Create HARQ processes dl_harqs.reserve(nof_dl_harq_procs); @@ -381,7 +384,11 @@ harq_entity::harq_entity(rnti_t rnti_, dl_harqs.emplace_back(to_harq_id(id), dl_h_logger, timeout_notif, max_ack_wait_in_slots); } for (unsigned id = 0; id != nof_ul_harq_procs; ++id) { - ul_harqs.emplace_back(to_harq_id(id), ul_h_logger, timeout_notif, max_ack_wait_in_slots); + if (ntn_harq.active()) { + ul_harqs.emplace_back(to_harq_id(id), ul_h_logger, nop_timeout_notifier, 1); + } else { + ul_harqs.emplace_back(to_harq_id(id), ul_h_logger, timeout_notif, max_ack_wait_in_slots); + } } } @@ -392,6 +399,9 @@ void harq_entity::slot_indication(slot_point slot_tx_) dl_h.slot_indication(slot_tx); } for (ul_harq_process& ul_h : ul_harqs) { + if (ntn_harq.active()) { + ntn_harq.save_tbs(ul_h, slot_tx); + } ul_h.slot_indication(slot_tx); } } @@ -424,6 +434,9 @@ int harq_entity::ul_crc_info(harq_id_t h_id, bool ack, slot_point pusch_slot) { ul_harq_process& h_ul = ul_harq(h_id); if (h_ul.empty() or h_ul.slot_ack() != pusch_slot) { + if (ntn_harq.active() && ack == true) { + return ntn_harq.get_tbs(pusch_slot); + } ul_h_logger.warning(h_id, "Discarding CRC. Cause: No active UL HARQ expecting a CRC at slot={}", pusch_slot); return -1; } @@ -450,3 +463,5 @@ void harq_entity::dl_ack_info_cancelled(slot_point uci_slot) } } } + +harq_entity::ntn_harq_agent::ntn_harq_agent(unsigned ntn_cs_koffset_) : ntn_cs_koffset(ntn_cs_koffset_) {} diff --git a/lib/scheduler/ue_scheduling/harq_process.h b/lib/scheduler/ue_scheduling/harq_process.h index b7012856fb..4d215eea29 100644 --- a/lib/scheduler/ue_scheduling/harq_process.h +++ b/lib/scheduler/ue_scheduling/harq_process.h @@ -22,6 +22,7 @@ #include "srsran/scheduler/sched_consts.h" #include "srsran/scheduler/scheduler_dci.h" #include "srsran/support/format_utils.h" +#include namespace srsran { @@ -401,6 +402,12 @@ class ul_harq_process : private detail::harq_process /// Cancels the HARQ and stops retransmitting the specified TB until the next new transmission. void cancel_harq(); + /// \brief Getter of the number of bytes of the last transmitted TB. + int get_tbs_bytes() const { return prev_tx_params.tbs_bytes; } + + /// \brief Getter of the slot when the HARQ process will assume that the ACK/CRC went missing. + slot_point get_slot_ack_timeout() const { return slot_ack_timeout; } + private: /// Parameters used for the last Tx of this HARQ process. alloc_params prev_tx_params; @@ -431,7 +438,8 @@ class harq_entity unsigned nof_dl_harq_procs, unsigned nof_ul_harq_procs, ue_harq_timeout_notifier timeout_notif, - unsigned max_ack_wait_in_slots = detail::harq_process::DEFAULT_ACK_TIMEOUT_SLOTS); + unsigned ntn_cs_koffset = 0, + unsigned max_ack_wait_in_slots = detail::harq_process::DEFAULT_ACK_TIMEOUT_SLOTS); /// Update slot, and checks if there are HARQ processes that have reached maxReTx with no ACK void slot_indication(slot_point slot_tx_); @@ -523,6 +531,14 @@ class harq_entity return nullptr; } + unsigned get_tbs_pending_crcs() const + { + if (ntn_harq.active()) { + return ntn_harq.get_total_tbs(); + } + return 0; + } + private: template harq_id_t find_oldest_harq_retx(const HarqVector& harqs) const @@ -558,6 +574,36 @@ class harq_entity return harq_id_t::INVALID_HARQ_ID; } + class ntn_harq_agent + { + public: + explicit ntn_harq_agent(unsigned ntn_cs_koffset_); + bool active() const { return ntn_cs_koffset != 0; } + void save_tbs(ul_harq_process& ul_h, slot_point slot_tx) + { + if (ul_h.empty()) { + return; + } + if (ul_h.get_slot_ack_timeout() <= slot_tx) { + int tbs = ul_h.get_tbs_bytes(); + int idx = (ul_h.slot_ack().to_uint() + ntn_cs_koffset) % slot_tbs.size(); + slot_tbs.at(idx) = tbs; + } + } + int get_tbs(slot_point slot_tx) + { + int ret = slot_tbs.at(slot_tx.to_uint() % slot_tbs.size()); + if (ret) { + slot_tbs.at(slot_tx.to_uint() % slot_tbs.size()) = 0; + } else { + return -1; + } + return ret; + } + int get_total_tbs() const { return std::accumulate(slot_tbs.begin(), slot_tbs.end(), 0); } + std::array slot_tbs; + unsigned ntn_cs_koffset; + }; rnti_t rnti; srslog::basic_logger& logger; harq_logger dl_h_logger; @@ -567,6 +613,8 @@ class harq_entity slot_point slot_tx; std::vector dl_harqs; std::vector ul_harqs; + ue_harq_timeout_notifier nop_timeout_notifier; + ntn_harq_agent ntn_harq; }; } // namespace srsran diff --git a/lib/scheduler/ue_scheduling/ue.cpp b/lib/scheduler/ue_scheduling/ue.cpp index 6c91158b15..17a22f74b0 100644 --- a/lib/scheduler/ue_scheduling/ue.cpp +++ b/lib/scheduler/ue_scheduling/ue.cpp @@ -143,6 +143,7 @@ unsigned ue::pending_ul_newtx_bytes() const harq_bytes += h_ul.last_tx_params().tbs_bytes; } } + harq_bytes += ue_cc->harqs.get_tbs_pending_crcs(); pending_bytes -= std::min(pending_bytes, harq_bytes); } diff --git a/lib/scheduler/ue_scheduling/ue_cell.cpp b/lib/scheduler/ue_scheduling/ue_cell.cpp index f3767651de..56bf6588d0 100644 --- a/lib/scheduler/ue_scheduling/ue_cell.cpp +++ b/lib/scheduler/ue_scheduling/ue_cell.cpp @@ -30,7 +30,8 @@ ue_cell::ue_cell(du_ue_index_t ue_index_, harqs(crnti_val, (unsigned)ue_cell_cfg_.cfg_dedicated().pdsch_serv_cell_cfg->nof_harq_proc, NOF_UL_HARQS, - harq_timeout_notifier), + harq_timeout_notifier, + ue_cell_cfg_.cell_cfg_common.ntn_cs_koffset), crnti_(crnti_val), cell_cfg(ue_cell_cfg_.cell_cfg_common), ue_cfg(&ue_cell_cfg_), @@ -40,7 +41,6 @@ ue_cell::ue_cell(du_ue_index_t ue_index_, ue_mcs_calculator(ue_cell_cfg_.cell_cfg_common, channel_state) { } - void ue_cell::deactivate() { // Stop UL HARQ retransmissions. diff --git a/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp b/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp index 12f191960e..6ab8c16a1e 100644 --- a/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp +++ b/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp @@ -648,13 +648,15 @@ alloc_outcome ue_cell_grid_allocator::allocate_ul_grant(const ue_pusch_grant& gr // Mark resources as occupied in the ResourceGrid. pusch_alloc.ul_res_grid.fill(grant_info{scs, pusch_td_cfg.symbols, grant.crbs}); + // Remove NTN offset when adding slot to HARQ process. + slot_point harq_slot = pusch_alloc.slot - ue_cell_cfg.cell_cfg_common.ntn_cs_koffset; // Allocate UE UL HARQ. if (h_ul.empty()) { // It is a new tx. - h_ul.new_tx(pusch_alloc.slot, expert_cfg.max_nof_harq_retxs); + h_ul.new_tx(harq_slot, expert_cfg.max_nof_harq_retxs); } else { // It is a retx. - h_ul.new_retx(pusch_alloc.slot); + h_ul.new_retx(harq_slot); } // Compute total DAI. See TS 38.213, 9.1.3.2. From c22a6dcb2a4b37caffdc987dd7d0fbfdc7523a75 Mon Sep 17 00:00:00 2001 From: yagoda Date: Sun, 3 Dec 2023 14:16:08 +0100 Subject: [PATCH 040/134] NTN: cleaning up ntn harq object --- apps/gnb/gnb_appconfig_translators.cpp | 4 +- lib/scheduler/ue_scheduling/harq_process.cpp | 18 +++++++-- lib/scheduler/ue_scheduling/harq_process.h | 37 +++++++++++++------ lib/scheduler/ue_scheduling/ue.cpp | 2 +- .../ue_scheduling/harq_entity_test.cpp | 2 +- 5 files changed, 44 insertions(+), 19 deletions(-) diff --git a/apps/gnb/gnb_appconfig_translators.cpp b/apps/gnb/gnb_appconfig_translators.cpp index 27a92019bb..c45251bd4b 100644 --- a/apps/gnb/gnb_appconfig_translators.cpp +++ b/apps/gnb/gnb_appconfig_translators.cpp @@ -420,7 +420,7 @@ static sib19_info create_sib19_info(const gnb_appconfig& config) sib19.ephemeris_info = config.ntn_cfg.value().ephemeris_info; // These values are provided to the config in ECEF coordinates, but the scheduler expects them in WGS84 with a step - // level of 1.3m + // level of 1.3m. sib19.ephemeris_info.value().position_x /= 1.3; sib19.ephemeris_info.value().position_y /= 1.3; sib19.ephemeris_info.value().position_z /= 1.3; @@ -1666,7 +1666,7 @@ scheduler_expert_config srsran::generate_scheduler_expert_config(const gnb_appco if (config.ntn_cfg.has_value()) { out_cfg.ue.auto_ack_harq = true; } - out_cfg.ue.ul_mcs = {pusch.min_ue_mcs, pusch.max_ue_mcs}; + out_cfg.ue.ul_mcs = {pusch.min_ue_mcs, pusch.max_ue_mcs}; out_cfg.ue.pusch_rv_sequence.assign(pusch.rv_sequence.begin(), pusch.rv_sequence.end()); out_cfg.ue.initial_ul_dc_offset = pusch.dc_offset; out_cfg.ue.max_puschs_per_slot = pusch.max_puschs_per_slot; diff --git a/lib/scheduler/ue_scheduling/harq_process.cpp b/lib/scheduler/ue_scheduling/harq_process.cpp index cd260648fb..a71b05635d 100644 --- a/lib/scheduler/ue_scheduling/harq_process.cpp +++ b/lib/scheduler/ue_scheduling/harq_process.cpp @@ -383,9 +383,10 @@ harq_entity::harq_entity(rnti_t rnti_, for (unsigned id = 0; id < nof_dl_harq_procs; ++id) { dl_harqs.emplace_back(to_harq_id(id), dl_h_logger, timeout_notif, max_ack_wait_in_slots); } + for (unsigned id = 0; id != nof_ul_harq_procs; ++id) { if (ntn_harq.active()) { - ul_harqs.emplace_back(to_harq_id(id), ul_h_logger, nop_timeout_notifier, 1); + ul_harqs.emplace_back(to_harq_id(id), ul_h_logger, nop_timeout_notifier, ntn_harq.ntn_harq_timeout); } else { ul_harqs.emplace_back(to_harq_id(id), ul_h_logger, timeout_notif, max_ack_wait_in_slots); } @@ -434,8 +435,12 @@ int harq_entity::ul_crc_info(harq_id_t h_id, bool ack, slot_point pusch_slot) { ul_harq_process& h_ul = ul_harq(h_id); if (h_ul.empty() or h_ul.slot_ack() != pusch_slot) { - if (ntn_harq.active() && ack == true) { - return ntn_harq.get_tbs(pusch_slot); + if (ntn_harq.active()) { + if (ack == true) { + return ntn_harq.pop_tbs(pusch_slot); + } else { + ntn_harq.clear_tbs(pusch_slot); + } } ul_h_logger.warning(h_id, "Discarding CRC. Cause: No active UL HARQ expecting a CRC at slot={}", pusch_slot); return -1; @@ -464,4 +469,9 @@ void harq_entity::dl_ack_info_cancelled(slot_point uci_slot) } } -harq_entity::ntn_harq_agent::ntn_harq_agent(unsigned ntn_cs_koffset_) : ntn_cs_koffset(ntn_cs_koffset_) {} +harq_entity::ntn_tbs_history::ntn_tbs_history(unsigned ntn_cs_koffset_) : ntn_cs_koffset(ntn_cs_koffset_) +{ + if (ntn_cs_koffset > 0) { + slot_tbs.resize(NTN_CELL_SPECIFIC_KOFFSET_MAX); + } +} \ No newline at end of file diff --git a/lib/scheduler/ue_scheduling/harq_process.h b/lib/scheduler/ue_scheduling/harq_process.h index 4d215eea29..d8cb0fb85e 100644 --- a/lib/scheduler/ue_scheduling/harq_process.h +++ b/lib/scheduler/ue_scheduling/harq_process.h @@ -531,7 +531,7 @@ class harq_entity return nullptr; } - unsigned get_tbs_pending_crcs() const + unsigned ntn_get_tbs_pending_crcs() const { if (ntn_harq.active()) { return ntn_harq.get_total_tbs(); @@ -574,35 +574,50 @@ class harq_entity return harq_id_t::INVALID_HARQ_ID; } - class ntn_harq_agent + class ntn_tbs_history { public: - explicit ntn_harq_agent(unsigned ntn_cs_koffset_); + /// \brief This class is used to store the TBS of the HARQ processes that have to be released before receiving the + /// associated PUSCH. + explicit ntn_tbs_history(unsigned ntn_cs_koffset_); + bool active() const { return ntn_cs_koffset != 0; } - void save_tbs(ul_harq_process& ul_h, slot_point slot_tx) + + /// \brief This function is used to save the TBS of the HARQ process. + void save_tbs(ul_harq_process& ul_h, slot_point _slot_tx) { if (ul_h.empty()) { return; } - if (ul_h.get_slot_ack_timeout() <= slot_tx) { + if (ul_h.get_slot_ack_timeout() <= _slot_tx) { int tbs = ul_h.get_tbs_bytes(); int idx = (ul_h.slot_ack().to_uint() + ntn_cs_koffset) % slot_tbs.size(); slot_tbs.at(idx) = tbs; } } - int get_tbs(slot_point slot_tx) + + /// \brief This function is used to pop the TBS of the HARQ process saved at the slot _slot_tx. + int pop_tbs(slot_point _slot_tx) { - int ret = slot_tbs.at(slot_tx.to_uint() % slot_tbs.size()); + int ret = slot_tbs.at(_slot_tx.to_uint() % slot_tbs.size()); if (ret) { - slot_tbs.at(slot_tx.to_uint() % slot_tbs.size()) = 0; + slot_tbs.at(_slot_tx.to_uint() % slot_tbs.size()) = 0; } else { return -1; } return ret; } + + /// \brief This function is used to clear the TBS of the HARQ process saved at the slot _slot_tx. + void clear_tbs(slot_point _slot_tx) { slot_tbs.at(_slot_tx.to_uint() % slot_tbs.size()) = 0; } + /// \brief This function is used to get the total TBS of the HARQ processes saved. int get_total_tbs() const { return std::accumulate(slot_tbs.begin(), slot_tbs.end(), 0); } - std::array slot_tbs; - unsigned ntn_cs_koffset; + // We timeout the HARQ since we need to reuse the process before the PUSCH arrives. + const unsigned ntn_harq_timeout = 1; + + private: + std::vector slot_tbs; + unsigned ntn_cs_koffset; }; rnti_t rnti; srslog::basic_logger& logger; @@ -614,7 +629,7 @@ class harq_entity std::vector dl_harqs; std::vector ul_harqs; ue_harq_timeout_notifier nop_timeout_notifier; - ntn_harq_agent ntn_harq; + ntn_tbs_history ntn_harq; }; } // namespace srsran diff --git a/lib/scheduler/ue_scheduling/ue.cpp b/lib/scheduler/ue_scheduling/ue.cpp index 17a22f74b0..26308d2511 100644 --- a/lib/scheduler/ue_scheduling/ue.cpp +++ b/lib/scheduler/ue_scheduling/ue.cpp @@ -143,7 +143,7 @@ unsigned ue::pending_ul_newtx_bytes() const harq_bytes += h_ul.last_tx_params().tbs_bytes; } } - harq_bytes += ue_cc->harqs.get_tbs_pending_crcs(); + harq_bytes += ue_cc->harqs.ntn_get_tbs_pending_crcs(); pending_bytes -= std::min(pending_bytes, harq_bytes); } diff --git a/tests/unittests/scheduler/ue_scheduling/harq_entity_test.cpp b/tests/unittests/scheduler/ue_scheduling/harq_entity_test.cpp index 75e37a2517..0f58b53c1e 100644 --- a/tests/unittests/scheduler/ue_scheduling/harq_entity_test.cpp +++ b/tests/unittests/scheduler/ue_scheduling/harq_entity_test.cpp @@ -46,7 +46,7 @@ TEST(harq_entity, when_all_harqs_are_allocated_harq_entity_cannot_find_empty_har TEST(harq_entity, after_max_ack_wait_timeout_dl_harqs_are_available_for_retx) { unsigned nof_harqs = 8, max_ack_wait_slots = 4; - harq_entity harq_ent(to_rnti(0x4601), nof_harqs, nof_harqs, {}, max_ack_wait_slots); + harq_entity harq_ent(to_rnti(0x4601), nof_harqs, nof_harqs, {}, 0, max_ack_wait_slots); slot_point sl_tx{0, 0}; unsigned ack_delay = 4; From 213a020965823ee01a30e9330b056a3487970602 Mon Sep 17 00:00:00 2001 From: yagoda Date: Tue, 19 Dec 2023 17:10:12 +0100 Subject: [PATCH 041/134] NTN: adding downlink support to NTN harq object --- .../pucch_scheduling/pucch_allocator_impl.cpp | 9 +-- .../uci_scheduling/uci_allocator_impl.cpp | 2 +- lib/scheduler/ue_scheduling/harq_process.cpp | 16 ++++- lib/scheduler/ue_scheduling/harq_process.h | 61 ++++++++++++++----- 4 files changed, 66 insertions(+), 22 deletions(-) diff --git a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp index 234130ae3a..0132812c37 100644 --- a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp +++ b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp @@ -93,9 +93,10 @@ optional pucch_allocator_impl::alloc_common_pucch_harq_ack_ue(cell_res const pdcch_dl_information& dci_info) { // Get the slot allocation grid considering the PDSCH delay (k0) and the PUCCH delay wrt PDSCH (k1). - cell_slot_resource_allocator& pucch_slot_alloc = slot_alloc[k0 + k1]; + cell_slot_resource_allocator& pucch_slot_alloc = slot_alloc[k0 + k1 + slot_alloc.cfg.ntn_cs_koffset]; - if (pucch_slot_alloc.result.ul.pucchs.full() or pucch_common_alloc_grid[slot_alloc[k0 + k1].slot.to_uint()].full()) { + if (pucch_slot_alloc.result.ul.pucchs.full() or + pucch_common_alloc_grid[slot_alloc[k0 + k1 + slot_alloc.cfg.ntn_cs_koffset].slot.to_uint()].full()) { return nullopt; } @@ -121,7 +122,7 @@ optional pucch_allocator_impl::alloc_common_pucch_harq_ack_ue(cell_res fill_pucch_harq_common_grant(pucch_info, tcrnti, pucch_res.value()); unsigned pucch_res_indicator = pucch_res.value().pucch_res_indicator; - pucch_common_alloc_grid[slot_alloc[k0 + k1].slot.to_uint()].emplace_back(tcrnti); + pucch_common_alloc_grid[slot_alloc[k0 + k1 + slot_alloc.cfg.ntn_cs_koffset].slot.to_uint()].emplace_back(tcrnti); logger.debug("tc-rnti={}: PUCCH HARQ-ACK common with res_ind={} allocated for slot={}", tcrnti, @@ -153,7 +154,7 @@ optional pucch_allocator_impl::alloc_ded_pucch_harq_ack_ue(cell_resour // be performed by the caller. // Get the slot allocation grid considering the PDSCH delay (k0) and the PUCCH delay wrt PDSCH (k1). - cell_slot_resource_allocator& pucch_slot_alloc = res_alloc[k0 + k1]; + cell_slot_resource_allocator& pucch_slot_alloc = res_alloc[k0 + k1 + res_alloc.cfg.ntn_cs_koffset]; auto& pucchs = pucch_slot_alloc.result.ul.pucchs; diff --git a/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp b/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp index 28cd230361..65fe401b04 100644 --- a/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp +++ b/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp @@ -100,7 +100,7 @@ optional uci_allocator_impl::alloc_uci_harq_ue_helper(cell_resou unsigned k1, const pdcch_dl_information* fallback_dci_info) { - cell_slot_resource_allocator& slot_alloc = res_alloc[k0 + k1]; + cell_slot_resource_allocator& slot_alloc = res_alloc[k0 + k1 + res_alloc.cfg.ntn_cs_koffset]; // Get existing PUSCH grant, if any, for a given UE's RNTI. auto& puschs = slot_alloc.result.ul.puschs; diff --git a/lib/scheduler/ue_scheduling/harq_process.cpp b/lib/scheduler/ue_scheduling/harq_process.cpp index a71b05635d..db7da80601 100644 --- a/lib/scheduler/ue_scheduling/harq_process.cpp +++ b/lib/scheduler/ue_scheduling/harq_process.cpp @@ -381,7 +381,11 @@ harq_entity::harq_entity(rnti_t rnti_, dl_harqs.reserve(nof_dl_harq_procs); ul_harqs.reserve(nof_ul_harq_procs); for (unsigned id = 0; id < nof_dl_harq_procs; ++id) { - dl_harqs.emplace_back(to_harq_id(id), dl_h_logger, timeout_notif, max_ack_wait_in_slots); + if (ntn_harq.active()) { + dl_harqs.emplace_back(to_harq_id(id), dl_h_logger, nop_timeout_notifier, ntn_harq.ntn_harq_timeout); + } else { + dl_harqs.emplace_back(to_harq_id(id), dl_h_logger, timeout_notif, max_ack_wait_in_slots); + } } for (unsigned id = 0; id != nof_ul_harq_procs; ++id) { @@ -397,11 +401,14 @@ void harq_entity::slot_indication(slot_point slot_tx_) { slot_tx = slot_tx_; for (dl_harq_process& dl_h : dl_harqs) { + if (ntn_harq.active()) { + ntn_harq.save_dl_harq_info(dl_h, slot_tx_); + } dl_h.slot_indication(slot_tx); } for (ul_harq_process& ul_h : ul_harqs) { if (ntn_harq.active()) { - ntn_harq.save_tbs(ul_h, slot_tx); + ntn_harq.save_ul_harq_info(ul_h, slot_tx_); } ul_h.slot_indication(slot_tx); } @@ -425,6 +432,8 @@ dl_harq_process::dl_ack_info_result harq_entity::dl_ack_info(slot_point h_dl.last_alloc_params().tb[0]->mcs, h_dl.last_alloc_params().tb[0]->tbs_bytes, status_upd}; + } else if (ntn_harq.active()) { + return ntn_harq.pop_ack_info(uci_slot, ack); } } logger.warning("DL HARQ for rnti={}, uci slot={} not found.", rnti, uci_slot); @@ -473,5 +482,6 @@ harq_entity::ntn_tbs_history::ntn_tbs_history(unsigned ntn_cs_koffset_) : ntn_cs { if (ntn_cs_koffset > 0) { slot_tbs.resize(NTN_CELL_SPECIFIC_KOFFSET_MAX); + slot_ack_info.resize(NTN_CELL_SPECIFIC_KOFFSET_MAX); } -} \ No newline at end of file +} diff --git a/lib/scheduler/ue_scheduling/harq_process.h b/lib/scheduler/ue_scheduling/harq_process.h index d8cb0fb85e..75327d9b7c 100644 --- a/lib/scheduler/ue_scheduling/harq_process.h +++ b/lib/scheduler/ue_scheduling/harq_process.h @@ -206,6 +206,9 @@ class harq_process /// Cancelled HARQ processes do not require the HARQ-ACK to be received to get flushed. void cancel_harq(unsigned tb_idx); + /// \brief Getter of the slot when the HARQ process will assume that the ACK/CRC went missing. + slot_point get_slot_ack_timeout() const { return slot_ack_timeout; } + protected: void tx_common(slot_point slot_tx, slot_point slot_ack); void new_tx_tb_common(unsigned tb_idx, unsigned max_nof_harq_retxs, uint8_t harq_bit_idx); @@ -360,6 +363,7 @@ class ul_harq_process : private detail::harq_process using base_type::transport_block; + using base_type::get_slot_ack_timeout; using base_type::harq_process; using base_type::id; using base_type::reset; @@ -405,9 +409,6 @@ class ul_harq_process : private detail::harq_process /// \brief Getter of the number of bytes of the last transmitted TB. int get_tbs_bytes() const { return prev_tx_params.tbs_bytes; } - /// \brief Getter of the slot when the HARQ process will assume that the ACK/CRC went missing. - slot_point get_slot_ack_timeout() const { return slot_ack_timeout; } - private: /// Parameters used for the last Tx of this HARQ process. alloc_params prev_tx_params; @@ -577,29 +578,58 @@ class harq_entity class ntn_tbs_history { public: - /// \brief This class is used to store the TBS of the HARQ processes that have to be released before receiving the - /// associated PUSCH. + /// \brief This class is used to store the TBS of the HARQ processes that have to be released before they have been + /// completed by an ACK or a PUSCH. explicit ntn_tbs_history(unsigned ntn_cs_koffset_); bool active() const { return ntn_cs_koffset != 0; } /// \brief This function is used to save the TBS of the HARQ process. - void save_tbs(ul_harq_process& ul_h, slot_point _slot_tx) + void save_dl_harq_info(const dl_harq_process& harq, const slot_point& _slot_tx) + { + if (harq.empty()) { + return; + } + if (harq.get_slot_ack_timeout() <= _slot_tx) { + int idx = (harq.slot_ack().to_uint() + ntn_cs_koffset) % slot_ack_info.size(); + slot_ack_info.at(idx).tbs_bytes = harq.last_alloc_params().tb[0]->tbs_bytes; + slot_ack_info.at(idx).h_id = harq.id; + slot_ack_info.at(idx).mcs = harq.last_alloc_params().tb[0]->mcs; + slot_ack_info.at(idx).mcs_table = harq.last_alloc_params().tb[0]->mcs_table; + slot_ack_info.at(idx).update = dl_harq_process::status_update::acked; + } + } + + /// \brief This function is used to save the ack info of the HARQ process. + void save_ul_harq_info(const ul_harq_process& harq, const slot_point& _slot_tx) { - if (ul_h.empty()) { + if (harq.empty()) { return; } - if (ul_h.get_slot_ack_timeout() <= _slot_tx) { - int tbs = ul_h.get_tbs_bytes(); - int idx = (ul_h.slot_ack().to_uint() + ntn_cs_koffset) % slot_tbs.size(); - slot_tbs.at(idx) = tbs; + if (harq.get_slot_ack_timeout() <= _slot_tx) { + int idx = (harq.slot_ack().to_uint() + ntn_cs_koffset) % slot_tbs.size(); + slot_tbs.at(idx) = harq.get_tbs_bytes(); } } + /// \brief This function is used to pop the ack info of the HARQ process saved at the slot _slot_tx. + dl_harq_process::dl_ack_info_result pop_ack_info(const slot_point& _slot_tx, mac_harq_ack_report_status ack) + { + auto ret = slot_ack_info.at(_slot_tx.to_uint() % slot_ack_info.size()); + if (ret.tbs_bytes) { + slot_ack_info.at(_slot_tx.to_uint() % slot_ack_info.size()) = {}; + } else { + return {}; + } + ret.update = ack == mac_harq_ack_report_status::ack ? dl_harq_process::status_update::acked + : dl_harq_process::status_update::nacked; + return ret; + } + /// \brief This function is used to pop the TBS of the HARQ process saved at the slot _slot_tx. - int pop_tbs(slot_point _slot_tx) + int pop_tbs(const slot_point& _slot_tx) { - int ret = slot_tbs.at(_slot_tx.to_uint() % slot_tbs.size()); + unsigned ret = slot_tbs.at(_slot_tx.to_uint() % slot_tbs.size()); if (ret) { slot_tbs.at(_slot_tx.to_uint() % slot_tbs.size()) = 0; } else { @@ -614,10 +644,13 @@ class harq_entity int get_total_tbs() const { return std::accumulate(slot_tbs.begin(), slot_tbs.end(), 0); } // We timeout the HARQ since we need to reuse the process before the PUSCH arrives. const unsigned ntn_harq_timeout = 1; + /// \brief The function is used to get the ntn koffset. + unsigned get_ntn_koffset() const { return ntn_cs_koffset; } private: std::vector slot_tbs; - unsigned ntn_cs_koffset; + std::vector slot_ack_info; + unsigned ntn_cs_koffset; }; rnti_t rnti; srslog::basic_logger& logger; From 984c92f214a13841336017a49db16e5c674ece3d Mon Sep 17 00:00:00 2001 From: yagoda Date: Thu, 4 Jan 2024 11:24:09 +0100 Subject: [PATCH 042/134] NTN, harq: set log message to info for NTN case --- lib/scheduler/ue_scheduling/harq_process.cpp | 11 +++++++++-- lib/scheduler/ue_scheduling/harq_process.h | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/scheduler/ue_scheduling/harq_process.cpp b/lib/scheduler/ue_scheduling/harq_process.cpp index db7da80601..a4913185bc 100644 --- a/lib/scheduler/ue_scheduling/harq_process.cpp +++ b/lib/scheduler/ue_scheduling/harq_process.cpp @@ -95,12 +95,19 @@ void detail::harq_process::slot_indication(slot_point slot_tx) } else { // Max number of reTxs was exceeded. Clear HARQ process. tb.state = transport_block::state_t::empty; - logger.warning(id, + fmt::memory_buffer fmtbuf; + fmt::format_to(fmtbuf, "Discarding HARQ. Cause: HARQ-ACK wait timeout ({} slots) was reached, but there are still " "missing HARQ-ACKs, none of the received so far are positive and the maximum number of reTxs {} " "was exceeded", slot_ack_timeout - last_slot_ack, - max_nof_harq_retxs(0)); + tb.max_nof_harq_retxs); + + if (max_ack_wait_in_slots == 1) { + logger.info(id, to_c_str(fmtbuf)); + } else { + logger.warning(id, to_c_str(fmtbuf)); + } } // Report timeout with NACK. diff --git a/lib/scheduler/ue_scheduling/harq_process.h b/lib/scheduler/ue_scheduling/harq_process.h index 75327d9b7c..704f957e7b 100644 --- a/lib/scheduler/ue_scheduling/harq_process.h +++ b/lib/scheduler/ue_scheduling/harq_process.h @@ -648,7 +648,7 @@ class harq_entity unsigned get_ntn_koffset() const { return ntn_cs_koffset; } private: - std::vector slot_tbs; + std::vector slot_tbs; std::vector slot_ack_info; unsigned ntn_cs_koffset; }; From ddaf393450e83e2c7a6d38e697311601671c5c2f Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 2 Jan 2024 15:10:50 +0100 Subject: [PATCH 043/134] phy: review PUSCH processor resource grid with zeros --- .../short/short_block_detector_impl.cpp | 6 +- .../pusch/pusch_demodulator_impl.cpp | 23 +++--- .../short/short_block_detector_test.cpp | 16 ++++ .../pusch/pusch_processor_vectortest.cpp | 73 +++++++++++++++++++ 4 files changed, 106 insertions(+), 12 deletions(-) diff --git a/lib/phy/upper/channel_coding/short/short_block_detector_impl.cpp b/lib/phy/upper/channel_coding/short/short_block_detector_impl.cpp index 769a8f8434..8c207ffb76 100644 --- a/lib/phy/upper/channel_coding/short/short_block_detector_impl.cpp +++ b/lib/phy/upper/channel_coding/short/short_block_detector_impl.cpp @@ -13,7 +13,6 @@ #include "srsran/adt/static_vector.h" #include "srsran/srsvec/bit.h" #include "srsran/srsvec/dot_prod.h" -#include "srsran/support/math_utils.h" using namespace srsran; @@ -159,6 +158,11 @@ bool short_block_detector_impl::detect(span output, unsigned bits_per_symbol = get_bits_per_symbol(mod); validate_spans(output, input, bits_per_symbol); + // If all input bits are zero, the result is invalid. + if (std::all_of(input.begin(), input.end(), [](log_likelihood_ratio bit) { return bit == 0; })) { + return false; + } + static_vector tmp; double max_metric = 0; diff --git a/lib/phy/upper/channel_processors/pusch/pusch_demodulator_impl.cpp b/lib/phy/upper/channel_processors/pusch/pusch_demodulator_impl.cpp index 7720ff1f19..d2190c0754 100644 --- a/lib/phy/upper/channel_processors/pusch/pusch_demodulator_impl.cpp +++ b/lib/phy/upper/channel_processors/pusch/pusch_demodulator_impl.cpp @@ -14,8 +14,6 @@ #include "pusch_demodulator_impl.h" #include "srsran/phy/upper/channel_processors/pusch/pusch_codeword_buffer.h" #include "srsran/phy/upper/channel_processors/pusch/pusch_demodulator_notifier.h" -#include "srsran/ran/sch_dmrs_power.h" -#include "srsran/srsvec/mean.h" #if defined(__SSE3__) #include @@ -57,7 +55,7 @@ revert_scrambling(span out, span(&in[i])); // Negate. v = _mm_xor_si128(mask, v); @@ -66,7 +64,7 @@ revert_scrambling(span out, span(&out[i]), v); } #endif // __SSE3__ @@ -182,6 +180,10 @@ void pusch_demodulator_impl::demodulate(pusch_codeword_buffer& codeword_buf } // Limit block size if the codeword block is smaller. + srsran_assert(codeword_block.size() % nof_bits_per_re == 0, + "The codeword block size (i.e., {}) must be multiple of the number of bits per RE (i.e., {}).", + codeword_block.size(), + nof_bits_per_re); nof_block_subc = std::min(nof_block_subc, static_cast(codeword_block.size()) / nof_bits_per_re); // Extract mask for the block. @@ -259,11 +261,11 @@ void pusch_demodulator_impl::demodulate(pusch_codeword_buffer& codeword_buf // Update and notify statistics. if (i_subc == i_subc_end) { - if (sinr_softbit_count != 0) { - if (noise_var_accumulate > 0.0) { - float mean_noise_var = noise_var_accumulate / static_cast(sinr_softbit_count); - stats.sinr_dB.emplace(-convert_power_to_dB(mean_noise_var)); - } + if ((sinr_softbit_count != 0) && (noise_var_accumulate > 0.0)) { + float mean_noise_var = noise_var_accumulate / static_cast(sinr_softbit_count); + stats.sinr_dB.emplace(-convert_power_to_dB(mean_noise_var)); + } else { + stats.sinr_dB.emplace(std::numeric_limits::infinity()); } if (evm_symbol_count != 0) { stats.evm.emplace(evm_accumulate / static_cast(evm_symbol_count)); @@ -272,8 +274,7 @@ void pusch_demodulator_impl::demodulate(pusch_codeword_buffer& codeword_buf } // Generate scrambling sequence. - static_bit_buffer temp_scrambling_seq(nof_block_softbits); - bit_buffer scrambling_seq = temp_scrambling_seq; + static_bit_buffer scrambling_seq(nof_block_softbits); descrambler->generate(scrambling_seq); // Revert scrambling. diff --git a/tests/unittests/phy/upper/channel_coding/short/short_block_detector_test.cpp b/tests/unittests/phy/upper/channel_coding/short/short_block_detector_test.cpp index 4535e8520f..24e51cb2d8 100644 --- a/tests/unittests/phy/upper/channel_coding/short/short_block_detector_test.cpp +++ b/tests/unittests/phy/upper/channel_coding/short/short_block_detector_test.cpp @@ -92,6 +92,22 @@ TEST_P(ShortBlockDetectorFixture, ShortBlockDetectorTest) } } +TEST_P(ShortBlockDetectorFixture, ShortBlockDetectorTestZeroLLR) +{ + const test_case_t& test_data = GetParam(); + unsigned nof_messages = test_data.nof_messages; + unsigned message_length = test_data.message_length; + unsigned codeblock_length = test_data.codeblock_length; + modulation_scheme mod = test_data.mod; + + for (unsigned msg_idx = 0; msg_idx != nof_messages; ++msg_idx) { + std::vector output(message_length); + std::vector input(nof_messages * codeblock_length, log_likelihood_ratio(0)); + + ASSERT_FALSE(test_detector->detect(output, input, mod)) << "Invalid detection."; + } +} + INSTANTIATE_TEST_SUITE_P(ShortBlockDetectorTest, ShortBlockDetectorFixture, ::testing::ValuesIn(short_block_detector_test_data)); 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 373c07ee9f..8115e810d5 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 @@ -203,6 +203,9 @@ TEST_P(PuschProcessorFixture, PuschProcessorVectortest) ASSERT_FALSE(uci_entries.empty()); const auto& uci_entry = uci_entries.front(); + // Make sure SINR reported in UCI is normal. + ASSERT_TRUE(std::isnormal(uci_entry.csi.get_sinr_dB())); + // Verify HARQ-ACK result. if (config.uci.nof_harq_ack > 0) { std::vector expected_harq_ack_unpacked = test_case.harq_ack.read(); @@ -228,6 +231,76 @@ TEST_P(PuschProcessorFixture, PuschProcessorVectortest) } } +TEST_P(PuschProcessorFixture, PuschProcessorVectortestZero) +{ + // Reuses the configurations from the vector test. + const test_case_t& test_case = GetParam(); + const test_case_context& context = test_case.context; + const pusch_processor::pdu_t& config = context.config; + + // Read resource grid data and overwrite the RE with zeros. + std::vector grid_data = test_case.grid.read(); + std::for_each(grid_data.begin(), grid_data.end(), [](auto& e) { e.value = 0; }); + + // Prepare resource grid. + resource_grid_reader_spy grid; + grid.write(grid_data); + + // Prepare receive data. + std::vector data(test_case.sch_data.read().size()); + + // Prepare softbuffer. + rx_softbuffer_spy softbuffer_spy( + ldpc::MAX_CODEBLOCK_SIZE, + ldpc::compute_nof_codeblocks(units::bytes(data.size()).to_bits(), config.codeword.value().ldpc_base_graph)); + unique_rx_softbuffer softbuffer(softbuffer_spy); + + // Make sure the configuration is valid. + ASSERT_TRUE(pdu_validator->is_valid(config)); + + // Process PUSCH PDU. + pusch_processor_result_notifier_spy results_notifier; + pusch_proc->process(data, std::move(softbuffer), results_notifier, grid, config); + + // Verify UL-SCH decode results are invalid. + const auto& sch_entries = results_notifier.get_sch_entries(); + ASSERT_FALSE(sch_entries.empty()); + const auto& sch_entry = sch_entries.front(); + ASSERT_FALSE(sch_entry.data.tb_crc_ok); + + // Make sure SINR is infinity. + ASSERT_TRUE(std::isinf(results_notifier.get_sch_entries().front().csi.get_sinr_dB())); + + // Skip the rest of the assertions if UCI is not present. + if ((config.uci.nof_harq_ack == 0) && (config.uci.nof_csi_part1 == 0) && config.uci.csi_part2_size.entries.empty()) { + return; + } + + // Extract UCI result. + const auto& uci_entries = results_notifier.get_uci_entries(); + ASSERT_FALSE(uci_entries.empty()); + const auto& uci_entry = uci_entries.front(); + + // Make sure SINR reported in UCI is normal. + ASSERT_TRUE(std::isinf(uci_entry.csi.get_sinr_dB())); + + // Verify HARQ-ACK result is invalid. + if (config.uci.nof_harq_ack > 0) { + ASSERT_EQ(uci_entry.harq_ack.status, uci_status::invalid); + } else { + ASSERT_TRUE(uci_entry.harq_ack.payload.empty()); + ASSERT_EQ(uci_entry.harq_ack.status, uci_status::unknown); + } + + // Verify CSI Part 1 result is invalid. + if (config.uci.nof_csi_part1 > 0) { + ASSERT_EQ(uci_entry.csi_part1.status, uci_status::invalid); + } else { + ASSERT_TRUE(uci_entry.csi_part1.payload.empty()); + ASSERT_EQ(uci_entry.csi_part1.status, uci_status::unknown); + } +} + // Creates test suite that combines all possible parameters. INSTANTIATE_TEST_SUITE_P(PuschProcessorVectortest, PuschProcessorFixture, From b43a1b683e4a56c7e17fd04f038dfb4a11f8374e Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 2 Jan 2024 19:18:15 +0100 Subject: [PATCH 044/134] phy: make post-equalization the default SINR calculation method --- apps/gnb/gnb_appconfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/gnb/gnb_appconfig.h b/apps/gnb/gnb_appconfig.h index 5c02c6b7dd..23328f4341 100644 --- a/apps/gnb/gnb_appconfig.h +++ b/apps/gnb/gnb_appconfig.h @@ -827,7 +827,7 @@ struct expert_upper_phy_appconfig { /// -\c channel_estimator: SINR is calculated by the channel estimator using the DM-RS. /// -\c post_equalization: SINR is calculated using the post-equalization noise variances of the equalized RE. /// -\c evm: SINR is obtained from the EVM of the PUSCH symbols. - std::string pusch_sinr_calc_method = "evm"; + std::string pusch_sinr_calc_method = "post_equalization"; /// \brief Request headroom size in slots. /// /// The request headroom size is the number of delayed slots that the upper physical layer will accept, ie, if the From d9589bfffd61de1752aa995bce813f06eadcb19f Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 4 Jan 2024 12:06:17 +0100 Subject: [PATCH 045/134] phy: fix short block detector unitalised payload --- .../upper/channel_coding/short/short_block_detector_impl.cpp | 1 + .../upper/channel_coding/short/short_block_detector_test.cpp | 4 ++++ .../channel_processors/pusch/pusch_processor_vectortest.cpp | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/lib/phy/upper/channel_coding/short/short_block_detector_impl.cpp b/lib/phy/upper/channel_coding/short/short_block_detector_impl.cpp index 8c207ffb76..57cecce738 100644 --- a/lib/phy/upper/channel_coding/short/short_block_detector_impl.cpp +++ b/lib/phy/upper/channel_coding/short/short_block_detector_impl.cpp @@ -160,6 +160,7 @@ bool short_block_detector_impl::detect(span output, // If all input bits are zero, the result is invalid. if (std::all_of(input.begin(), input.end(), [](log_likelihood_ratio bit) { return bit == 0; })) { + std::fill(output.begin(), output.end(), 1); return false; } diff --git a/tests/unittests/phy/upper/channel_coding/short/short_block_detector_test.cpp b/tests/unittests/phy/upper/channel_coding/short/short_block_detector_test.cpp index 24e51cb2d8..d2eff3fb57 100644 --- a/tests/unittests/phy/upper/channel_coding/short/short_block_detector_test.cpp +++ b/tests/unittests/phy/upper/channel_coding/short/short_block_detector_test.cpp @@ -17,6 +17,7 @@ #include "short_block_detector_test_data.h" #include "srsran/phy/upper/channel_coding/channel_coding_factories.h" #include "fmt/ostream.h" +#include #include /// \cond @@ -104,7 +105,10 @@ TEST_P(ShortBlockDetectorFixture, ShortBlockDetectorTestZeroLLR) std::vector output(message_length); std::vector input(nof_messages * codeblock_length, log_likelihood_ratio(0)); + // Detection must be invalid and all values to one. ASSERT_FALSE(test_detector->detect(output, input, mod)) << "Invalid detection."; + ASSERT_TRUE(std::all_of(output.begin(), output.end(), [](uint8_t value) { return value == 1; })) + << "All output bits must be one."; } } 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 8115e810d5..e2c4fb7c00 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 @@ -286,7 +286,9 @@ TEST_P(PuschProcessorFixture, PuschProcessorVectortestZero) // Verify HARQ-ACK result is invalid. if (config.uci.nof_harq_ack > 0) { + uci_payload_type expected_payload = ~uci_payload_type(config.uci.nof_harq_ack); ASSERT_EQ(uci_entry.harq_ack.status, uci_status::invalid); + ASSERT_EQ(uci_entry.harq_ack.payload, expected_payload); } else { ASSERT_TRUE(uci_entry.harq_ack.payload.empty()); ASSERT_EQ(uci_entry.harq_ack.status, uci_status::unknown); @@ -294,7 +296,9 @@ TEST_P(PuschProcessorFixture, PuschProcessorVectortestZero) // Verify CSI Part 1 result is invalid. if (config.uci.nof_csi_part1 > 0) { + uci_payload_type expected_payload = ~uci_payload_type(config.uci.nof_csi_part1); ASSERT_EQ(uci_entry.csi_part1.status, uci_status::invalid); + ASSERT_EQ(uci_entry.csi_part1.payload, expected_payload); } else { ASSERT_TRUE(uci_entry.csi_part1.payload.empty()); ASSERT_EQ(uci_entry.csi_part1.status, uci_status::unknown); From 758c7232d55a62b8d08e7f19d3099097240b81f1 Mon Sep 17 00:00:00 2001 From: dvdgrgrtt Date: Wed, 3 Jan 2024 14:23:24 +0100 Subject: [PATCH 046/134] prach_detector: avoid runtime malloc Move a const static table from function level to file level, so that it is reused by multiple functions/methods and it is created at initialization time instead of runtime. --- .../prach_detector_generic_impl.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/phy/upper/channel_processors/prach_detector_generic_impl.cpp b/lib/phy/upper/channel_processors/prach_detector_generic_impl.cpp index f07e6789e9..6c14724f23 100644 --- a/lib/phy/upper/channel_processors/prach_detector_generic_impl.cpp +++ b/lib/phy/upper/channel_processors/prach_detector_generic_impl.cpp @@ -27,6 +27,8 @@ using namespace srsran; +static const detail::threshold_and_margin_finder threshold_and_margin_table(detail::all_threshold_and_margins); + bool prach_detector_validator_impl::is_valid(const prach_detector::configuration& config) const { detail::threshold_params th_params; @@ -36,8 +38,7 @@ bool prach_detector_validator_impl::is_valid(const prach_detector::configuration th_params.zero_correlation_zone = config.zero_correlation_zone; th_params.combine_symbols = true; - static const detail::threshold_and_margin_finder threshold_and_margin_table(detail::all_threshold_and_margins); - auto flag = threshold_and_margin_table.check_flag(th_params); + auto flag = threshold_and_margin_table.check_flag(th_params); return (flag != detail::threshold_and_margin_finder::threshold_flag::red); } @@ -138,10 +139,9 @@ prach_detection_result prach_detector_generic_impl::detect(const prach_buffer& i th_params.zero_correlation_zone = config.zero_correlation_zone; th_params.combine_symbols = combine_symbols; - static const detail::threshold_and_margin_finder threshold_and_margin_table(detail::all_threshold_and_margins); - auto th_and_margin = threshold_and_margin_table.get(th_params); - float threshold = std::get<0>(th_and_margin); - unsigned win_margin = std::get<1>(th_and_margin); + auto th_and_margin = threshold_and_margin_table.get(th_params); + float threshold = std::get<0>(th_and_margin); + unsigned win_margin = std::get<1>(th_and_margin); srsran_assert((win_margin > 0) && (threshold > 0.0), "Window margin and threshold are not selected for the number of ports (i.e., {}) and the preamble " "format (i.e., {}).", From 9a84d31f272e51f1b69224efb547623cbb697528 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 26 Dec 2023 14:00:02 +0100 Subject: [PATCH 047/134] cmake: add missing newline --- lib/hal/dpdk/bbdev/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/hal/dpdk/bbdev/CMakeLists.txt b/lib/hal/dpdk/bbdev/CMakeLists.txt index 1639deeeab..7e1a2e5dd0 100644 --- a/lib/hal/dpdk/bbdev/CMakeLists.txt +++ b/lib/hal/dpdk/bbdev/CMakeLists.txt @@ -5,6 +5,7 @@ # forth in the LICENSE file which can be found at the top level of # the distribution. # + set(SOURCES bbdev_acc.cpp bbdev_acc_factory.cpp From 1afc49b0f6f0c9adc8474c327d0d0b0ecee03ccd Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 3 Jan 2024 14:15:01 +0000 Subject: [PATCH 048/134] rlc: disable metrics unless the user requests it --- apps/gnb/gnb_appconfig.h | 2 +- lib/rlc/rlc_base_entity.h | 2 + lib/rlc/rlc_rx_entity.h | 1 + lib/rlc/rlc_rx_metrics_container.h | 32 +++++++++++++ lib/rlc/rlc_tx_entity.h | 1 + lib/rlc/rlc_tx_metrics_container.h | 45 ++++++++++++++++++- .../du_high/test_utils/du_high_test_bench.cpp | 2 +- tests/unittests/rlc/rlc_um_test.cpp | 2 +- 8 files changed, 83 insertions(+), 4 deletions(-) diff --git a/apps/gnb/gnb_appconfig.h b/apps/gnb/gnb_appconfig.h index 23328f4341..9fdc1185dd 100644 --- a/apps/gnb/gnb_appconfig.h +++ b/apps/gnb/gnb_appconfig.h @@ -784,7 +784,7 @@ struct pcap_appconfig { /// Metrics report configuration. struct metrics_appconfig { struct { - unsigned report_period = 1000; // RLC report period in ms + unsigned report_period = 0; // RLC report period in ms bool json_enabled = false; } rlc; unsigned cu_cp_statistics_report_period = 1; // Statistics report period in seconds diff --git a/lib/rlc/rlc_base_entity.h b/lib/rlc/rlc_base_entity.h index b55a0a468e..a3177eed62 100644 --- a/lib/rlc/rlc_base_entity.h +++ b/lib/rlc/rlc_base_entity.h @@ -41,6 +41,8 @@ class rlc_base_entity : public rlc_entity { rlc_metrics_notif = rlc_metrics_notifier_; if (metrics_period.count() != 0) { + tx->enable_metrics(); + rx->enable_metrics(); metrics_timer.set(metrics_period, [this](timer_id_t /*tid*/) { push_metrics(); }); metrics_timer.run(); } diff --git a/lib/rlc/rlc_rx_entity.h b/lib/rlc/rlc_rx_entity.h index 62b099f45f..c86c07e7b6 100644 --- a/lib/rlc/rlc_rx_entity.h +++ b/lib/rlc/rlc_rx_entity.h @@ -37,6 +37,7 @@ class rlc_rx_entity : public rlc_rx_lower_layer_interface, public rlc_rx_metrics rlc_pcap& pcap; public: + void enable_metrics() { metrics.enabled = true; } rlc_rx_metrics get_metrics() { return metrics.get_metrics(); } void reset_metrics() { return metrics.reset_metrics(); } }; diff --git a/lib/rlc/rlc_rx_metrics_container.h b/lib/rlc/rlc_rx_metrics_container.h index 33107d29df..fefc3d7852 100644 --- a/lib/rlc/rlc_rx_metrics_container.h +++ b/lib/rlc/rlc_rx_metrics_container.h @@ -22,14 +22,22 @@ class rlc_rx_metrics_container std::mutex metrics_mutex; public: + bool enabled = false; + void metrics_set_mode(rlc_mode mode) { + if (not enabled) { + return; + } std::lock_guard lock(metrics_mutex); metrics.mode = mode; } void metrics_add_sdus(uint32_t num_sdus_, size_t num_sdu_bytes_) { + if (not enabled) { + return; + } std::lock_guard lock(metrics_mutex); metrics.num_sdus += num_sdus_; metrics.num_sdu_bytes += num_sdu_bytes_; @@ -37,6 +45,9 @@ class rlc_rx_metrics_container void metrics_add_pdus(uint32_t num_pdus_, size_t num_pdu_bytes_) { + if (not enabled) { + return; + } std::lock_guard lock(metrics_mutex); metrics.num_pdus += num_pdus_; metrics.num_pdu_bytes += num_pdu_bytes_; @@ -44,12 +55,18 @@ class rlc_rx_metrics_container void metrics_add_lost_pdus(uint32_t num_pdus_) { + if (not enabled) { + return; + } std::lock_guard lock(metrics_mutex); metrics.num_lost_pdus += num_pdus_; } void metrics_add_malformed_pdus(uint32_t num_pdus_) { + if (not enabled) { + return; + } std::lock_guard lock(metrics_mutex); metrics.num_malformed_pdus += num_pdus_; } @@ -57,6 +74,9 @@ class rlc_rx_metrics_container /// RLC AM specific metrics void metrics_add_ctrl_pdus(uint32_t num_ctrl_, uint32_t num_ctrl_pdu_bytes_) { + if (not enabled) { + return; + } std::lock_guard lock(metrics_mutex); srsran_assert(metrics.mode == rlc_mode::am, "Wrong mode for AM metrics."); metrics.mode_specific.am.num_ctrl_pdus += num_ctrl_; @@ -65,12 +85,20 @@ class rlc_rx_metrics_container rlc_rx_metrics get_metrics() { + srsran_assert(enabled, "Trying to get metrics, but metrics are disabled."); + if (not enabled) { + return {}; + } std::lock_guard lock(metrics_mutex); return metrics; } rlc_rx_metrics get_and_reset_metrics() { + srsran_assert(enabled, "Trying to get and reset metrics, but metrics are disabled."); + if (not enabled) { + return {}; + } std::lock_guard lock(metrics_mutex); rlc_rx_metrics ret = metrics; metrics = {}; @@ -80,6 +108,10 @@ class rlc_rx_metrics_container void reset_metrics() { + srsran_assert(enabled, "Trying to reset metrics, but metrics are disabled."); + if (not enabled) { + return; + } std::lock_guard lock(metrics_mutex); rlc_mode tmp_mode = metrics.mode; metrics = {}; diff --git a/lib/rlc/rlc_tx_entity.h b/lib/rlc/rlc_tx_entity.h index 1c5d1dc50d..a5a22640b9 100644 --- a/lib/rlc/rlc_tx_entity.h +++ b/lib/rlc/rlc_tx_entity.h @@ -49,6 +49,7 @@ class rlc_tx_entity : public rlc_tx_upper_layer_data_interface, rlc_pcap& pcap; public: + void enable_metrics() { metrics.enabled = true; } rlc_tx_metrics get_metrics() { return metrics.get_metrics(); } void reset_metrics() { return metrics.reset_metrics(); } }; diff --git a/lib/rlc/rlc_tx_metrics_container.h b/lib/rlc/rlc_tx_metrics_container.h index fe40632182..476668610c 100644 --- a/lib/rlc/rlc_tx_metrics_container.h +++ b/lib/rlc/rlc_tx_metrics_container.h @@ -22,14 +22,22 @@ class rlc_tx_metrics_container std::mutex metrics_mutex; public: + bool enabled = false; + void metrics_set_mode(rlc_mode mode) { + if (not enabled) { + return; + } std::lock_guard lock(metrics_mutex); metrics.mode = mode; } void metrics_add_sdus(uint32_t num_sdus_, size_t num_sdu_bytes_) { + if (not enabled) { + return; + } std::lock_guard lock(metrics_mutex); metrics.num_sdus += num_sdus_; metrics.num_sdu_bytes += num_sdu_bytes_; @@ -37,12 +45,18 @@ class rlc_tx_metrics_container void metrics_add_lost_sdus(uint32_t num_sdus_) { + if (not enabled) { + return; + } std::lock_guard lock(metrics_mutex); metrics.num_dropped_sdus += num_sdus_; } void metrics_add_pdus(uint32_t num_pdus_, size_t num_pdu_bytes_) { + if (not enabled) { + return; + } std::lock_guard lock(metrics_mutex); metrics.num_pdus += num_pdus_; metrics.num_pdu_bytes += num_pdu_bytes_; @@ -50,12 +64,18 @@ class rlc_tx_metrics_container void metrics_add_discard(uint32_t num_discarded_sdus_) { + if (not enabled) { + return; + } std::lock_guard lock(metrics_mutex); metrics.num_discarded_sdus += num_discarded_sdus_; } void metrics_add_discard_failure(uint32_t num_discard_failures_) { + if (not enabled) { + return; + } std::lock_guard lock(metrics_mutex); metrics.num_discard_failures += num_discard_failures_; } @@ -63,14 +83,19 @@ class rlc_tx_metrics_container // TM specific metrics void metrics_add_small_alloc(uint32_t num_allocs_) { + if (not enabled) { + return; + } std::lock_guard lock(metrics_mutex); srsran_assert(metrics.mode == rlc_mode::tm, "Wrong mode for TM metrics."); metrics.mode_specific.tm.num_small_allocs += num_allocs_; } - // UM specific metrics void metrics_add_segment(uint32_t num_segments_) { + if (not enabled) { + return; + } std::lock_guard lock(metrics_mutex); srsran_assert(metrics.mode == rlc_mode::um_bidir || metrics.mode == rlc_mode::um_unidir_dl, "Wrong mode for UM metrics."); @@ -80,6 +105,9 @@ class rlc_tx_metrics_container // AM specific metrics void metrics_add_retx_pdus(uint32_t num_retx_, uint32_t num_retx_pdu_bytes_) { + if (not enabled) { + return; + } std::lock_guard lock(metrics_mutex); srsran_assert(metrics.mode == rlc_mode::am, "Wrong mode for AM metrics."); metrics.mode_specific.am.num_retx_pdus += num_retx_; @@ -90,6 +118,9 @@ class rlc_tx_metrics_container void metrics_add_ctrl_pdus(uint32_t num_ctrl_, uint32_t num_ctrl_pdu_bytes_) { + if (not enabled) { + return; + } std::lock_guard lock(metrics_mutex); srsran_assert(metrics.mode == rlc_mode::am, "Wrong mode for AM metrics."); metrics.mode_specific.am.num_ctrl_pdus += num_ctrl_; @@ -101,12 +132,20 @@ class rlc_tx_metrics_container // Metrics getters and setters rlc_tx_metrics get_metrics() { + srsran_assert(enabled, "Trying to get metrics, but metrics are disabled."); + if (not enabled) { + return {}; + } std::lock_guard lock(metrics_mutex); return metrics; } rlc_tx_metrics get_and_reset_metrics() { + srsran_assert(enabled, "Trying to get metrics, but metrics are disabled."); + if (not enabled) { + return {}; + } std::lock_guard lock(metrics_mutex); rlc_tx_metrics ret = metrics; metrics = {}; @@ -116,6 +155,10 @@ class rlc_tx_metrics_container void reset_metrics() { + srsran_assert(enabled, "Trying to reset metrics, but metrics are disabled."); + if (not enabled) { + return; + } std::lock_guard lock(metrics_mutex); rlc_mode tmp_mode = metrics.mode; metrics = {}; 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 8f0c2c4447..0cdb71aefe 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 @@ -163,7 +163,7 @@ du_high_test_bench::du_high_test_bench() : cfg.gnb_du_name = "srsdu"; cfg.du_bind_addr = {"127.0.0.1"}; cfg.cells = {config_helpers::make_default_du_cell_config()}; - cfg.qos = config_helpers::make_default_du_qos_config_list(1000); + cfg.qos = config_helpers::make_default_du_qos_config_list(0); cfg.sched_cfg = config_helpers::make_default_scheduler_expert_config(); cfg.mac_p = &mac_pcap; cfg.rlc_p = &rlc_pcap; diff --git a/tests/unittests/rlc/rlc_um_test.cpp b/tests/unittests/rlc/rlc_um_test.cpp index 791a13c6ad..7549405913 100644 --- a/tests/unittests/rlc/rlc_um_test.cpp +++ b/tests/unittests/rlc/rlc_um_test.cpp @@ -88,7 +88,7 @@ class rlc_um_test : public ::testing::Test, public ::testing::WithParamInterface du_ue_index_t::MIN_DU_UE_INDEX, srb_id_t::srb0, config, - std::chrono::milliseconds(1000), + std::chrono::milliseconds(0), nullptr, tester1, tester1, From cecd6014807c5c3d3c099a909aa3f349d0347021 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 3 Jan 2024 23:15:36 +0000 Subject: [PATCH 049/134] rlc: move metrics_enable to constructor --- lib/rlc/rlc_am_entity.h | 12 ++++++++-- lib/rlc/rlc_base_entity.h | 4 +--- lib/rlc/rlc_rx_am_entity.cpp | 3 ++- lib/rlc/rlc_rx_am_entity.h | 1 + lib/rlc/rlc_rx_entity.h | 6 ++--- lib/rlc/rlc_rx_metrics_container.h | 3 ++- lib/rlc/rlc_rx_tm_entity.cpp | 4 +++- lib/rlc/rlc_rx_tm_entity.h | 1 + lib/rlc/rlc_rx_um_entity.cpp | 3 ++- lib/rlc/rlc_rx_um_entity.h | 1 + lib/rlc/rlc_tm_entity.h | 14 ++++++++--- lib/rlc/rlc_tx_am_entity.cpp | 3 ++- lib/rlc/rlc_tx_am_entity.h | 1 + lib/rlc/rlc_tx_entity.h | 3 ++- lib/rlc/rlc_tx_metrics_container.h | 3 ++- lib/rlc/rlc_tx_tm_entity.cpp | 3 ++- lib/rlc/rlc_tx_tm_entity.h | 1 + lib/rlc/rlc_tx_um_entity.cpp | 3 ++- lib/rlc/rlc_tx_um_entity.h | 1 + lib/rlc/rlc_um_entity.h | 23 +++++++++++++++---- tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp | 2 ++ .../rlc/rlc_handle_status_report.cpp | 1 + .../rlc/rlc_stress_test_args.h | 1 + tests/unittests/rlc/rlc_rx_am_test.cpp | 1 + tests/unittests/rlc/rlc_rx_tm_test.cpp | 2 +- tests/unittests/rlc/rlc_tx_am_test.cpp | 1 + tests/unittests/rlc/rlc_tx_tm_test.cpp | 2 +- tests/unittests/rlc/rlc_um_test.cpp | 2 +- 28 files changed, 78 insertions(+), 27 deletions(-) diff --git a/lib/rlc/rlc_am_entity.h b/lib/rlc/rlc_am_entity.h index 44728a329d..de9b124ea0 100644 --- a/lib/rlc/rlc_am_entity.h +++ b/lib/rlc/rlc_am_entity.h @@ -51,9 +51,17 @@ class rlc_am_entity : public rlc_base_entity timer_factory{timers, pcell_executor}, pcell_executor, ue_executor, + metrics_period.count() != 0, + pcap); + std::unique_ptr rx_am = std::make_unique(du_index_, + ue_index_, + rb_id_, + config.rx, + rx_upper_dn, + timer_factory{timers, ue_executor}, + ue_executor, + metrics_period.count() != 0, pcap); - std::unique_ptr rx_am = std::make_unique( - du_index_, ue_index_, rb_id_, config.rx, rx_upper_dn, timer_factory{timers, ue_executor}, ue_executor, pcap); // Tx/Rx interconnect tx_am->set_status_provider(rx_am.get()); diff --git a/lib/rlc/rlc_base_entity.h b/lib/rlc/rlc_base_entity.h index a3177eed62..7529453a58 100644 --- a/lib/rlc/rlc_base_entity.h +++ b/lib/rlc/rlc_base_entity.h @@ -41,8 +41,6 @@ class rlc_base_entity : public rlc_entity { rlc_metrics_notif = rlc_metrics_notifier_; if (metrics_period.count() != 0) { - tx->enable_metrics(); - rx->enable_metrics(); metrics_timer.set(metrics_period, [this](timer_id_t /*tid*/) { push_metrics(); }); metrics_timer.run(); } @@ -79,9 +77,9 @@ class rlc_base_entity : public rlc_entity rb_id_t rb_id; std::unique_ptr tx = {}; std::unique_ptr rx = {}; + timer_duration metrics_period; private: - timer_duration metrics_period; unique_timer metrics_timer; rlc_metrics_notifier* rlc_metrics_notif; diff --git a/lib/rlc/rlc_rx_am_entity.cpp b/lib/rlc/rlc_rx_am_entity.cpp index 206868c3f0..8a8fc0c894 100644 --- a/lib/rlc/rlc_rx_am_entity.cpp +++ b/lib/rlc/rlc_rx_am_entity.cpp @@ -22,8 +22,9 @@ rlc_rx_am_entity::rlc_rx_am_entity(uint32_t du_index, rlc_rx_upper_layer_data_notifier& upper_dn_, timer_factory timers, task_executor& ue_executor_, + bool metrics_enabled, rlc_pcap& pcap_) : - rlc_rx_entity(du_index, ue_index, rb_id, upper_dn_, pcap_), + rlc_rx_entity(du_index, ue_index, rb_id, upper_dn_, metrics_enabled, pcap_), cfg(config), mod(cardinality(to_number(cfg.sn_field_length))), am_window_size(window_size(to_number(cfg.sn_field_length))), diff --git a/lib/rlc/rlc_rx_am_entity.h b/lib/rlc/rlc_rx_am_entity.h index 577447e199..48aa909e25 100644 --- a/lib/rlc/rlc_rx_am_entity.h +++ b/lib/rlc/rlc_rx_am_entity.h @@ -142,6 +142,7 @@ class rlc_rx_am_entity : public rlc_rx_entity, public rlc_rx_am_status_provider rlc_rx_upper_layer_data_notifier& upper_dn_, timer_factory timers, task_executor& ue_executor, + bool metrics_enabled, rlc_pcap& pcap_); // Rx/Tx interconnect diff --git a/lib/rlc/rlc_rx_entity.h b/lib/rlc/rlc_rx_entity.h index c86c07e7b6..13d0634b60 100644 --- a/lib/rlc/rlc_rx_entity.h +++ b/lib/rlc/rlc_rx_entity.h @@ -26,18 +26,18 @@ class rlc_rx_entity : public rlc_rx_lower_layer_interface, public rlc_rx_metrics du_ue_index_t ue_index, rb_id_t rb_id, rlc_rx_upper_layer_data_notifier& upper_dn_, + bool metrics_enable, rlc_pcap& pcap_) : - logger("RLC", {du_index, ue_index, rb_id, "UL"}), upper_dn(upper_dn_), pcap(pcap_) + logger("RLC", {du_index, ue_index, rb_id, "UL"}), upper_dn(upper_dn_), metrics(metrics_enable), pcap(pcap_) { } rlc_bearer_logger logger; - rlc_rx_metrics_container metrics; rlc_rx_upper_layer_data_notifier& upper_dn; + rlc_rx_metrics_container metrics; rlc_pcap& pcap; public: - void enable_metrics() { metrics.enabled = true; } rlc_rx_metrics get_metrics() { return metrics.get_metrics(); } void reset_metrics() { return metrics.reset_metrics(); } }; diff --git a/lib/rlc/rlc_rx_metrics_container.h b/lib/rlc/rlc_rx_metrics_container.h index fefc3d7852..0b0cf1172d 100644 --- a/lib/rlc/rlc_rx_metrics_container.h +++ b/lib/rlc/rlc_rx_metrics_container.h @@ -20,9 +20,10 @@ class rlc_rx_metrics_container { rlc_rx_metrics metrics = {}; std::mutex metrics_mutex; + bool enabled = false; public: - bool enabled = false; + rlc_rx_metrics_container(bool enabled_) : enabled(enabled_) {} void metrics_set_mode(rlc_mode mode) { diff --git a/lib/rlc/rlc_rx_tm_entity.cpp b/lib/rlc/rlc_rx_tm_entity.cpp index 4de34d2d5d..82ff78f9b7 100644 --- a/lib/rlc/rlc_rx_tm_entity.cpp +++ b/lib/rlc/rlc_rx_tm_entity.cpp @@ -16,8 +16,10 @@ rlc_rx_tm_entity::rlc_rx_tm_entity(uint32_t du_index, du_ue_index_t ue_index, rb_id_t rb_id, rlc_rx_upper_layer_data_notifier& upper_dn_, + bool metrics_enabled, rlc_pcap& pcap_) : - rlc_rx_entity(du_index, ue_index, rb_id, upper_dn_, pcap_), pcap_context(ue_index, rb_id, /* is_uplink */ true) + rlc_rx_entity(du_index, ue_index, rb_id, upper_dn_, metrics_enabled, pcap_), + pcap_context(ue_index, rb_id, /* is_uplink */ true) { metrics.metrics_set_mode(rlc_mode::tm); logger.log_info("RLC TM created."); diff --git a/lib/rlc/rlc_rx_tm_entity.h b/lib/rlc/rlc_rx_tm_entity.h index 5cbc6207bd..35eda873cc 100644 --- a/lib/rlc/rlc_rx_tm_entity.h +++ b/lib/rlc/rlc_rx_tm_entity.h @@ -24,6 +24,7 @@ class rlc_rx_tm_entity : public rlc_rx_entity du_ue_index_t ue_index, rb_id_t rb_id, rlc_rx_upper_layer_data_notifier& upper_dn_, + bool metrics_enabled, rlc_pcap& pcap_); // Interfaces for higher layers diff --git a/lib/rlc/rlc_rx_um_entity.cpp b/lib/rlc/rlc_rx_um_entity.cpp index 212c3ef0ec..f9ede04788 100644 --- a/lib/rlc/rlc_rx_um_entity.cpp +++ b/lib/rlc/rlc_rx_um_entity.cpp @@ -20,8 +20,9 @@ rlc_rx_um_entity::rlc_rx_um_entity(uint32_t du_index, rlc_rx_upper_layer_data_notifier& upper_dn_, timer_factory timers, task_executor& ue_executor, + bool metrics_enable, rlc_pcap& pcap_) : - rlc_rx_entity(du_index, ue_index, rb_id, upper_dn_, pcap_), + rlc_rx_entity(du_index, ue_index, rb_id, upper_dn_, metrics_enable, pcap_), cfg(config), mod(cardinality(to_number(cfg.sn_field_length))), um_window_size(window_size(to_number(cfg.sn_field_length))), diff --git a/lib/rlc/rlc_rx_um_entity.h b/lib/rlc/rlc_rx_um_entity.h index a3fe847ba0..62f26497c0 100644 --- a/lib/rlc/rlc_rx_um_entity.h +++ b/lib/rlc/rlc_rx_um_entity.h @@ -95,6 +95,7 @@ class rlc_rx_um_entity : public rlc_rx_entity rlc_rx_upper_layer_data_notifier& upper_dn_, timer_factory timers, task_executor& ue_executor, + bool metrics_enabled_, rlc_pcap& pcap_); void on_expired_reassembly_timer(); diff --git a/lib/rlc/rlc_tm_entity.h b/lib/rlc/rlc_tm_entity.h index 8ec479ca22..9d6255ca7e 100644 --- a/lib/rlc/rlc_tm_entity.h +++ b/lib/rlc/rlc_tm_entity.h @@ -39,9 +39,17 @@ class rlc_tm_entity : public rlc_base_entity rlc_metrics_notifier_, timer_factory{timers, ue_executor}) { - tx = std::unique_ptr(new rlc_tx_tm_entity( - du_index_, ue_index_, rb_id_, tx_upper_dn, tx_upper_cn, tx_lower_dn, pcell_executor, pcap)); - rx = std::unique_ptr(new rlc_rx_tm_entity(du_index_, ue_index_, rb_id_, rx_upper_dn, pcap)); + tx = std::unique_ptr(new rlc_tx_tm_entity(du_index_, + ue_index_, + rb_id_, + tx_upper_dn, + tx_upper_cn, + tx_lower_dn, + pcell_executor, + metrics_period.count() != 0, + pcap)); + rx = std::unique_ptr( + new rlc_rx_tm_entity(du_index_, ue_index_, rb_id_, rx_upper_dn, metrics_period.count() != 0, pcap)); } }; diff --git a/lib/rlc/rlc_tx_am_entity.cpp b/lib/rlc/rlc_tx_am_entity.cpp index 8b997512de..be0fa29c26 100644 --- a/lib/rlc/rlc_tx_am_entity.cpp +++ b/lib/rlc/rlc_tx_am_entity.cpp @@ -29,8 +29,9 @@ rlc_tx_am_entity::rlc_tx_am_entity(uint32_t du_index timer_factory timers, task_executor& pcell_executor_, task_executor& ue_executor_, + bool metrics_enabled_, rlc_pcap& pcap_) : - rlc_tx_entity(du_index, ue_index, rb_id, upper_dn_, upper_cn_, lower_dn_, pcap_), + rlc_tx_entity(du_index, ue_index, rb_id, upper_dn_, upper_cn_, lower_dn_, metrics_enabled_, pcap_), cfg(config), sdu_queue(cfg.queue_size), retx_queue(window_size(to_number(cfg.sn_field_length))), diff --git a/lib/rlc/rlc_tx_am_entity.h b/lib/rlc/rlc_tx_am_entity.h index 73ed2368b5..a19cfa0a35 100644 --- a/lib/rlc/rlc_tx_am_entity.h +++ b/lib/rlc/rlc_tx_am_entity.h @@ -134,6 +134,7 @@ class rlc_tx_am_entity : public rlc_tx_entity, public rlc_tx_am_status_handler, timer_factory timers, task_executor& pcell_executor_, task_executor& ue_executor_, + bool metrics_enabled_, rlc_pcap& pcap_); // TX/RX interconnect diff --git a/lib/rlc/rlc_tx_entity.h b/lib/rlc/rlc_tx_entity.h index a5a22640b9..1a1b8792db 100644 --- a/lib/rlc/rlc_tx_entity.h +++ b/lib/rlc/rlc_tx_entity.h @@ -32,8 +32,10 @@ class rlc_tx_entity : public rlc_tx_upper_layer_data_interface, rlc_tx_upper_layer_data_notifier& upper_dn_, rlc_tx_upper_layer_control_notifier& upper_cn_, rlc_tx_lower_layer_notifier& lower_dn_, + bool metrics_enabled, rlc_pcap& pcap_) : logger("RLC", {du_index, ue_index, rb_id, "DL"}), + metrics(metrics_enabled), upper_dn(upper_dn_), upper_cn(upper_cn_), lower_dn(lower_dn_), @@ -49,7 +51,6 @@ class rlc_tx_entity : public rlc_tx_upper_layer_data_interface, rlc_pcap& pcap; public: - void enable_metrics() { metrics.enabled = true; } rlc_tx_metrics get_metrics() { return metrics.get_metrics(); } void reset_metrics() { return metrics.reset_metrics(); } }; diff --git a/lib/rlc/rlc_tx_metrics_container.h b/lib/rlc/rlc_tx_metrics_container.h index 476668610c..0296034f1c 100644 --- a/lib/rlc/rlc_tx_metrics_container.h +++ b/lib/rlc/rlc_tx_metrics_container.h @@ -20,9 +20,10 @@ class rlc_tx_metrics_container { rlc_tx_metrics metrics = {}; std::mutex metrics_mutex; + bool enabled = false; public: - bool enabled = false; + rlc_tx_metrics_container(bool enabled_) : enabled(enabled_) {} void metrics_set_mode(rlc_mode mode) { diff --git a/lib/rlc/rlc_tx_tm_entity.cpp b/lib/rlc/rlc_tx_tm_entity.cpp index 2e6e05e8d9..db4553a1ec 100644 --- a/lib/rlc/rlc_tx_tm_entity.cpp +++ b/lib/rlc/rlc_tx_tm_entity.cpp @@ -20,8 +20,9 @@ rlc_tx_tm_entity::rlc_tx_tm_entity(uint32_t du_index rlc_tx_upper_layer_control_notifier& upper_cn_, rlc_tx_lower_layer_notifier& lower_dn_, task_executor& pcell_executor_, + bool metrics_enabled_, rlc_pcap& pcap_) : - rlc_tx_entity(du_index, ue_index, rb_id, upper_dn_, upper_cn_, lower_dn_, pcap_), + rlc_tx_entity(du_index, ue_index, rb_id, upper_dn_, upper_cn_, lower_dn_, metrics_enabled_, pcap_), pcell_executor(pcell_executor_), pcap_context(ue_index, rb_id, /* is_uplink */ false) { diff --git a/lib/rlc/rlc_tx_tm_entity.h b/lib/rlc/rlc_tx_tm_entity.h index ff581a9e98..bdbf3782d3 100644 --- a/lib/rlc/rlc_tx_tm_entity.h +++ b/lib/rlc/rlc_tx_tm_entity.h @@ -39,6 +39,7 @@ class rlc_tx_tm_entity : public rlc_tx_entity rlc_tx_upper_layer_control_notifier& upper_cn_, rlc_tx_lower_layer_notifier& lower_dn_, task_executor& pcell_executor_, + bool metrics_enabled_, rlc_pcap& pcap_); // Interfaces for higher layers diff --git a/lib/rlc/rlc_tx_um_entity.cpp b/lib/rlc/rlc_tx_um_entity.cpp index b090b07fa5..7d57705b88 100644 --- a/lib/rlc/rlc_tx_um_entity.cpp +++ b/lib/rlc/rlc_tx_um_entity.cpp @@ -22,8 +22,9 @@ rlc_tx_um_entity::rlc_tx_um_entity(uint32_t du_index rlc_tx_upper_layer_control_notifier& upper_cn_, rlc_tx_lower_layer_notifier& lower_dn_, task_executor& pcell_executor_, + bool metrics_enabled, rlc_pcap& pcap_) : - rlc_tx_entity(du_index, ue_index, rb_id, upper_dn_, upper_cn_, lower_dn_, pcap_), + rlc_tx_entity(du_index, ue_index, rb_id, upper_dn_, upper_cn_, lower_dn_, metrics_enabled, pcap_), cfg(config), sdu_queue(cfg.queue_size), mod(cardinality(to_number(cfg.sn_field_length))), diff --git a/lib/rlc/rlc_tx_um_entity.h b/lib/rlc/rlc_tx_um_entity.h index 6f42a8ecae..0b0d905083 100644 --- a/lib/rlc/rlc_tx_um_entity.h +++ b/lib/rlc/rlc_tx_um_entity.h @@ -78,6 +78,7 @@ class rlc_tx_um_entity : public rlc_tx_entity rlc_tx_upper_layer_control_notifier& upper_cn_, rlc_tx_lower_layer_notifier& lower_dn_, task_executor& pcell_executor_, + bool metrics_enabled, rlc_pcap& pcap_); // Interfaces for higher layers diff --git a/lib/rlc/rlc_um_entity.h b/lib/rlc/rlc_um_entity.h index cbead3ce52..8f52fbf864 100644 --- a/lib/rlc/rlc_um_entity.h +++ b/lib/rlc/rlc_um_entity.h @@ -40,10 +40,25 @@ class rlc_um_entity : public rlc_base_entity rlc_metrics_notifier_, timer_factory{timers, ue_executor}) { - tx = std::make_unique( - du_index_, ue_index_, rb_id_, config.tx, tx_upper_dn, tx_upper_cn, tx_lower_dn, pcell_executor, pcap); - rx = std::make_unique( - du_index_, ue_index_, rb_id_, config.rx, rx_upper_dn, timer_factory{timers, ue_executor}, ue_executor, pcap); + tx = std::make_unique(du_index_, + ue_index_, + rb_id_, + config.tx, + tx_upper_dn, + tx_upper_cn, + tx_lower_dn, + pcell_executor, + metrics_period.count() != 0, + pcap); + rx = std::make_unique(du_index_, + ue_index_, + rb_id_, + config.rx, + rx_upper_dn, + timer_factory{timers, ue_executor}, + ue_executor, + metrics_period.count() != 0, + pcap); } }; diff --git a/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp b/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp index 82c1a1d524..fa275204c9 100644 --- a/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp +++ b/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp @@ -139,6 +139,7 @@ std::vector generate_pdus(bench_params params, rx_order order) timer_factory{timers, pcell_worker}, pcell_worker, ue_worker, + false, pcap); // Bind AM Rx/Tx interconnect @@ -225,6 +226,7 @@ void benchmark_rx_pdu(const bench_params& params, rx_order order) *tester, timer_factory{timers, ue_worker}, ue_worker, + false, pcap); // Bind AM Rx/Tx interconnect diff --git a/tests/benchmarks/rlc/rlc_handle_status_report.cpp b/tests/benchmarks/rlc/rlc_handle_status_report.cpp index e7280289bd..b12efd8698 100644 --- a/tests/benchmarks/rlc/rlc_handle_status_report.cpp +++ b/tests/benchmarks/rlc/rlc_handle_status_report.cpp @@ -118,6 +118,7 @@ void benchmark_status_pdu_handling(rlc_am_status_pdu status, const bench_params& timer_factory{timers, pcell_worker}, pcell_worker, ue_worker, + false, pcap); // Bind AM Rx/Tx interconnect diff --git a/tests/integrationtests/rlc/rlc_stress_test_args.h b/tests/integrationtests/rlc/rlc_stress_test_args.h index 79ebd57a6c..aada025a2e 100644 --- a/tests/integrationtests/rlc/rlc_stress_test_args.h +++ b/tests/integrationtests/rlc/rlc_stress_test_args.h @@ -326,6 +326,7 @@ inline rlc_config get_rlc_config_from_args(const stress_test_args& args) fprintf(stderr, "Unsupported RLC mode %s, exiting.\n", args.mode.c_str()); exit(-1); } + cnfg.metrics_period = std::chrono::milliseconds(1000); return cnfg; } diff --git a/tests/unittests/rlc/rlc_rx_am_test.cpp b/tests/unittests/rlc/rlc_rx_am_test.cpp index 57df90b7df..b85a628135 100644 --- a/tests/unittests/rlc/rlc_rx_am_test.cpp +++ b/tests/unittests/rlc/rlc_rx_am_test.cpp @@ -96,6 +96,7 @@ class rlc_rx_am_test : public ::testing::Test, *tester, timer_factory{timers, ue_worker}, ue_worker, + true, pcap); // Bind AM Tx/Rx interconnect diff --git a/tests/unittests/rlc/rlc_rx_tm_test.cpp b/tests/unittests/rlc/rlc_rx_tm_test.cpp index 4d110d85c1..c8e1b822da 100644 --- a/tests/unittests/rlc/rlc_rx_tm_test.cpp +++ b/tests/unittests/rlc/rlc_rx_tm_test.cpp @@ -50,7 +50,7 @@ class rlc_rx_am_test : public ::testing::Test, public rlc_trx_test tester = std::make_unique(); // Create RLC AM TX entity - rlc = std::make_unique(0, du_ue_index_t::MIN_DU_UE_INDEX, srb_id_t::srb0, *tester, pcap); + rlc = std::make_unique(0, du_ue_index_t::MIN_DU_UE_INDEX, srb_id_t::srb0, *tester, true, pcap); } void TearDown() override diff --git a/tests/unittests/rlc/rlc_tx_am_test.cpp b/tests/unittests/rlc/rlc_tx_am_test.cpp index 13a3f012db..90c0dad505 100644 --- a/tests/unittests/rlc/rlc_tx_am_test.cpp +++ b/tests/unittests/rlc/rlc_tx_am_test.cpp @@ -104,6 +104,7 @@ class rlc_tx_am_test : public ::testing::Test, public ::testing::WithParamInterf timer_factory{timers, pcell_worker}, pcell_worker, ue_worker, + true, pcap); // Bind AM Rx/Tx interconnect diff --git a/tests/unittests/rlc/rlc_tx_tm_test.cpp b/tests/unittests/rlc/rlc_tx_tm_test.cpp index a8aaf7f7bf..8ec7eec40a 100644 --- a/tests/unittests/rlc/rlc_tx_tm_test.cpp +++ b/tests/unittests/rlc/rlc_tx_tm_test.cpp @@ -64,7 +64,7 @@ class rlc_tx_tm_test : public ::testing::Test, public rlc_trx_test // Create RLC TM TX entity rlc = std::make_unique( - 0, du_ue_index_t::MIN_DU_UE_INDEX, srb_id_t::srb0, *tester, *tester, *tester, pcell_worker, pcap); + 0, du_ue_index_t::MIN_DU_UE_INDEX, srb_id_t::srb0, *tester, *tester, *tester, pcell_worker, true, pcap); } void TearDown() override diff --git a/tests/unittests/rlc/rlc_um_test.cpp b/tests/unittests/rlc/rlc_um_test.cpp index 7549405913..791a13c6ad 100644 --- a/tests/unittests/rlc/rlc_um_test.cpp +++ b/tests/unittests/rlc/rlc_um_test.cpp @@ -88,7 +88,7 @@ class rlc_um_test : public ::testing::Test, public ::testing::WithParamInterface du_ue_index_t::MIN_DU_UE_INDEX, srb_id_t::srb0, config, - std::chrono::milliseconds(0), + std::chrono::milliseconds(1000), nullptr, tester1, tester1, From 5fa088dcd8faad1b7369652bb1652f7f1eca5ee7 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Wed, 3 Jan 2024 13:39:07 +0100 Subject: [PATCH 050/134] sched: check UCI cache size list before emplace op Signed-off-by: Carlo Galiotto --- lib/scheduler/uci_scheduling/uci_allocator_impl.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp b/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp index 65fe401b04..3c1dd638db 100644 --- a/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp +++ b/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp @@ -239,6 +239,15 @@ optional uci_allocator_impl::alloc_uci_harq_ue(cell_resource_all continue; } + if (uci_alloc_grid[slot_alloc.slot.to_uint()].ucis.full()) { + logger.info( + "rnti={}: UCI allocation for slot={} skipped due to UCI cache full. Attempting this allocation for the next " + "k1 candidate, if any k1 available", + crnti, + slot_alloc.slot); + continue; + } + if (csi_helper::is_csi_reporting_slot(ue_cell_cfg.cfg_dedicated(), uci_slot)) { // NOTE: For TX with more than 2 antenna, we avoid multiplexing HARQ-ACK with CSI in the slots for CSI because the // CSI report is 11 bit, and the current PUCCH F2 capacity is exactly 11 bits. From 802b5fb5fbcc2473834e15323f1ffbc453d332e9 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 4 Jan 2024 18:47:47 +0100 Subject: [PATCH 051/134] cu-cp: cu-cp interface methods should not be in the cu-cp base class --- apps/gnb/gnb.cpp | 7 +++--- include/srsran/cu_cp/cu_cp.h | 24 ++++++++++++------- lib/cu_cp/cu_cp_impl.h | 6 ++++- .../du_high_cu/du_high_cu_test_simulator.cpp | 5 ++-- 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/apps/gnb/gnb.cpp b/apps/gnb/gnb.cpp index f4770edb57..3d768674c2 100644 --- a/apps/gnb/gnb.cpp +++ b/apps/gnb/gnb.cpp @@ -436,7 +436,8 @@ int main(int argc, char** argv) std::unique_ptr cu_cp_obj = create_cu_cp(cu_cp_cfg); // Connect NGAP adpter to CU-CP to pass NGAP messages. - ngap_adapter->connect_ngap(&cu_cp_obj->get_ngap_message_handler(), &cu_cp_obj->get_ngap_event_handler()); + ngap_adapter->connect_ngap(&cu_cp_obj->get_cu_cp_ngap_connection_interface().get_ngap_message_handler(), + &cu_cp_obj->get_cu_cp_ngap_connection_interface().get_ngap_event_handler()); // Connect E1AP to CU-CP. e1ap_gw.attach_cu_cp(cu_cp_obj->get_connected_cu_ups()); @@ -451,9 +452,9 @@ int main(int argc, char** argv) if (gnb_cfg.amf_cfg.no_core) { // Signal AMF connection so test UEs do not get rejected - cu_cp_obj->handle_amf_connection(); + cu_cp_obj->get_cu_cp_ngap_handler().handle_amf_connection(); } else { - if (not cu_cp_obj->amf_is_connected()) { + if (not cu_cp_obj->get_cu_cp_ngap_connection_interface().amf_is_connected()) { report_error("CU-CP failed to connect to AMF"); } } diff --git a/include/srsran/cu_cp/cu_cp.h b/include/srsran/cu_cp/cu_cp.h index 21c631fa96..f449e9d738 100644 --- a/include/srsran/cu_cp/cu_cp.h +++ b/include/srsran/cu_cp/cu_cp.h @@ -65,22 +65,28 @@ class cu_cp_cu_up_connection_interface virtual e1ap_message_handler& get_e1ap_message_handler(const cu_up_index_t cu_up_index) = 0; }; -class cu_cp_interface : public cu_cp_ngap_connection_interface, - public cu_cp_ngap_handler, - public cu_cp_cu_up_connection_interface - +class cu_cp_interface { public: virtual ~cu_cp_interface() = default; - virtual du_repository& get_connected_dus() = 0; - virtual cu_up_repository& get_connected_cu_ups() = 0; - virtual cu_cp_ngap_handler& get_cu_cp_ngap_handler() = 0; - virtual cu_cp_ngap_connection_interface& get_cu_cp_ngap_connection_interface() = 0; + /// \brief Get repository of handlers for the DUs currently connected to the CU-CP. + virtual du_repository& get_connected_dus() = 0; + + /// \brief Get repository of handlers for the CU-UPs currently connected to the CU-CP. + virtual cu_up_repository& get_connected_cu_ups() = 0; + + /// \brief Get handler of the NG interface of the CU-CP. + virtual cu_cp_ngap_handler& get_cu_cp_ngap_handler() = 0; + virtual cu_cp_ngap_connection_interface& get_cu_cp_ngap_connection_interface() = 0; + + /// \brief Get handler of the E1 interface of the CU-CP. virtual cu_cp_cu_up_connection_interface& get_cu_cp_cu_up_connection_interface() = 0; virtual void start() = 0; - virtual void stop() = 0; + + /// \brief Stop the CU-CP operation. + virtual void stop() = 0; }; } // namespace srs_cu_cp diff --git a/lib/cu_cp/cu_cp_impl.h b/lib/cu_cp/cu_cp_impl.h index d60a0b3b8d..69806f3b59 100644 --- a/lib/cu_cp/cu_cp_impl.h +++ b/lib/cu_cp/cu_cp_impl.h @@ -33,7 +33,11 @@ namespace srsran { namespace srs_cu_cp { -class cu_cp_impl final : public cu_cp_interface, public cu_cp_impl_interface +class cu_cp_impl final : public cu_cp_interface, + public cu_cp_impl_interface, + public cu_cp_ngap_connection_interface, + public cu_cp_ngap_handler, + public cu_cp_cu_up_connection_interface { public: explicit cu_cp_impl(const cu_cp_configuration& config_); diff --git a/tests/integrationtests/du_high_cu/du_high_cu_test_simulator.cpp b/tests/integrationtests/du_high_cu/du_high_cu_test_simulator.cpp index 6f296c0f74..65de1e7608 100644 --- a/tests/integrationtests/du_high_cu/du_high_cu_test_simulator.cpp +++ b/tests/integrationtests/du_high_cu/du_high_cu_test_simulator.cpp @@ -104,13 +104,14 @@ du_high_cu_test_simulator::du_high_cu_test_simulator(const du_high_cu_cp_test_si // Instatiate CU-CP. cu_cp_inst = create_cu_cp(cu_cfg); - cu_cp_inst->handle_amf_connection(); + cu_cp_inst->get_cu_cp_ngap_handler().handle_amf_connection(); // Start CU-CP. cu_cp_inst->start(); // Connect AMF by injecting a ng_setup_response - cu_cp_inst->get_ngap_message_handler().handle_message(srs_cu_cp::generate_ng_setup_response()); + cu_cp_inst->get_cu_cp_ngap_connection_interface().get_ngap_message_handler().handle_message( + srs_cu_cp::generate_ng_setup_response()); // Connect F1-C to CU-CP. f1c_gw.attach_cu_cp_du_repo(cu_cp_inst->get_connected_dus()); From e704d1e8838f53f4e9f659733a1d8897cfcd5b6e Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 4 Jan 2024 19:30:14 +0100 Subject: [PATCH 052/134] cu-cp: avoid including asn1/e1ap in the public headers of the cu-cp --- include/srsran/e1ap/common/e1ap_common.h | 7 +++---- include/srsran/e1ap/cu_up/e1ap_connection_client.h | 1 + lib/e1ap/common/e1ap_asn1_packer.cpp | 2 +- .../procedures/bearer_context_modification_procedure.h | 2 +- .../cu_cp/procedures/bearer_context_release_procedure.h | 2 +- lib/e1ap/cu_up/e1ap_cu_up_impl.cpp | 2 +- lib/e1ap/cu_up/procedures/e1ap_cu_up_setup_procedure.cpp | 2 +- tests/unittests/cu_cp/du_processor_test_messages.cpp | 1 + tests/unittests/cu_up/cu_up_test_helpers.h | 1 + tests/unittests/e1ap/common/e1ap_cu_cp_test_messages.h | 1 + tests/unittests/e1ap/common/e1ap_cu_up_test_messages.cpp | 1 + tests/unittests/e1ap/common/test_helpers.h | 1 + 12 files changed, 14 insertions(+), 9 deletions(-) diff --git a/include/srsran/e1ap/common/e1ap_common.h b/include/srsran/e1ap/common/e1ap_common.h index 11a9ca5fcf..aab4459b67 100644 --- a/include/srsran/e1ap/common/e1ap_common.h +++ b/include/srsran/e1ap/common/e1ap_common.h @@ -10,12 +10,11 @@ #pragma once -#include "e1ap_message.h" -#include "srsran/asn1/e1ap/e1ap.h" - namespace srsran { -/// This interface is used to push E1AP messages to the E1AP interface. +struct e1ap_message; + +/// This interface is used to push the received E1AP PDUs to the CU-CP or CU-UP. class e1ap_message_handler { public: diff --git a/include/srsran/e1ap/cu_up/e1ap_connection_client.h b/include/srsran/e1ap/cu_up/e1ap_connection_client.h index 2330940a62..95ae9811cb 100644 --- a/include/srsran/e1ap/cu_up/e1ap_connection_client.h +++ b/include/srsran/e1ap/cu_up/e1ap_connection_client.h @@ -11,6 +11,7 @@ #pragma once #include "srsran/e1ap/common/e1ap_common.h" +#include namespace srsran { namespace srs_cu_up { diff --git a/lib/e1ap/common/e1ap_asn1_packer.cpp b/lib/e1ap/common/e1ap_asn1_packer.cpp index d8153b65e7..fd99c855e4 100644 --- a/lib/e1ap/common/e1ap_asn1_packer.cpp +++ b/lib/e1ap/common/e1ap_asn1_packer.cpp @@ -9,7 +9,7 @@ */ #include "e1ap_asn1_packer.h" -#include "srsran/asn1/e1ap/e1ap.h" +#include "srsran/e1ap/common/e1ap_message.h" using namespace srsran; diff --git a/lib/e1ap/cu_cp/procedures/bearer_context_modification_procedure.h b/lib/e1ap/cu_cp/procedures/bearer_context_modification_procedure.h index 698cb4430e..ba9b9a059a 100644 --- a/lib/e1ap/cu_cp/procedures/bearer_context_modification_procedure.h +++ b/lib/e1ap/cu_cp/procedures/bearer_context_modification_procedure.h @@ -13,7 +13,7 @@ #include "../e1ap_cu_cp_impl.h" #include "../ue_context/e1ap_cu_cp_ue_context.h" #include "common/e1ap_asn1_utils.h" -#include "srsran/asn1/e1ap/e1ap.h" +#include "srsran/e1ap/common/e1ap_message.h" #include "srsran/e1ap/cu_cp/e1ap_cu_cp.h" #include "srsran/support/async/async_task.h" diff --git a/lib/e1ap/cu_cp/procedures/bearer_context_release_procedure.h b/lib/e1ap/cu_cp/procedures/bearer_context_release_procedure.h index b7c95cfd17..55c1fb96fe 100644 --- a/lib/e1ap/cu_cp/procedures/bearer_context_release_procedure.h +++ b/lib/e1ap/cu_cp/procedures/bearer_context_release_procedure.h @@ -13,7 +13,7 @@ #include "../e1ap_cu_cp_impl.h" #include "../ue_context/e1ap_cu_cp_ue_context.h" #include "common/e1ap_asn1_utils.h" -#include "srsran/asn1/e1ap/e1ap.h" +#include "srsran/e1ap/common/e1ap_message.h" #include "srsran/e1ap/cu_cp/e1ap_cu_cp.h" #include "srsran/support/async/async_task.h" diff --git a/lib/e1ap/cu_up/e1ap_cu_up_impl.cpp b/lib/e1ap/cu_up/e1ap_cu_up_impl.cpp index 5151e5d919..f79380b41b 100644 --- a/lib/e1ap/cu_up/e1ap_cu_up_impl.cpp +++ b/lib/e1ap/cu_up/e1ap_cu_up_impl.cpp @@ -13,7 +13,7 @@ #include "cu_up/procedures/e1ap_cu_up_event_manager.h" #include "e1ap_cu_up_asn1_helpers.h" #include "procedures/e1ap_cu_up_setup_procedure.h" -#include "srsran/asn1/e1ap/e1ap.h" +#include "srsran/e1ap/common/e1ap_message.h" #include "srsran/e1ap/cu_up/e1ap_connection_client.h" #include "srsran/ran/bcd_helpers.h" #include "srsran/support/timers.h" diff --git a/lib/e1ap/cu_up/procedures/e1ap_cu_up_setup_procedure.cpp b/lib/e1ap/cu_up/procedures/e1ap_cu_up_setup_procedure.cpp index e89e11d819..26170fa879 100644 --- a/lib/e1ap/cu_up/procedures/e1ap_cu_up_setup_procedure.cpp +++ b/lib/e1ap/cu_up/procedures/e1ap_cu_up_setup_procedure.cpp @@ -10,7 +10,7 @@ #include "e1ap_cu_up_setup_procedure.h" #include "../e1ap_cu_up_asn1_helpers.h" -#include "srsran/f1ap/common/f1ap_message.h" +#include "srsran/e1ap/common/e1ap_message.h" #include "srsran/ran/bcd_helpers.h" #include "srsran/support/async/async_timer.h" diff --git a/tests/unittests/cu_cp/du_processor_test_messages.cpp b/tests/unittests/cu_cp/du_processor_test_messages.cpp index b9664203bd..95a7035db1 100644 --- a/tests/unittests/cu_cp/du_processor_test_messages.cpp +++ b/tests/unittests/cu_cp/du_processor_test_messages.cpp @@ -14,6 +14,7 @@ #include "lib/f1ap/cu_cp/f1ap_asn1_helpers.h" #include "tests/unittests/e1ap/common/e1ap_cu_cp_test_messages.h" #include "tests/unittests/f1ap/common/f1ap_cu_test_messages.h" +#include "srsran/e1ap/common/e1ap_message.h" #include "srsran/f1ap/common/f1ap_message.h" using namespace srsran; diff --git a/tests/unittests/cu_up/cu_up_test_helpers.h b/tests/unittests/cu_up/cu_up_test_helpers.h index a66dc2845a..b9ba468553 100644 --- a/tests/unittests/cu_up/cu_up_test_helpers.h +++ b/tests/unittests/cu_up/cu_up_test_helpers.h @@ -11,6 +11,7 @@ #pragma once #include "srsran/e1ap/common/e1ap_common.h" +#include "srsran/e1ap/common/e1ap_message.h" #include "srsran/e1ap/cu_up/e1ap_cu_up.h" #include "srsran/f1u/cu_up/f1u_gateway.h" #include "srsran/gtpu/gtpu_demux.h" diff --git a/tests/unittests/e1ap/common/e1ap_cu_cp_test_messages.h b/tests/unittests/e1ap/common/e1ap_cu_cp_test_messages.h index c5f78bad4e..172e04e223 100644 --- a/tests/unittests/e1ap/common/e1ap_cu_cp_test_messages.h +++ b/tests/unittests/e1ap/common/e1ap_cu_cp_test_messages.h @@ -10,6 +10,7 @@ #pragma once +#include "srsran/e1ap/common/e1ap_message.h" #include "srsran/e1ap/cu_cp/e1ap_cu_cp.h" namespace srsran { diff --git a/tests/unittests/e1ap/common/e1ap_cu_up_test_messages.cpp b/tests/unittests/e1ap/common/e1ap_cu_up_test_messages.cpp index 158b1f6e08..75dee813be 100644 --- a/tests/unittests/e1ap/common/e1ap_cu_up_test_messages.cpp +++ b/tests/unittests/e1ap/common/e1ap_cu_up_test_messages.cpp @@ -9,6 +9,7 @@ */ #include "e1ap_cu_up_test_messages.h" +#include "srsran/e1ap/common/e1ap_message.h" using namespace srsran; using namespace srs_cu_up; diff --git a/tests/unittests/e1ap/common/test_helpers.h b/tests/unittests/e1ap/common/test_helpers.h index ad6f3f994b..30f98804a4 100644 --- a/tests/unittests/e1ap/common/test_helpers.h +++ b/tests/unittests/e1ap/common/test_helpers.h @@ -15,6 +15,7 @@ #include "srsran/cu_up/cu_up.h" #include "srsran/cu_up/cu_up_types.h" #include "srsran/e1ap/common/e1ap_common.h" +#include "srsran/e1ap/common/e1ap_message.h" #include "srsran/e1ap/cu_cp/e1ap_cu_cp.h" #include "srsran/e1ap/cu_up/e1ap_cu_up.h" #include "srsran/e1ap/cu_up/e1ap_cu_up_bearer_context_update.h" From 027c374352b3c4557654e4bf36eb7bcf05508e0e Mon Sep 17 00:00:00 2001 From: ninjab3s Date: Fri, 5 Jan 2024 17:47:27 +0100 Subject: [PATCH 053/134] ci: Add libatomic to RHEL install_dep script --- .gitlab/ci/builders/install_dependencies.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab/ci/builders/install_dependencies.sh b/.gitlab/ci/builders/install_dependencies.sh index da67a73cb3..0b42610f96 100755 --- a/.gitlab/ci/builders/install_dependencies.sh +++ b/.gitlab/ci/builders/install_dependencies.sh @@ -54,10 +54,10 @@ main() { elif [[ "$ID" == "rhel" ]]; then if [[ "$mode" == "all" || "$mode" == "build" ]]; then - dnf -y install cmake fftw-devel lksctp-tools-devel yaml-cpp-devel mbedtls-devel gcc-toolset-11 gcc-toolset-11-gcc-c++ + dnf -y install cmake fftw-devel lksctp-tools-devel yaml-cpp-devel mbedtls-devel gcc-toolset-11 gcc-toolset-11-gcc-c++ gcc-toolset-12-libatomic-devel fi if [[ "$mode" == "all" || "$mode" == "run" ]]; then - dnf -y install fftw-devel lksctp-tools-devel yaml-cpp-devel mbedtls-devel + dnf -y install fftw-devel lksctp-tools-devel yaml-cpp-devel mbedtls-devel gcc-toolset-12-libatomic-devel fi if [[ "$mode" == "all" || "$mode" == "extra" ]]; then dnf -y install cppzmq-devel libusb1-devel boost-devel numactl-devel # dpdk libelf libdwarf From 755f1226fad0faa8f140fef4f1b0820d523980df Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 21 Dec 2023 22:46:47 +0100 Subject: [PATCH 054/134] support: initial iteration of an implementation of a lockfree stack --- .../memory_pool/lockfree_object_pool.h | 153 ++++++++++++++++++ tests/unittests/support/CMakeLists.txt | 4 + .../support/lockfree_object_pool_test.cpp | 48 ++++++ 3 files changed, 205 insertions(+) create mode 100644 include/srsran/support/memory_pool/lockfree_object_pool.h create mode 100644 tests/unittests/support/lockfree_object_pool_test.cpp diff --git a/include/srsran/support/memory_pool/lockfree_object_pool.h b/include/srsran/support/memory_pool/lockfree_object_pool.h new file mode 100644 index 0000000000..ef631ec2b4 --- /dev/null +++ b/include/srsran/support/memory_pool/lockfree_object_pool.h @@ -0,0 +1,153 @@ +/* + * + * 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. + * + */ + +/// \file Implementation of lock-free intrusive stack. +/// +/// Implementation is inspired on +/// https://www.codeproject.com/Articles/801537/A-Fundamental-Lock-Free-Building-Block-The-Lock-Fr. + +#pragma once + +#include "memory_block_list.h" +#include +#include + +namespace srsran { + +namespace detail { + +class lockfree_stack_node +{ +public: + using node_offset = uint32_t; + using epoch_index = uint32_t; + + static constexpr node_offset invalid_offset = std::numeric_limits::max(); + + node_offset next_offset; + epoch_index epoch; +}; + +class lockfree_offset_stack +{ + using node_t = lockfree_stack_node; + +public: + lockfree_offset_stack(uint8_t* pool_start_) : pool_start(pool_start_) {} + + /// Pushes a new memory block to the stack. + void push(node_t* n) noexcept + { + node_t old_head{node_t::invalid_offset, 0}; + node_t new_head{get_offset(*n), 0}; + n->next_offset = node_t::invalid_offset; + while (not head.compare_exchange_weak(old_head, new_head)) { + n->next_offset = old_head.next_offset; + new_head.epoch = old_head.epoch + 1; + } + } + + SRSRAN_NODISCARD bool pop(node_t*& n) + { + node_t old_head{node_t::invalid_offset, 0}; + node_t new_head{node_t::invalid_offset, 0}; + n = nullptr; + while (not head.compare_exchange_weak(old_head, new_head)) { + n = get_next_ptr(old_head); + if (n == nullptr) { + break; + } + new_head = node_t{n->next_offset, old_head.epoch + 1}; + } + return n != nullptr; + } + +private: + node_t* get_next_ptr(const node_t& n) + { + return n.next_offset != node_t::invalid_offset ? reinterpret_cast(pool_start + n.next_offset) : nullptr; + } + node_t::node_offset get_offset(const node_t& n) { return reinterpret_cast(&n) - pool_start; } + + std::atomic head{node_t{node_t::invalid_offset, 0}}; + + uint8_t* pool_start = nullptr; +}; + +} // namespace detail + +template +class lockfree_object_pool +{ + struct node : public detail::lockfree_stack_node { + T obj; + + node(const T& obj_) : obj(obj_) {} + }; + + struct custom_deleter { + lockfree_object_pool* pool; + + void operator()(T* t) + { + if (t != nullptr) { + pool->deallocate(t); + } + } + }; + +public: + using ptr = std::unique_ptr; + + lockfree_object_pool(size_t nof_elems, const T& val) : + objects(nof_elems, val), + offset_obj_to_node((size_t)(&(objects[0].obj)) - (size_t)&objects[0]), + free_list(reinterpret_cast(objects.data())), + estim_size(nof_elems) + { + srsran_assert(nof_elems > 0, "Invalid pool size={}", nof_elems); + + for (unsigned i = 0; i != nof_elems; ++i) { + free_list.push(&objects[i]); + } + } + + ptr allocate() noexcept + { + detail::lockfree_stack_node* popped_node; + if (free_list.pop(popped_node)) { + estim_size.fetch_sub(1, std::memory_order_relaxed); + return ptr{&static_cast(popped_node)->obj, custom_deleter{this}}; + } + return ptr{nullptr, custom_deleter{this}}; + } + + size_t capacity() const { return objects.size(); } + + size_t estimated_size() const { return estim_size.load(std::memory_order_relaxed); } + +private: + void deallocate(T* o) + { + estim_size.fetch_add(1, std::memory_order_relaxed); + node* node_ptr = reinterpret_cast(reinterpret_cast(o) - offset_obj_to_node); + free_list.push(node_ptr); + } + + std::vector objects; + + const size_t offset_obj_to_node; + + detail::lockfree_offset_stack free_list; + + std::atomic estim_size; +}; + +} // namespace srsran \ No newline at end of file diff --git a/tests/unittests/support/CMakeLists.txt b/tests/unittests/support/CMakeLists.txt index 92b45c4723..aead26b4c1 100644 --- a/tests/unittests/support/CMakeLists.txt +++ b/tests/unittests/support/CMakeLists.txt @@ -68,6 +68,10 @@ add_executable(fixed_size_memory_pool_test fixed_size_memory_pool_test.cpp) target_link_libraries(fixed_size_memory_pool_test srsran_support gtest gtest_main) add_test(fixed_size_memory_pool_test fixed_size_memory_pool_test) +add_executable(lockfree_object_pool_test lockfree_object_pool_test.cpp) +target_link_libraries(lockfree_object_pool_test atomic srsran_support gtest gtest_main) +add_test(lockfree_object_pool_test lockfree_object_pool_test) + add_executable(units_test units_test.cpp) target_link_libraries(units_test srslog srsran_support gtest gtest_main) add_test(units_test units_test) diff --git a/tests/unittests/support/lockfree_object_pool_test.cpp b/tests/unittests/support/lockfree_object_pool_test.cpp new file mode 100644 index 0000000000..b165e833c7 --- /dev/null +++ b/tests/unittests/support/lockfree_object_pool_test.cpp @@ -0,0 +1,48 @@ +/* + * + * 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 "srsran/support/memory_pool/lockfree_object_pool.h" +#include + +using namespace srsran; + +TEST(lockfree_object_pool_test, pool_created_with_requested_capacity) +{ + unsigned nof_objs = 10; + int val = 3; + lockfree_object_pool pool(nof_objs, val); + + ASSERT_EQ(pool.capacity(), nof_objs); + ASSERT_EQ(pool.estimated_size(), pool.capacity()); +} + +TEST(lockfree_object_pool_test, pool_allocates_elements_with_initialized_value) +{ + unsigned nof_objs = 10; + int val = 5; + + lockfree_object_pool pool(nof_objs, val); + + std::vector::ptr> allocated_objs; + for (unsigned i = 0; i != nof_objs; ++i) { + ASSERT_EQ(pool.estimated_size(), pool.capacity() - i); + allocated_objs.push_back(pool.allocate()); + ASSERT_EQ(*allocated_objs.back(), val); + } + ASSERT_EQ(pool.estimated_size(), 0); + ASSERT_EQ(pool.allocate(), nullptr); + + allocated_objs.clear(); + ASSERT_EQ(pool.estimated_size(), nof_objs); + + auto ptr = pool.allocate(); + ASSERT_EQ(*ptr, val); + ASSERT_EQ(pool.estimated_size(), nof_objs - 1); +} \ No newline at end of file From a78359575db5572ec2acf17404a4285e6efe4142 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 22 Dec 2023 00:53:19 +0100 Subject: [PATCH 055/134] support: use lockfree stack in byte buffer pool --- .../fixed_size_memory_block_pool.h | 54 +++++------- .../memory_pool/lockfree_object_pool.h | 87 +++++++++++++++++-- 2 files changed, 105 insertions(+), 36 deletions(-) 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 5822f44bd6..9c38888136 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,7 @@ #pragma once +#include "lockfree_object_pool.h" #include "memory_block_list.h" #include "srsran/adt/static_vector.h" #include "srsran/support/error_handling.h" @@ -66,7 +67,11 @@ class fixed_size_memory_block_pool nof_blocks(nof_blocks_), max_local_batches( std::max(std::min((size_t)MAX_LOCAL_BATCH_CAPACITY, static_cast(nof_blocks / block_batch_size / 32U)), - static_cast(2U))) + static_cast(2U))), + // Allocate the required memory for the given number of segments and segment size. + allocated_memory(mblock_size * nof_blocks), + // Push all segments to the central cache. + central_mem_cache(ceil(nof_blocks / (double)block_batch_size)) { srsran_assert(nof_blocks > max_local_cache_size(), "The number of segments in the pool must be much larger than the thread cache size ({} <= {})", @@ -77,17 +82,13 @@ class fixed_size_memory_block_pool mblock_size, free_memory_block_list::min_memory_block_align()); - // Allocate the required memory for the given number of segments and segment size. - const size_t total_mem = mblock_size * nof_blocks; - allocated_memory.resize(total_mem); - - // Push all segments to the central cache. - const size_t nof_batches = ceil(nof_blocks / (double)block_batch_size); - central_mem_cache.resize(nof_batches); - for (unsigned i = 0; i != nof_blocks; ++i) { - const unsigned batch_idx = i / block_batch_size; - const unsigned offset = i * mblock_size; - central_mem_cache[batch_idx].push(allocated_memory.data() + offset); + const unsigned nof_batches = ceil(nof_blocks / (double)block_batch_size); + for (unsigned i = 0; i != nof_batches; ++i) { + free_memory_block_list batch; + for (unsigned j = 0; j != block_batch_size; ++j) { + batch.push(allocated_memory.data() + (i * block_batch_size + j) * mblock_size); + } + central_mem_cache.push(batch); } } @@ -97,11 +98,7 @@ class fixed_size_memory_block_pool fixed_size_memory_block_pool& operator=(const fixed_size_memory_block_pool&) = delete; fixed_size_memory_block_pool& operator=(fixed_size_memory_block_pool&&) = delete; - ~fixed_size_memory_block_pool() - { - std::lock_guard lock(central_cache_mutex); - allocated_memory.clear(); - } + ~fixed_size_memory_block_pool() {} /// \brief Get instance of a memory pool singleton. static fixed_size_memory_block_pool& get_instance(size_t nof_blocks = 0, @@ -140,10 +137,9 @@ class fixed_size_memory_block_pool } // Local cache is empty. Attempt memory block pop from central cache. - std::lock_guard lock(central_cache_mutex); - if (not central_mem_cache.empty()) { - w_ctx->local_cache.push_back(central_mem_cache.back()); - central_mem_cache.pop_back(); + free_memory_block_list batch; + if (central_mem_cache.pop(batch)) { + w_ctx->local_cache.push_back(batch); node = w_ctx->local_cache.back().try_pop(); } @@ -182,9 +178,8 @@ class fixed_size_memory_block_pool 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. // We leave one batch in the local cache. - std::lock_guard lock(central_cache_mutex); for (unsigned i = 0; i != max_local_batches - 1; ++i) { - central_mem_cache.push_back(w_ctx->local_cache.back()); + central_mem_cache.push(w_ctx->local_cache.back()); w_ctx->local_cache.pop_back(); } } @@ -212,10 +207,9 @@ class fixed_size_memory_block_pool worker_ctxt() : id(std::this_thread::get_id()) {} ~worker_ctxt() { - pool_type& pool = pool_type::get_instance(); - std::lock_guard lock(pool.central_cache_mutex); + pool_type& pool = pool_type::get_instance(); while (not local_cache.empty()) { - pool.central_mem_cache.push_back(local_cache.back()); + pool.central_mem_cache.push(local_cache.back()); local_cache.pop_back(); } } @@ -231,11 +225,11 @@ class fixed_size_memory_block_pool const size_t nof_blocks; const size_t max_local_batches; - std::mutex central_cache_mutex; - std::vector central_mem_cache; - - std::mutex debug_mutex; std::vector allocated_memory; + + lockfree_bounded_stack central_mem_cache; + + std::mutex debug_mutex; }; } // namespace srsran diff --git a/include/srsran/support/memory_pool/lockfree_object_pool.h b/include/srsran/support/memory_pool/lockfree_object_pool.h index ef631ec2b4..75c0a7f5a2 100644 --- a/include/srsran/support/memory_pool/lockfree_object_pool.h +++ b/include/srsran/support/memory_pool/lockfree_object_pool.h @@ -16,6 +16,7 @@ #pragma once #include "memory_block_list.h" +#include "srsran/adt/unique_function.h" #include #include @@ -40,7 +41,7 @@ class lockfree_offset_stack using node_t = lockfree_stack_node; public: - lockfree_offset_stack(uint8_t* pool_start_) : pool_start(pool_start_) {} + lockfree_offset_stack(node_t* pool_start_) : pool_start(reinterpret_cast(pool_start_)) {} /// Pushes a new memory block to the stack. void push(node_t* n) noexcept @@ -83,6 +84,61 @@ class lockfree_offset_stack } // namespace detail +template +class lockfree_bounded_stack +{ + struct node : public detail::lockfree_stack_node { + T obj; + + node() = default; + node(const T& obj_) : obj(obj_) {} + }; + +public: + lockfree_bounded_stack(size_t capacity) : mem_chunk(capacity), free_list(mem_chunk.data()), stack(mem_chunk.data()) + { + srsran_assert(capacity > 0, "Invalid stack capacity={}", capacity); + for (unsigned i = 0; i != capacity; ++i) { + free_list.push(&mem_chunk[i]); + } + } + + void push(const T& item) + { + detail::lockfree_stack_node* popped_node; + bool success = free_list.pop(popped_node); + if (not success) { + return; + } + // srsran_assert(success, "capacity exceeded"); + static_cast(popped_node)->obj = item; + stack.push(popped_node); + sz_estim.fetch_add(1, std::memory_order_relaxed); + } + + bool pop(T& item) + { + detail::lockfree_stack_node* popped_node; + if (stack.pop(popped_node)) { + item = static_cast(popped_node)->obj; + free_list.push(popped_node); + sz_estim.fetch_sub(1, std::memory_order_relaxed); + return true; + } + return false; + } + + size_t size() const { return sz_estim; } + +private: + std::vector mem_chunk; + + detail::lockfree_offset_stack free_list; + detail::lockfree_offset_stack stack; + + std::atomic sz_estim{0}; +}; + template class lockfree_object_pool { @@ -106,10 +162,10 @@ class lockfree_object_pool public: using ptr = std::unique_ptr; - lockfree_object_pool(size_t nof_elems, const T& val) : + lockfree_object_pool(size_t nof_elems, const T& val = {}) : objects(nof_elems, val), offset_obj_to_node((size_t)(&(objects[0].obj)) - (size_t)&objects[0]), - free_list(reinterpret_cast(objects.data())), + free_list(objects.data()), estim_size(nof_elems) { srsran_assert(nof_elems > 0, "Invalid pool size={}", nof_elems); @@ -119,6 +175,25 @@ class lockfree_object_pool } } + lockfree_object_pool(size_t nof_elems, unique_function factory) : + objects([nof_elems, factory = std::move(factory)]() mutable { + srsran_assert(nof_elems > 0, "Invalid pool size={}", nof_elems); + std::vector vec; + vec.reserve(nof_elems); + for (unsigned i = 0; i != nof_elems; ++i) { + vec.emplace_back(factory()); + } + return vec; + }()), + offset_obj_to_node((size_t)(&(objects[0].obj)) - (size_t)&objects[0]), + free_list(objects.data()), + estim_size(nof_elems) + { + for (unsigned i = 0; i != nof_elems; ++i) { + free_list.push(&objects[i]); + } + } + ptr allocate() noexcept { detail::lockfree_stack_node* popped_node; @@ -134,16 +209,16 @@ class lockfree_object_pool size_t estimated_size() const { return estim_size.load(std::memory_order_relaxed); } private: - void deallocate(T* o) + void deallocate(T* o) noexcept { - estim_size.fetch_add(1, std::memory_order_relaxed); node* node_ptr = reinterpret_cast(reinterpret_cast(o) - offset_obj_to_node); free_list.push(node_ptr); + estim_size.fetch_add(1, std::memory_order_relaxed); } std::vector objects; - const size_t offset_obj_to_node; + size_t offset_obj_to_node; detail::lockfree_offset_stack free_list; From f3ea5d3ac4b79274e269249b5a7f53e71ccfe3f2 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 22 Dec 2023 12:39:57 +0100 Subject: [PATCH 056/134] support: new implementation of lockfree stack --- .../fixed_size_memory_block_pool.h | 10 +- .../memory_pool/lockfree_object_pool.h | 116 +++++++++++++----- .../support/lockfree_object_pool_test.cpp | 36 +++++- 3 files changed, 126 insertions(+), 36 deletions(-) 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 9c38888136..ed4f51fbb4 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 @@ -88,7 +88,7 @@ class fixed_size_memory_block_pool for (unsigned j = 0; j != block_batch_size; ++j) { batch.push(allocated_memory.data() + (i * block_batch_size + j) * mblock_size); } - central_mem_cache.push(batch); + report_fatal_error_if_not(central_mem_cache.push(batch), "Failed to push batch to central cache"); } } @@ -179,7 +179,8 @@ class fixed_size_memory_block_pool // Local cache is full. Rebalance by sending batches of blocks to central cache. // We leave one batch in the local cache. for (unsigned i = 0; i != max_local_batches - 1; ++i) { - central_mem_cache.push(w_ctx->local_cache.back()); + report_fatal_error_if_not(central_mem_cache.push(w_ctx->local_cache.back()), + "Failed to push batch to central cache"); w_ctx->local_cache.pop_back(); } } @@ -209,6 +210,11 @@ class fixed_size_memory_block_pool { pool_type& pool = pool_type::get_instance(); while (not local_cache.empty()) { + if (local_cache.back().size() < block_batch_size) { + // for now we do not handle this situation. + local_cache.pop_back(); + continue; + } pool.central_mem_cache.push(local_cache.back()); local_cache.pop_back(); } diff --git a/include/srsran/support/memory_pool/lockfree_object_pool.h b/include/srsran/support/memory_pool/lockfree_object_pool.h index 75c0a7f5a2..7a93241f2b 100644 --- a/include/srsran/support/memory_pool/lockfree_object_pool.h +++ b/include/srsran/support/memory_pool/lockfree_object_pool.h @@ -24,6 +24,63 @@ namespace srsran { namespace detail { +class lockfree_index_stack +{ +public: + using index_type = uint32_t; + + static constexpr index_type npos() { return std::numeric_limits::max(); } + + lockfree_index_stack(uint32_t nof_indexes, bool start_full) : + top(node{start_full ? 0 : npos(), 0}), next_idx(nof_indexes, npos()) + { + srsran_assert(nof_indexes > 0 and nof_indexes < npos(), "Invalid stack size={}", nof_indexes); + + // Initialize the stack of next indexes like [1, 2, 3, ..., nof_indexes - 1, npos] + for (index_type i = 1; i < nof_indexes; ++i) { + next_idx[i - 1] = i; + } + } + + index_type capacity() const { return next_idx.size(); } + + index_type try_pop() + { + node old_top{top.load(std::memory_order_relaxed)}; + if (old_top.index == npos()) { + return npos(); + } + node new_top{next_idx[old_top.index], old_top.epoch + 1}; + while (not top.compare_exchange_weak(old_top, new_top)) { + if (old_top.index == npos()) { + return npos(); + } + new_top = node{next_idx[old_top.index], old_top.epoch + 1}; + } + return old_top.index; + } + + void push(index_type index) + { + node old_top{top.load(std::memory_order_relaxed)}; + next_idx[index] = old_top.index; + node new_top{index, old_top.epoch + 1}; + while (not top.compare_exchange_weak(old_top, new_top)) { + new_top.epoch = old_top.epoch + 1; + next_idx[index] = old_top.index; + } + } + +private: + struct node { + index_type index; + index_type epoch; + }; + + std::atomic top; + std::vector next_idx; +}; + class lockfree_stack_node { public: @@ -87,56 +144,49 @@ class lockfree_offset_stack template class lockfree_bounded_stack { - struct node : public detail::lockfree_stack_node { - T obj; + using index_type = detail::lockfree_index_stack::index_type; - node() = default; - node(const T& obj_) : obj(obj_) {} - }; + static constexpr index_type npos() { return detail::lockfree_index_stack::npos(); } public: - lockfree_bounded_stack(size_t capacity) : mem_chunk(capacity), free_list(mem_chunk.data()), stack(mem_chunk.data()) - { - srsran_assert(capacity > 0, "Invalid stack capacity={}", capacity); - for (unsigned i = 0; i != capacity; ++i) { - free_list.push(&mem_chunk[i]); - } - } + lockfree_bounded_stack(unsigned capacity) : objects(capacity), free_list(capacity, true), stack(capacity, false) {} - void push(const T& item) + bool push(const T& item) { - detail::lockfree_stack_node* popped_node; - bool success = free_list.pop(popped_node); - if (not success) { - return; + index_type popped_idx = free_list.try_pop(); + if (popped_idx == npos()) { + // Capacity exceeded. + return false; } - // srsran_assert(success, "capacity exceeded"); - static_cast(popped_node)->obj = item; - stack.push(popped_node); + objects[popped_idx] = item; + stack.push(popped_idx); sz_estim.fetch_add(1, std::memory_order_relaxed); + return true; } - bool pop(T& item) + bool pop(T& popped_item) { - detail::lockfree_stack_node* popped_node; - if (stack.pop(popped_node)) { - item = static_cast(popped_node)->obj; - free_list.push(popped_node); - sz_estim.fetch_sub(1, std::memory_order_relaxed); - return true; + index_type popped_idx = stack.try_pop(); + if (popped_idx == npos()) { + return false; } - return false; + popped_item = std::move(objects[popped_idx]); + free_list.push(popped_idx); + sz_estim.fetch_sub(1, std::memory_order_relaxed); + return true; } - size_t size() const { return sz_estim; } + size_t size() const { return sz_estim.load(std::memory_order_relaxed); } + + size_t capacity() const { return objects.size(); } private: - std::vector mem_chunk; + std::vector objects; - detail::lockfree_offset_stack free_list; - detail::lockfree_offset_stack stack; + detail::lockfree_index_stack free_list; + detail::lockfree_index_stack stack; - std::atomic sz_estim{0}; + std::atomic sz_estim{0}; }; template diff --git a/tests/unittests/support/lockfree_object_pool_test.cpp b/tests/unittests/support/lockfree_object_pool_test.cpp index b165e833c7..71937a93a7 100644 --- a/tests/unittests/support/lockfree_object_pool_test.cpp +++ b/tests/unittests/support/lockfree_object_pool_test.cpp @@ -45,4 +45,38 @@ TEST(lockfree_object_pool_test, pool_allocates_elements_with_initialized_value) auto ptr = pool.allocate(); ASSERT_EQ(*ptr, val); ASSERT_EQ(pool.estimated_size(), nof_objs - 1); -} \ No newline at end of file +} + +TEST(lockfree_bounded_stack_test, test_initialization) +{ + lockfree_bounded_stack stack{10}; + ASSERT_EQ(stack.capacity(), 10); + ASSERT_EQ(stack.size(), 0); +} + +TEST(lockfree_bounded_stack_test, test_push_pop_one_element) +{ + lockfree_bounded_stack stack{10}; + + stack.push(5); + ASSERT_EQ(stack.size(), 1); + ASSERT_EQ(stack.capacity(), 10); + + int val; + ASSERT_TRUE(stack.pop(val)); + ASSERT_EQ(val, 5); + ASSERT_EQ(stack.size(), 0); + ASSERT_EQ(stack.capacity(), 10); +} + +TEST(lockfree_bounded_stack_test, test_pop_empty) +{ + lockfree_bounded_stack stack{10}; + + int val = 3; + ASSERT_FALSE(stack.pop(val)); + stack.push(val); + ASSERT_TRUE(stack.pop(val)); + ASSERT_EQ(val, 3); + ASSERT_FALSE(stack.pop(val)); +} From 55a363a732ca39b148141b58509189bf3488a068 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 22 Dec 2023 17:09:56 +0100 Subject: [PATCH 057/134] support: use new stack of indexes in lockfree object pool implementation --- .../memory_pool/lockfree_object_pool.h | 158 +++++------------- .../support/lockfree_object_pool_test.cpp | 6 +- 2 files changed, 43 insertions(+), 121 deletions(-) diff --git a/include/srsran/support/memory_pool/lockfree_object_pool.h b/include/srsran/support/memory_pool/lockfree_object_pool.h index 7a93241f2b..4c6bdf3817 100644 --- a/include/srsran/support/memory_pool/lockfree_object_pool.h +++ b/include/srsran/support/memory_pool/lockfree_object_pool.h @@ -9,9 +9,6 @@ */ /// \file Implementation of lock-free intrusive stack. -/// -/// Implementation is inspired on -/// https://www.codeproject.com/Articles/801537/A-Fundamental-Lock-Free-Building-Block-The-Lock-Fr. #pragma once @@ -24,6 +21,7 @@ namespace srsran { namespace detail { +/// \brief Lock-free stack of indexes. class lockfree_index_stack { public: @@ -81,66 +79,9 @@ class lockfree_index_stack std::vector next_idx; }; -class lockfree_stack_node -{ -public: - using node_offset = uint32_t; - using epoch_index = uint32_t; - - static constexpr node_offset invalid_offset = std::numeric_limits::max(); - - node_offset next_offset; - epoch_index epoch; -}; - -class lockfree_offset_stack -{ - using node_t = lockfree_stack_node; - -public: - lockfree_offset_stack(node_t* pool_start_) : pool_start(reinterpret_cast(pool_start_)) {} - - /// Pushes a new memory block to the stack. - void push(node_t* n) noexcept - { - node_t old_head{node_t::invalid_offset, 0}; - node_t new_head{get_offset(*n), 0}; - n->next_offset = node_t::invalid_offset; - while (not head.compare_exchange_weak(old_head, new_head)) { - n->next_offset = old_head.next_offset; - new_head.epoch = old_head.epoch + 1; - } - } - - SRSRAN_NODISCARD bool pop(node_t*& n) - { - node_t old_head{node_t::invalid_offset, 0}; - node_t new_head{node_t::invalid_offset, 0}; - n = nullptr; - while (not head.compare_exchange_weak(old_head, new_head)) { - n = get_next_ptr(old_head); - if (n == nullptr) { - break; - } - new_head = node_t{n->next_offset, old_head.epoch + 1}; - } - return n != nullptr; - } - -private: - node_t* get_next_ptr(const node_t& n) - { - return n.next_offset != node_t::invalid_offset ? reinterpret_cast(pool_start + n.next_offset) : nullptr; - } - node_t::node_offset get_offset(const node_t& n) { return reinterpret_cast(&n) - pool_start; } - - std::atomic head{node_t{node_t::invalid_offset, 0}}; - - uint8_t* pool_start = nullptr; -}; - } // namespace detail +/// \brief Lock-free stack of objects with bounded capacity. template class lockfree_bounded_stack { @@ -189,90 +130,71 @@ class lockfree_bounded_stack std::atomic sz_estim{0}; }; +/// \brief Lock-free pool of objects. template class lockfree_object_pool { - struct node : public detail::lockfree_stack_node { - T obj; - - node(const T& obj_) : obj(obj_) {} - }; + using index_type = detail::lockfree_index_stack::index_type; - struct custom_deleter { - lockfree_object_pool* pool; + static constexpr index_type npos() { return detail::lockfree_index_stack::npos(); } - void operator()(T* t) + struct pool_deleter { + lockfree_object_pool* parent; + void operator()(T* t) { if (t != nullptr) { - pool->deallocate(t); + parent->release_raw(t); } } }; public: - using ptr = std::unique_ptr; + /// Pointer type to object managed by the object pool. + using ptr = std::unique_ptr; - lockfree_object_pool(size_t nof_elems, const T& val = {}) : - objects(nof_elems, val), - offset_obj_to_node((size_t)(&(objects[0].obj)) - (size_t)&objects[0]), - free_list(objects.data()), - estim_size(nof_elems) + lockfree_object_pool(unsigned nof_elems, const T& val = {}) : + objects(nof_elems, val), free_list(nof_elems, true), sz_estim(nof_elems) { srsran_assert(nof_elems > 0, "Invalid pool size={}", nof_elems); - - for (unsigned i = 0; i != nof_elems; ++i) { - free_list.push(&objects[i]); - } } - lockfree_object_pool(size_t nof_elems, unique_function factory) : - objects([nof_elems, factory = std::move(factory)]() mutable { - srsran_assert(nof_elems > 0, "Invalid pool size={}", nof_elems); - std::vector vec; - vec.reserve(nof_elems); - for (unsigned i = 0; i != nof_elems; ++i) { - vec.emplace_back(factory()); - } - return vec; - }()), - offset_obj_to_node((size_t)(&(objects[0].obj)) - (size_t)&objects[0]), - free_list(objects.data()), - estim_size(nof_elems) - { - for (unsigned i = 0; i != nof_elems; ++i) { - free_list.push(&objects[i]); - } - } - - ptr allocate() noexcept - { - detail::lockfree_stack_node* popped_node; - if (free_list.pop(popped_node)) { - estim_size.fetch_sub(1, std::memory_order_relaxed); - return ptr{&static_cast(popped_node)->obj, custom_deleter{this}}; - } - return ptr{nullptr, custom_deleter{this}}; - } + /// Allocate new pool object with managed lifetime. + ptr get() { return ptr{get_raw(), pool_deleter{this}}; } + /// Maximum number of objects managed by this pool. size_t capacity() const { return objects.size(); } - size_t estimated_size() const { return estim_size.load(std::memory_order_relaxed); } + /// Estimation of the available objects currently stored in this pool. + size_t estimated_size() const { return sz_estim.load(std::memory_order_relaxed); } -private: - void deallocate(T* o) noexcept + T* get_raw() { - node* node_ptr = reinterpret_cast(reinterpret_cast(o) - offset_obj_to_node); - free_list.push(node_ptr); - estim_size.fetch_add(1, std::memory_order_relaxed); + index_type popped_idx = free_list.try_pop(); + if (popped_idx == npos()) { + // Capacity exceeded. + return nullptr; + } + sz_estim.fetch_sub(1, std::memory_order_relaxed); + return &objects[popped_idx]; } - std::vector objects; + void release_raw(T* node) + { + srsran_assert(node >= objects.data() and node < objects.data() + objects.size(), + "Deallocated nodes must be within the pool"); + index_type idx = node - objects.data(); + sz_estim.fetch_add(1, std::memory_order_relaxed); + free_list.push(idx); + } - size_t offset_obj_to_node; +private: + // List of created objects. + std::vector objects; - detail::lockfree_offset_stack free_list; + // List of free indexes of the objects vector. + detail::lockfree_index_stack free_list; - std::atomic estim_size; + std::atomic sz_estim; }; } // namespace srsran \ No newline at end of file diff --git a/tests/unittests/support/lockfree_object_pool_test.cpp b/tests/unittests/support/lockfree_object_pool_test.cpp index 71937a93a7..fc1f0f4d0f 100644 --- a/tests/unittests/support/lockfree_object_pool_test.cpp +++ b/tests/unittests/support/lockfree_object_pool_test.cpp @@ -33,16 +33,16 @@ TEST(lockfree_object_pool_test, pool_allocates_elements_with_initialized_value) std::vector::ptr> allocated_objs; for (unsigned i = 0; i != nof_objs; ++i) { ASSERT_EQ(pool.estimated_size(), pool.capacity() - i); - allocated_objs.push_back(pool.allocate()); + allocated_objs.push_back(pool.get()); ASSERT_EQ(*allocated_objs.back(), val); } ASSERT_EQ(pool.estimated_size(), 0); - ASSERT_EQ(pool.allocate(), nullptr); + ASSERT_EQ(pool.get(), nullptr); allocated_objs.clear(); ASSERT_EQ(pool.estimated_size(), nof_objs); - auto ptr = pool.allocate(); + auto ptr = pool.get(); ASSERT_EQ(*ptr, val); ASSERT_EQ(pool.estimated_size(), nof_objs - 1); } From 3c5fd3cee1d23f9ef9dfeba7a773a68796faa2ec Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 3 Jan 2024 15:45:31 +0100 Subject: [PATCH 058/134] support: relax lockfree stack memory ordering --- include/srsran/support/memory_pool/lockfree_object_pool.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/srsran/support/memory_pool/lockfree_object_pool.h b/include/srsran/support/memory_pool/lockfree_object_pool.h index 4c6bdf3817..1793ce35ce 100644 --- a/include/srsran/support/memory_pool/lockfree_object_pool.h +++ b/include/srsran/support/memory_pool/lockfree_object_pool.h @@ -49,7 +49,7 @@ class lockfree_index_stack return npos(); } node new_top{next_idx[old_top.index], old_top.epoch + 1}; - while (not top.compare_exchange_weak(old_top, new_top)) { + while (not top.compare_exchange_weak(old_top, new_top, std::memory_order_acquire, std::memory_order_acquire)) { if (old_top.index == npos()) { return npos(); } @@ -63,7 +63,7 @@ class lockfree_index_stack node old_top{top.load(std::memory_order_relaxed)}; next_idx[index] = old_top.index; node new_top{index, old_top.epoch + 1}; - while (not top.compare_exchange_weak(old_top, new_top)) { + while (not top.compare_exchange_weak(old_top, new_top, std::memory_order_release, std::memory_order_release)) { new_top.epoch = old_top.epoch + 1; next_idx[index] = old_top.index; } From df6451f17d6af7303349677c451b2949eb20c1aa Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 3 Jan 2024 18:52:40 +0100 Subject: [PATCH 059/134] support: fix byte_buffer_pool when worker gets destroyed --- .../memory_pool/fixed_size_memory_block_pool.h | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) 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 ed4f51fbb4..6835e2c555 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 @@ -211,7 +211,18 @@ class fixed_size_memory_block_pool pool_type& pool = pool_type::get_instance(); while (not local_cache.empty()) { if (local_cache.back().size() < block_batch_size) { - // for now we do not handle this situation. + // Batch is incomplete. We combine it with any other existing incomplete batch. + { + std::lock_guard lock(pool.incomplete_batch_mutex); + while (not local_cache.back().empty()) { + pool.incomplete_batch.push(local_cache.back().try_pop()); + if (pool.incomplete_batch.size() >= block_batch_size) { + // The incomplete batch is now complete and can be pushed to the central cache. + pool.central_mem_cache.push(pool.incomplete_batch); + pool.incomplete_batch.clear(); + } + } + } local_cache.pop_back(); continue; } @@ -235,6 +246,11 @@ class fixed_size_memory_block_pool lockfree_bounded_stack central_mem_cache; + // When workers get deleted, some local batches may be still incomplete. We collect them here to form full batches + // when other workers get deleted as well. + std::mutex incomplete_batch_mutex; + free_memory_block_list incomplete_batch; + std::mutex debug_mutex; }; From 031d5af29ea9db37f3e5fbfc51683f8eaa1d1aed Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 5 Jan 2024 10:46:10 +0100 Subject: [PATCH 060/134] support: fix memory ordering in lockfree stack --- .../support/memory_pool/lockfree_object_pool.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/include/srsran/support/memory_pool/lockfree_object_pool.h b/include/srsran/support/memory_pool/lockfree_object_pool.h index 1793ce35ce..f4b8e473e3 100644 --- a/include/srsran/support/memory_pool/lockfree_object_pool.h +++ b/include/srsran/support/memory_pool/lockfree_object_pool.h @@ -12,9 +12,9 @@ #pragma once -#include "memory_block_list.h" -#include "srsran/adt/unique_function.h" +#include "srsran/support/srsran_assert.h" #include +#include #include namespace srsran { @@ -49,7 +49,11 @@ class lockfree_index_stack return npos(); } node new_top{next_idx[old_top.index], old_top.epoch + 1}; - while (not top.compare_exchange_weak(old_top, new_top, std::memory_order_acquire, std::memory_order_acquire)) { + // We use memory ordering "acquire" to form a "synchronizes-with" relationship with the release in push(). + // The "acquire" ordering also ensures that the next_idx[old_top.index] read is not reordered to happen before the + // atomic operation. + // In case of failure, "top" remains unchanged, so the operation can have "relaxed" ordering. + while (not top.compare_exchange_weak(old_top, new_top, std::memory_order_acquire, std::memory_order_relaxed)) { if (old_top.index == npos()) { return npos(); } @@ -63,6 +67,9 @@ class lockfree_index_stack node old_top{top.load(std::memory_order_relaxed)}; next_idx[index] = old_top.index; node new_top{index, old_top.epoch + 1}; + // We use memory ordering "release" for success path to form a "synchronizes-with" relationship with the acquire in + // pop(). The "release" ordering also ensures that the next_idx[index] write is visible to other threads. + // In case of failure, "top" remains unchanged, so the operation can have "release" ordering. while (not top.compare_exchange_weak(old_top, new_top, std::memory_order_release, std::memory_order_release)) { new_top.epoch = old_top.epoch + 1; next_idx[index] = old_top.index; From 72993a666583ef6f3d459c2dfa767c06258c7777 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 5 Jan 2024 11:06:08 +0100 Subject: [PATCH 061/134] support: add assert to ensure that no one changes the size of the lockfree stack node --- include/srsran/support/memory_pool/lockfree_object_pool.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/srsran/support/memory_pool/lockfree_object_pool.h b/include/srsran/support/memory_pool/lockfree_object_pool.h index f4b8e473e3..6a55440e47 100644 --- a/include/srsran/support/memory_pool/lockfree_object_pool.h +++ b/include/srsran/support/memory_pool/lockfree_object_pool.h @@ -81,6 +81,8 @@ class lockfree_index_stack index_type index; index_type epoch; }; + static_assert(sizeof(node) == sizeof(uint64_t), + "node sizeof should no go beyond 64-bits, otherwise we lose is_lock_free guarantees in most platforms"); std::atomic top; std::vector next_idx; From 929680157e9d30a8c4a6621220e2f0b50f52aeb8 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 5 Jan 2024 16:49:59 +0100 Subject: [PATCH 062/134] support: link lib atomic to srsran_support --- lib/support/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/support/CMakeLists.txt b/lib/support/CMakeLists.txt index 2c08cc2761..01b3f8208d 100644 --- a/lib/support/CMakeLists.txt +++ b/lib/support/CMakeLists.txt @@ -27,7 +27,7 @@ set(SOURCES byte_buffer_chain.cpp) add_library(srsran_support STATIC ${SOURCES}) -target_link_libraries(srsran_support srsran_network ${CMAKE_THREAD_LIBS_INIT} ${YAMLCPP_LIBRARY} srslog) +target_link_libraries(srsran_support srsran_network ${CMAKE_THREAD_LIBS_INIT} ${YAMLCPP_LIBRARY} srslog atomic) add_backward(srsran_support) if (Backward_FOUND AND BACKWARD_HAS_EXTERNAL_LIBRARIES) From 9b6c23654d552634e23625b2323228b5341e0c90 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 5 Jan 2024 17:09:09 +0100 Subject: [PATCH 063/134] support: fix memory ordering in lockfree stack push method --- include/srsran/support/memory_pool/lockfree_object_pool.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/srsran/support/memory_pool/lockfree_object_pool.h b/include/srsran/support/memory_pool/lockfree_object_pool.h index 6a55440e47..4a7d815e40 100644 --- a/include/srsran/support/memory_pool/lockfree_object_pool.h +++ b/include/srsran/support/memory_pool/lockfree_object_pool.h @@ -69,8 +69,8 @@ class lockfree_index_stack node new_top{index, old_top.epoch + 1}; // We use memory ordering "release" for success path to form a "synchronizes-with" relationship with the acquire in // pop(). The "release" ordering also ensures that the next_idx[index] write is visible to other threads. - // In case of failure, "top" remains unchanged, so the operation can have "release" ordering. - while (not top.compare_exchange_weak(old_top, new_top, std::memory_order_release, std::memory_order_release)) { + // In case of failure, "top" remains unchanged, so the operation can have "relaxed" ordering. + while (not top.compare_exchange_weak(old_top, new_top, std::memory_order_release, std::memory_order_relaxed)) { new_top.epoch = old_top.epoch + 1; next_idx[index] = old_top.index; } From ae2ab8b26aa1f8eb0f0ad291bc5e001d47b49341 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 5 Jan 2024 17:49:47 +0100 Subject: [PATCH 064/134] support: add tsan label to several unit tests that require threads --- include/srsran/support/memory_pool/lockfree_object_pool.h | 4 ++-- tests/unittests/support/CMakeLists.txt | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/include/srsran/support/memory_pool/lockfree_object_pool.h b/include/srsran/support/memory_pool/lockfree_object_pool.h index 4a7d815e40..5587d76e2a 100644 --- a/include/srsran/support/memory_pool/lockfree_object_pool.h +++ b/include/srsran/support/memory_pool/lockfree_object_pool.h @@ -81,8 +81,8 @@ class lockfree_index_stack index_type index; index_type epoch; }; - static_assert(sizeof(node) == sizeof(uint64_t), - "node sizeof should no go beyond 64-bits, otherwise we lose is_lock_free guarantees in most platforms"); + static_assert(sizeof(node) <= sizeof(uint64_t), + "node sizeof should not go above 64-bits, otherwise we lose is_lock_free guarantees in most platforms"); std::atomic top; std::vector next_idx; diff --git a/tests/unittests/support/CMakeLists.txt b/tests/unittests/support/CMakeLists.txt index aead26b4c1..eb81f194b9 100644 --- a/tests/unittests/support/CMakeLists.txt +++ b/tests/unittests/support/CMakeLists.txt @@ -67,10 +67,12 @@ add_test(ring_buffer_pool_test ring_buffer_pool_test) add_executable(fixed_size_memory_pool_test fixed_size_memory_pool_test.cpp) target_link_libraries(fixed_size_memory_pool_test srsran_support gtest gtest_main) add_test(fixed_size_memory_pool_test fixed_size_memory_pool_test) +set_tests_properties(fixed_size_memory_pool_test PROPERTIES LABELS "tsan") add_executable(lockfree_object_pool_test lockfree_object_pool_test.cpp) -target_link_libraries(lockfree_object_pool_test atomic srsran_support gtest gtest_main) +target_link_libraries(lockfree_object_pool_test srsran_support gtest gtest_main) add_test(lockfree_object_pool_test lockfree_object_pool_test) +set_tests_properties(lockfree_object_pool_test PROPERTIES LABELS "tsan") add_executable(units_test units_test.cpp) target_link_libraries(units_test srslog srsran_support gtest gtest_main) From 10bc552e3f0c84138e3dba362f0d9819b8e40892 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 5 Jan 2024 18:49:56 +0100 Subject: [PATCH 065/134] f1ap-cu: remove asn1 from public f1ap-cu headers --- include/srsran/f1ap/cu_cp/f1ap_cu.h | 9 --------- include/srsran/f1ap/cu_cp/f1ap_cu_ue_context_update.h | 2 -- tests/unittests/f1ap/common/f1ap_cu_test_messages.h | 1 + 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/include/srsran/f1ap/cu_cp/f1ap_cu.h b/include/srsran/f1ap/cu_cp/f1ap_cu.h index f7c52de82f..963a92c564 100644 --- a/include/srsran/f1ap/cu_cp/f1ap_cu.h +++ b/include/srsran/f1ap/cu_cp/f1ap_cu.h @@ -23,11 +23,6 @@ namespace srsran { namespace srs_cu_cp { -struct f1ap_ul_rrc_message { - ue_index_t ue_index = ue_index_t::invalid; - asn1::f1ap::ul_rrc_msg_transfer_s msg; -}; - struct f1ap_dl_rrc_message { ue_index_t ue_index = ue_index_t::invalid; srb_id_t srb_id = srb_id_t::nulltype; @@ -63,10 +58,6 @@ struct f1ap_ue_context_release_command { optional srb_id; }; -struct f1ap_ue_context_release_complete { - asn1::f1ap::ue_context_release_complete_s msg; -}; - /// Handle F1AP UE context management procedures as defined in TS 38.473 section 8.3. class f1ap_ue_context_manager { diff --git a/include/srsran/f1ap/cu_cp/f1ap_cu_ue_context_update.h b/include/srsran/f1ap/cu_cp/f1ap_cu_ue_context_update.h index d162dd9bfb..35fd2f40fe 100644 --- a/include/srsran/f1ap/cu_cp/f1ap_cu_ue_context_update.h +++ b/include/srsran/f1ap/cu_cp/f1ap_cu_ue_context_update.h @@ -10,8 +10,6 @@ #pragma once -#include "srsran/asn1/f1ap/f1ap_ies.h" -#include "srsran/asn1/f1ap/f1ap_pdu_contents_ue.h" #include "srsran/cu_cp/cu_cp_types.h" #include "srsran/f1ap/common/f1ap_ue_id.h" #include "srsran/ran/cause.h" diff --git a/tests/unittests/f1ap/common/f1ap_cu_test_messages.h b/tests/unittests/f1ap/common/f1ap_cu_test_messages.h index 27fbcbe6b7..6e77bbdc8e 100644 --- a/tests/unittests/f1ap/common/f1ap_cu_test_messages.h +++ b/tests/unittests/f1ap/common/f1ap_cu_test_messages.h @@ -12,6 +12,7 @@ #include "srsran/f1ap/common/f1ap_ue_id.h" #include "srsran/f1ap/cu_cp/f1ap_cu.h" +#include "srsran/asn1/f1ap/f1ap_ies.h" #include "srsran/ran/rnti.h" namespace srsran { From cb6d67aad8eaacf84250ab8d1528fea02276cfdd Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 5 Jan 2024 19:14:21 +0100 Subject: [PATCH 066/134] ngap: remove asn1 from the ngap public interface --- include/srsran/ngap/ngap.h | 6 +---- include/srsran/ngap/ngap_message.h | 24 +++++++++++++++++++ lib/ngap/ngap_asn1_packer.cpp | 6 ++--- lib/ngap/ngap_asn1_packer.h | 4 ++++ lib/ngap/procedures/ng_setup_procedure.h | 1 + ...ngap_dl_nas_message_transfer_procedure.cpp | 1 + .../ngap_handover_preparation_procedure.cpp | 1 + ...handover_resource_allocation_procedure.cpp | 1 + .../ngap_initial_context_setup_procedure.cpp | 1 + ..._pdu_session_resource_modify_procedure.cpp | 1 + ...pdu_session_resource_release_procedure.cpp | 1 + ...p_pdu_session_resource_setup_procedure.cpp | 1 + .../ngap_ue_context_release_procedure.cpp | 1 + .../f1ap/common/f1ap_cu_test_messages.h | 2 +- .../unittests/ngap/ngap_asn1_packer_test.cpp | 13 +++++----- tests/unittests/ngap/ngap_test_messages.cpp | 1 + tests/unittests/ngap/ngap_test_messages.h | 1 + tests/unittests/ngap/test_helpers.h | 1 + 18 files changed, 52 insertions(+), 15 deletions(-) create mode 100644 include/srsran/ngap/ngap_message.h diff --git a/include/srsran/ngap/ngap.h b/include/srsran/ngap/ngap.h index 5b7df6b468..5eaa4606a3 100644 --- a/include/srsran/ngap/ngap.h +++ b/include/srsran/ngap/ngap.h @@ -10,7 +10,6 @@ #pragma once -#include "srsran/asn1/ngap/ngap.h" #include "srsran/cu_cp/cu_cp_types.h" #include "srsran/ngap/ngap_handover.h" #include "srsran/ngap/ngap_setup.h" @@ -18,12 +17,9 @@ #include "srsran/support/timers.h" namespace srsran { - namespace srs_cu_cp { -struct ngap_message { - asn1::ngap::ngap_pdu_c pdu; -}; +struct ngap_message; /// This interface is used to push NGAP messages to the NGAP interface. class ngap_message_handler diff --git a/include/srsran/ngap/ngap_message.h b/include/srsran/ngap/ngap_message.h new file mode 100644 index 0000000000..cbee52569d --- /dev/null +++ b/include/srsran/ngap/ngap_message.h @@ -0,0 +1,24 @@ +/* + * + * 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/asn1/ngap/ngap.h" + +namespace srsran { +namespace srs_cu_cp { + +/// \brief NGAP PDU sent and received from the AMF. +struct ngap_message { + asn1::ngap::ngap_pdu_c pdu; +}; + +} // namespace srs_cu_cp +} // namespace srsran \ No newline at end of file diff --git a/lib/ngap/ngap_asn1_packer.cpp b/lib/ngap/ngap_asn1_packer.cpp index a2fd9853db..ab19e9380a 100644 --- a/lib/ngap/ngap_asn1_packer.cpp +++ b/lib/ngap/ngap_asn1_packer.cpp @@ -9,8 +9,10 @@ */ #include "ngap_asn1_packer.h" +#include "srsran/ngap/ngap_message.h" -namespace srsran { +using namespace srsran; +using namespace srs_cu_cp; ngap_asn1_packer::ngap_asn1_packer(sctp_network_gateway_data_handler& gw_, ngap_message_handler& ngap_handler, @@ -58,5 +60,3 @@ void ngap_asn1_packer::handle_message(const srs_cu_cp::ngap_message& msg) } gw.handle_pdu(tx_pdu); } - -} // namespace srsran diff --git a/lib/ngap/ngap_asn1_packer.h b/lib/ngap/ngap_asn1_packer.h index 699f640f70..67d793cce2 100644 --- a/lib/ngap/ngap_asn1_packer.h +++ b/lib/ngap/ngap_asn1_packer.h @@ -18,6 +18,9 @@ #include namespace srsran { +namespace srs_cu_cp { + +struct ngap_message; class ngap_asn1_packer : public srs_cu_cp::ngap_message_handler { @@ -35,4 +38,5 @@ class ngap_asn1_packer : public srs_cu_cp::ngap_message_handler dlt_pcap& pcap; }; +} // namespace srs_cu_cp } // namespace srsran diff --git a/lib/ngap/procedures/ng_setup_procedure.h b/lib/ngap/procedures/ng_setup_procedure.h index 69e38a25a7..ab1a36d215 100644 --- a/lib/ngap/procedures/ng_setup_procedure.h +++ b/lib/ngap/procedures/ng_setup_procedure.h @@ -13,6 +13,7 @@ #include "../ngap_context.h" #include "ngap_transaction_manager.h" #include "srsran/ngap/ngap.h" +#include "srsran/ngap/ngap_message.h" #include "srsran/support/async/async_task.h" namespace srsran { diff --git a/lib/ngap/procedures/ngap_dl_nas_message_transfer_procedure.cpp b/lib/ngap/procedures/ngap_dl_nas_message_transfer_procedure.cpp index 44efc074c1..55ee0d8728 100644 --- a/lib/ngap/procedures/ngap_dl_nas_message_transfer_procedure.cpp +++ b/lib/ngap/procedures/ngap_dl_nas_message_transfer_procedure.cpp @@ -9,6 +9,7 @@ */ #include "ngap_dl_nas_message_transfer_procedure.h" +#include "srsran/ngap/ngap_message.h" using namespace srsran; using namespace srsran::srs_cu_cp; diff --git a/lib/ngap/procedures/ngap_handover_preparation_procedure.cpp b/lib/ngap/procedures/ngap_handover_preparation_procedure.cpp index 211baae216..79d164747f 100644 --- a/lib/ngap/procedures/ngap_handover_preparation_procedure.cpp +++ b/lib/ngap/procedures/ngap_handover_preparation_procedure.cpp @@ -9,6 +9,7 @@ */ #include "ngap_handover_preparation_procedure.h" +#include "srsran/ngap/ngap_message.h" #include "srsran/ran/bcd_helpers.h" using namespace srsran; diff --git a/lib/ngap/procedures/ngap_handover_resource_allocation_procedure.cpp b/lib/ngap/procedures/ngap_handover_resource_allocation_procedure.cpp index 6a824efb04..eba7f8fb13 100644 --- a/lib/ngap/procedures/ngap_handover_resource_allocation_procedure.cpp +++ b/lib/ngap/procedures/ngap_handover_resource_allocation_procedure.cpp @@ -10,6 +10,7 @@ #include "ngap_handover_resource_allocation_procedure.h" #include "../ngap_asn1_helpers.h" +#include "srsran/ngap/ngap_message.h" using namespace srsran; using namespace srsran::srs_cu_cp; diff --git a/lib/ngap/procedures/ngap_initial_context_setup_procedure.cpp b/lib/ngap/procedures/ngap_initial_context_setup_procedure.cpp index 506c38a4cd..ae4a867b49 100644 --- a/lib/ngap/procedures/ngap_initial_context_setup_procedure.cpp +++ b/lib/ngap/procedures/ngap_initial_context_setup_procedure.cpp @@ -12,6 +12,7 @@ #include "../ngap_asn1_helpers.h" #include "ngap_procedure_helpers.h" #include "srsran/ngap/ngap.h" +#include "srsran/ngap/ngap_message.h" #include "srsran/ran/cause.h" using namespace srsran; diff --git a/lib/ngap/procedures/ngap_pdu_session_resource_modify_procedure.cpp b/lib/ngap/procedures/ngap_pdu_session_resource_modify_procedure.cpp index f0ed89e752..e64224119a 100644 --- a/lib/ngap/procedures/ngap_pdu_session_resource_modify_procedure.cpp +++ b/lib/ngap/procedures/ngap_pdu_session_resource_modify_procedure.cpp @@ -10,6 +10,7 @@ #include "ngap_pdu_session_resource_modify_procedure.h" #include "../ngap/ngap_asn1_helpers.h" +#include "srsran/ngap/ngap_message.h" using namespace srsran; using namespace srsran::srs_cu_cp; diff --git a/lib/ngap/procedures/ngap_pdu_session_resource_release_procedure.cpp b/lib/ngap/procedures/ngap_pdu_session_resource_release_procedure.cpp index c19f70561f..2cf54350d5 100644 --- a/lib/ngap/procedures/ngap_pdu_session_resource_release_procedure.cpp +++ b/lib/ngap/procedures/ngap_pdu_session_resource_release_procedure.cpp @@ -10,6 +10,7 @@ #include "ngap_pdu_session_resource_release_procedure.h" #include "../ngap/ngap_asn1_helpers.h" +#include "srsran/ngap/ngap_message.h" using namespace srsran; using namespace srsran::srs_cu_cp; diff --git a/lib/ngap/procedures/ngap_pdu_session_resource_setup_procedure.cpp b/lib/ngap/procedures/ngap_pdu_session_resource_setup_procedure.cpp index 0e48edefb8..fbb1111c9c 100644 --- a/lib/ngap/procedures/ngap_pdu_session_resource_setup_procedure.cpp +++ b/lib/ngap/procedures/ngap_pdu_session_resource_setup_procedure.cpp @@ -12,6 +12,7 @@ #include "../ngap/ngap_asn1_helpers.h" #include "ngap_procedure_helpers.h" #include "srsran/ngap/ngap.h" +#include "srsran/ngap/ngap_message.h" using namespace srsran; using namespace srsran::srs_cu_cp; diff --git a/lib/ngap/procedures/ngap_ue_context_release_procedure.cpp b/lib/ngap/procedures/ngap_ue_context_release_procedure.cpp index b60e4e0892..26e6e32b8c 100644 --- a/lib/ngap/procedures/ngap_ue_context_release_procedure.cpp +++ b/lib/ngap/procedures/ngap_ue_context_release_procedure.cpp @@ -10,6 +10,7 @@ #include "ngap_ue_context_release_procedure.h" #include "../ngap/ngap_asn1_helpers.h" +#include "srsran/ngap/ngap_message.h" using namespace srsran; using namespace srsran::srs_cu_cp; diff --git a/tests/unittests/f1ap/common/f1ap_cu_test_messages.h b/tests/unittests/f1ap/common/f1ap_cu_test_messages.h index 6e77bbdc8e..f7f6ec3e08 100644 --- a/tests/unittests/f1ap/common/f1ap_cu_test_messages.h +++ b/tests/unittests/f1ap/common/f1ap_cu_test_messages.h @@ -10,9 +10,9 @@ #pragma once +#include "srsran/asn1/f1ap/f1ap_ies.h" #include "srsran/f1ap/common/f1ap_ue_id.h" #include "srsran/f1ap/cu_cp/f1ap_cu.h" -#include "srsran/asn1/f1ap/f1ap_ies.h" #include "srsran/ran/rnti.h" namespace srsran { diff --git a/tests/unittests/ngap/ngap_asn1_packer_test.cpp b/tests/unittests/ngap/ngap_asn1_packer_test.cpp index 3c7a4fb879..e07e210199 100644 --- a/tests/unittests/ngap/ngap_asn1_packer_test.cpp +++ b/tests/unittests/ngap/ngap_asn1_packer_test.cpp @@ -14,6 +14,7 @@ #include "ngap_test_messages.h" #include "test_helpers.h" #include "tests/unittests/gateways/test_helpers.h" +#include "srsran/ngap/ngap_message.h" #include using namespace srsran; @@ -41,7 +42,7 @@ class ngap_asn1_packer_test : public ::testing::Test gw = std::make_unique(); ngap = std::make_unique(); - packer = std::make_unique(*gw, *ngap, pcap); + packer = std::make_unique(*gw, *ngap, pcap); } void TearDown() override @@ -50,11 +51,11 @@ class ngap_asn1_packer_test : public ::testing::Test srslog::flush(); } - std::unique_ptr gw; - std::unique_ptr ngap; - std::unique_ptr packer; - srslog::basic_logger& test_logger = srslog::fetch_basic_logger("TEST"); - null_dlt_pcap pcap; + std::unique_ptr gw; + std::unique_ptr ngap; + std::unique_ptr packer; + srslog::basic_logger& test_logger = srslog::fetch_basic_logger("TEST"); + null_dlt_pcap pcap; }; /// Test successful packing and compare with captured test vector diff --git a/tests/unittests/ngap/ngap_test_messages.cpp b/tests/unittests/ngap/ngap_test_messages.cpp index 62c1442ada..d6ea3b6e31 100644 --- a/tests/unittests/ngap/ngap_test_messages.cpp +++ b/tests/unittests/ngap/ngap_test_messages.cpp @@ -12,6 +12,7 @@ #include "lib/ngap/ngap_asn1_converters.h" #include "srsran/asn1/ngap/common.h" #include "srsran/asn1/ngap/ngap_ies.h" +#include "srsran/ngap/ngap_message.h" #include "srsran/ngap/ngap_types.h" #include "srsran/ran/cu_types.h" diff --git a/tests/unittests/ngap/ngap_test_messages.h b/tests/unittests/ngap/ngap_test_messages.h index 520786ff11..bf40150181 100644 --- a/tests/unittests/ngap/ngap_test_messages.h +++ b/tests/unittests/ngap/ngap_test_messages.h @@ -10,6 +10,7 @@ #pragma once +#include "srsran/asn1/ngap/ngap_ies.h" #include "srsran/cu_cp/cu_cp_types.h" #include "srsran/ngap/ngap.h" #include "srsran/ngap/ngap_types.h" diff --git a/tests/unittests/ngap/test_helpers.h b/tests/unittests/ngap/test_helpers.h index 304bbf5c75..fa8e0a9424 100644 --- a/tests/unittests/ngap/test_helpers.h +++ b/tests/unittests/ngap/test_helpers.h @@ -13,6 +13,7 @@ #include "ngap_test_messages.h" #include "srsran/adt/byte_buffer.h" #include "srsran/cu_cp/cu_cp_types.h" +#include "srsran/ngap/ngap_message.h" #include "srsran/pcap/dlt_pcap.h" #include "srsran/rrc/rrc_ue.h" #include "srsran/security/security.h" From 0117d151c6edcdf854d6fc01c130b8eaf55e57b7 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Fri, 5 Jan 2024 19:30:34 +0100 Subject: [PATCH 067/134] sched: reset uci allocator cache in the cell_scheduler Signed-off-by: Carlo Galiotto --- lib/scheduler/cell_scheduler.cpp | 2 ++ lib/scheduler/uci_scheduling/uci_scheduler_impl.cpp | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/scheduler/cell_scheduler.cpp b/lib/scheduler/cell_scheduler.cpp index 92cf453612..11f5470418 100644 --- a/lib/scheduler/cell_scheduler.cpp +++ b/lib/scheduler/cell_scheduler.cpp @@ -80,6 +80,7 @@ void cell_scheduler::run_slot(slot_point sl_tx) res_grid.slot_indication(skipped_slot); pdcch_sch.slot_indication(skipped_slot); pucch_alloc.slot_indication(skipped_slot); + uci_alloc.slot_indication(skipped_slot); } } @@ -87,6 +88,7 @@ void cell_scheduler::run_slot(slot_point sl_tx) res_grid.slot_indication(sl_tx); pdcch_sch.slot_indication(sl_tx); pucch_alloc.slot_indication(sl_tx); + uci_alloc.slot_indication(sl_tx); // > Mark slot start for logging purposes. result_logger.on_slot_start(); diff --git a/lib/scheduler/uci_scheduling/uci_scheduler_impl.cpp b/lib/scheduler/uci_scheduling/uci_scheduler_impl.cpp index 71ad9e19d8..717a32e79b 100644 --- a/lib/scheduler/uci_scheduling/uci_scheduler_impl.cpp +++ b/lib/scheduler/uci_scheduling/uci_scheduler_impl.cpp @@ -27,9 +27,6 @@ uci_scheduler_impl::~uci_scheduler_impl() = default; void uci_scheduler_impl::run_slot(cell_resource_allocator& cell_alloc, slot_point sl_tx) { - // Reset the UCI allocator counter of the allocated PDSCHs to be acknowledged per slot. - uci_alloc.slot_indication(sl_tx); - for (auto& user : ues) { // At this point, we assume the config validator ensures there is pCell. auto& ue_cell = user->get_pcell(); From 932f927cbccfc6f70ba962667149ae5b76260126 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 8 Jan 2024 13:13:14 +0100 Subject: [PATCH 068/134] phy: fix downlink processor concurrency phy: apply code review --- apps/examples/du/phy_factory.cpp | 5 +- apps/gnb/gnb_du_factory.cpp | 1 + .../channel_processor_factories.h | 12 +- .../signal_processor_factories.h | 6 +- .../srsran/phy/upper/upper_phy_factories.h | 2 + .../channel_processor_factories.cpp | 112 ++++++++++++++++++ .../channel_processors/pdcch_processor_pool.h | 45 +++++++ .../channel_processors/ssb_processor_pool.h | 44 +++++++ .../nzp_csi_rs_generator_pool.h | 45 +++++++ .../signal_processor_factories.cpp | 60 ++++++++++ lib/phy/upper/upper_phy_factories.cpp | 28 ++++- 11 files changed, 351 insertions(+), 9 deletions(-) create mode 100644 lib/phy/upper/channel_processors/pdcch_processor_pool.h create mode 100644 lib/phy/upper/channel_processors/ssb_processor_pool.h create mode 100644 lib/phy/upper/signal_processors/nzp_csi_rs_generator_pool.h diff --git a/apps/examples/du/phy_factory.cpp b/apps/examples/du/phy_factory.cpp index 4e9cf9cd00..8b819326dd 100644 --- a/apps/examples/du/phy_factory.cpp +++ b/apps/examples/du/phy_factory.cpp @@ -21,8 +21,9 @@ std::unique_ptr srsran::create_upper_phy(const upper_phy_params& upper_phy_rx_symbol_request_notifier* rx_symbol_request_notifier) { downlink_processor_factory_sw_config dl_proc_config; - dl_proc_config.ldpc_encoder_type = "auto"; - dl_proc_config.crc_calculator_type = "auto"; + dl_proc_config.ldpc_encoder_type = "auto"; + dl_proc_config.crc_calculator_type = "auto"; + dl_proc_config.nof_concurrent_threads = 1; // Create downlink processor factory. std::shared_ptr dl_proc_factory = create_downlink_processor_factory_sw(dl_proc_config); diff --git a/apps/gnb/gnb_du_factory.cpp b/apps/gnb/gnb_du_factory.cpp index b6b5f011f6..de741dc2d6 100644 --- a/apps/gnb/gnb_du_factory.cpp +++ b/apps/gnb/gnb_du_factory.cpp @@ -54,6 +54,7 @@ static du_low_configuration create_du_low_config(const gnb_appconfig& } else { srsran_assert(false, "Invalid PDSCH processor type {}.", upper_phy_threads_cfg.pdsch_processor_type); } + du_lo_cfg.dl_proc_cfg.nof_concurrent_threads = params.expert_execution_cfg.threads.upper_threads.nof_dl_threads; du_lo_cfg.upper_phy = generate_du_low_config(params); 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 f61c8d003d..f3c1167ced 100644 --- a/include/srsran/phy/upper/channel_processors/channel_processor_factories.h +++ b/include/srsran/phy/upper/channel_processors/channel_processor_factories.h @@ -89,7 +89,7 @@ class pdcch_processor_factory virtual ~pdcch_processor_factory() = default; virtual std::unique_ptr create() = 0; virtual std::unique_ptr create_validator() = 0; - std::unique_ptr create(srslog::basic_logger& logger, bool enable_logging_broadcast); + virtual std::unique_ptr create(srslog::basic_logger& logger, bool enable_logging_broadcast); }; std::shared_ptr @@ -97,6 +97,10 @@ create_pdcch_processor_factory_sw(std::shared_ptr std::shared_ptr modulator_factory, std::shared_ptr dmrs_factory); +std::shared_ptr +create_pdcch_processor_pool_factory(std::shared_ptr processor_factory, + unsigned nof_concurrent_threads); + class pdsch_encoder_factory { public: @@ -239,7 +243,7 @@ class ssb_processor_factory virtual ~ssb_processor_factory() = default; virtual std::unique_ptr create() = 0; virtual std::unique_ptr create_validator() = 0; - std::unique_ptr create(srslog::basic_logger& logger); + virtual std::unique_ptr create(srslog::basic_logger& logger); }; struct ssb_processor_factory_sw_configuration { @@ -252,4 +256,8 @@ struct ssb_processor_factory_sw_configuration { std::shared_ptr create_ssb_processor_factory_sw(ssb_processor_factory_sw_configuration& config); +std::shared_ptr +create_ssb_processor_pool_factory(std::shared_ptr processor_factory, + unsigned nof_concurrent_threads); + } // 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 d2cc6dccdb..15be73c9cb 100644 --- a/include/srsran/phy/upper/signal_processors/signal_processor_factories.h +++ b/include/srsran/phy/upper/signal_processors/signal_processor_factories.h @@ -77,12 +77,16 @@ class nzp_csi_rs_generator_factory virtual ~nzp_csi_rs_generator_factory() = default; virtual std::unique_ptr create() = 0; virtual std::unique_ptr create_validator() = 0; - std::unique_ptr create(srslog::basic_logger& logger); + virtual std::unique_ptr create(srslog::basic_logger& logger); }; std::shared_ptr create_nzp_csi_rs_generator_factory_sw(std::shared_ptr prg_factory); +std::shared_ptr +create_nzp_csi_rs_generator_pool_factory(std::shared_ptr generator_factory, + unsigned nof_concurrent_threads); + class port_channel_estimator_factory { public: diff --git a/include/srsran/phy/upper/upper_phy_factories.h b/include/srsran/phy/upper/upper_phy_factories.h index f09581e237..f222818f98 100644 --- a/include/srsran/phy/upper/upper_phy_factories.h +++ b/include/srsran/phy/upper/upper_phy_factories.h @@ -164,6 +164,8 @@ struct downlink_processor_factory_sw_config { pdsch_processor_concurrent_configuration, pdsch_processor_lite_configuration> pdsch_processor; + /// Number of concurrent threads processing downlink transmissions. + unsigned nof_concurrent_threads; }; /// Creates a full software based downlink processor factory. diff --git a/lib/phy/upper/channel_processors/channel_processor_factories.cpp b/lib/phy/upper/channel_processors/channel_processor_factories.cpp index 48592cbb71..d1ef7f46eb 100644 --- a/lib/phy/upper/channel_processors/channel_processor_factories.cpp +++ b/lib/phy/upper/channel_processors/channel_processor_factories.cpp @@ -14,6 +14,7 @@ #include "pdcch_encoder_impl.h" #include "pdcch_modulator_impl.h" #include "pdcch_processor_impl.h" +#include "pdcch_processor_pool.h" #include "pdsch_encoder_impl.h" #include "pdsch_modulator_impl.h" #include "pdsch_processor_concurrent_impl.h" @@ -29,6 +30,7 @@ #include "pucch_processor_impl.h" #include "pucch_processor_pool.h" #include "ssb_processor_impl.h" +#include "ssb_processor_pool.h" #include "srsran/phy/support/support_formatters.h" #include "srsran/phy/upper/channel_modulation/channel_modulation_factories.h" #include "srsran/phy/upper/sequence_generators/sequence_generator_factories.h" @@ -172,6 +174,54 @@ class pdcch_processor_factory_sw : public pdcch_processor_factory } }; +class pdcch_processor_pool_factory : public pdcch_processor_factory +{ +public: + pdcch_processor_pool_factory(std::shared_ptr factory_, unsigned nof_concurrent_threads_) : + factory(std::move(factory_)), nof_concurrent_threads(nof_concurrent_threads_) + { + srsran_assert(factory, "Invalid PDCCH processor factory."); + srsran_assert(nof_concurrent_threads > 1, "Number of concurrent threads must be greater than one."); + } + + std::unique_ptr create() override + { + if (!processors) { + std::vector> procs(nof_concurrent_threads); + + for (auto& processor : procs) { + processor = factory->create(); + } + + processors = std::make_shared(std::move(procs)); + } + + return std::make_unique(std::move(processors)); + } + + std::unique_ptr create(srslog::basic_logger& logger, bool enable_logging_broadcast) override + { + if (!processors) { + std::vector> procs(nof_concurrent_threads); + + for (auto& processor : procs) { + processor = factory->create(logger, enable_logging_broadcast); + } + + processors = std::make_shared(std::move(procs)); + } + + return std::make_unique(std::move(processors)); + } + + std::unique_ptr create_validator() override { return factory->create_validator(); } + +private: + std::shared_ptr factory; + unsigned nof_concurrent_threads; + std::shared_ptr processors; +}; + class pdsch_encoder_factory_sw : public pdsch_encoder_factory { private: @@ -668,6 +718,54 @@ class ssb_processor_factory_sw : public ssb_processor_factory std::shared_ptr sss_factory; }; +class ssb_processor_pool_factory : public ssb_processor_factory +{ +public: + ssb_processor_pool_factory(std::shared_ptr factory_, unsigned nof_concurrent_threads_) : + factory(std::move(factory_)), nof_concurrent_threads(nof_concurrent_threads_) + { + srsran_assert(factory, "Invalid SSB processor factory."); + srsran_assert(nof_concurrent_threads > 1, "Number of concurrent threads must be greater than one."); + } + + std::unique_ptr create() override + { + if (!processors) { + std::vector> instances(nof_concurrent_threads); + + for (auto& processor : instances) { + processor = factory->create(); + } + + processors = std::make_shared(std::move(instances)); + } + + return std::make_unique(std::move(processors)); + } + + std::unique_ptr create(srslog::basic_logger& logger) override + { + if (!processors) { + std::vector> instances(nof_concurrent_threads); + + for (auto& processor : instances) { + processor = factory->create(logger); + } + + processors = std::make_shared(std::move(instances)); + } + + return std::make_unique(std::move(processors)); + } + + std::unique_ptr create_validator() override { return factory->create_validator(); } + +private: + std::shared_ptr factory; + unsigned nof_concurrent_threads; + std::shared_ptr processors; +}; + class pucch_demodulator_factory_sw : public pucch_demodulator_factory { public: @@ -736,6 +834,13 @@ srsran::create_pdcch_processor_factory_sw(std::shared_ptr std::move(encoder_factory), std::move(modulator_factory), std::move(dmrs_factory)); } +std::shared_ptr +srsran::create_pdcch_processor_pool_factory(std::shared_ptr processor_factory, + unsigned nof_concurrent_threads) +{ + return std::make_shared(processor_factory, nof_concurrent_threads); +} + std::shared_ptr srsran::create_pdsch_encoder_factory_sw(pdsch_encoder_factory_sw_configuration& config) { @@ -862,6 +967,13 @@ srsran::create_ssb_processor_factory_sw(ssb_processor_factory_sw_configuration& return std::make_shared(config); } +std::shared_ptr +srsran::create_ssb_processor_pool_factory(std::shared_ptr processor_factory, + unsigned nof_concurrent_threads) +{ + return std::make_shared(processor_factory, nof_concurrent_threads); +} + template static std::chrono::nanoseconds time_execution(Func&& func) { diff --git a/lib/phy/upper/channel_processors/pdcch_processor_pool.h b/lib/phy/upper/channel_processors/pdcch_processor_pool.h new file mode 100644 index 0000000000..2abf1b7bf3 --- /dev/null +++ b/lib/phy/upper/channel_processors/pdcch_processor_pool.h @@ -0,0 +1,45 @@ +/* + * + * 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/upper/channel_processors/pdcch_processor.h" +#include "srsran/support/memory_pool/concurrent_thread_local_object_pool.h" + +namespace srsran { + +/// \brief Concurrent PDCCH processor pool. +/// +/// Wraps a concurrent pool of PDCCH processors. It assigns a PDCCH processor to each thread that processes PDCCH. +class pdcch_processor_pool : public pdcch_processor +{ +public: + /// PDCCH processor pool type. + using pdcch_processor_pool_type = concurrent_thread_local_object_pool; + + /// Creates a PDCCH processor pool from a list of processors. Ownership is transferred to the pool. + explicit pdcch_processor_pool(std::shared_ptr processors_) : + processors(std::move(processors_)) + { + srsran_assert(processors, "Invalid processor pool."); + } + + // See interface for documentation. + void process(resource_grid_mapper& mapper, const pdu_t& pdu) override + { + pdcch_processor& processor = processors->get(); + return processor.process(mapper, pdu); + } + +private: + std::shared_ptr processors; +}; + +} // namespace srsran \ No newline at end of file diff --git a/lib/phy/upper/channel_processors/ssb_processor_pool.h b/lib/phy/upper/channel_processors/ssb_processor_pool.h new file mode 100644 index 0000000000..6a67f59a1b --- /dev/null +++ b/lib/phy/upper/channel_processors/ssb_processor_pool.h @@ -0,0 +1,44 @@ +/* + * + * 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/upper/channel_processors/ssb_processor.h" +#include "srsran/support/memory_pool/concurrent_thread_local_object_pool.h" + +namespace srsran { + +/// \brief Concurrent SSB processor pool. +/// +/// Wraps a concurrent pool of SSB processors. It assigns a SSB processor to each thread that processes SSB. +class ssb_processor_pool : public ssb_processor +{ +public: + /// SSB processor pool type. + using ssb_processor_pool_type = concurrent_thread_local_object_pool; + + /// Creates a SSB processor pool from a list of processors. Ownership is transferred to the pool. + explicit ssb_processor_pool(std::shared_ptr processors_) : processors(std::move(processors_)) + { + srsran_assert(processors, "Invalid processor pool."); + } + + // See interface for documentation. + void process(resource_grid_writer& grid, const pdu_t& pdu) override + { + ssb_processor& processor = processors->get(); + return processor.process(grid, pdu); + } + +private: + std::shared_ptr processors; +}; + +} // namespace srsran \ No newline at end of file diff --git a/lib/phy/upper/signal_processors/nzp_csi_rs_generator_pool.h b/lib/phy/upper/signal_processors/nzp_csi_rs_generator_pool.h new file mode 100644 index 0000000000..f74776ed83 --- /dev/null +++ b/lib/phy/upper/signal_processors/nzp_csi_rs_generator_pool.h @@ -0,0 +1,45 @@ +/* + * + * 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/upper/signal_processors/nzp_csi_rs_generator.h" +#include "srsran/support/memory_pool/concurrent_thread_local_object_pool.h" + +namespace srsran { + +/// \brief Concurrent NZP-CSI-RS generator pool. +/// +/// Wraps a concurrent pool of NZP-CSI-RS generators. It assigns a generator to each thread. +class nzp_csi_rs_generator_pool : public nzp_csi_rs_generator +{ +public: + /// NZP-CSI-RS generator pool type. + using generator_pool_type = concurrent_thread_local_object_pool; + + /// Creates a SSB processor pool from a list of processors. Ownership is transferred to the pool. + explicit nzp_csi_rs_generator_pool(std::shared_ptr processors_) : + processors(std::move(processors_)) + { + srsran_assert(processors, "Invalid processor pool."); + } + + // See interface for documentation. + void map(resource_grid_mapper& mapper, const config_t& config) override + { + nzp_csi_rs_generator& processor = processors->get(); + return processor.map(mapper, config); + } + +private: + std::shared_ptr processors; +}; + +} // namespace srsran \ No newline at end of file diff --git a/lib/phy/upper/signal_processors/signal_processor_factories.cpp b/lib/phy/upper/signal_processors/signal_processor_factories.cpp index f99ef12b78..0a82d489de 100644 --- a/lib/phy/upper/signal_processors/signal_processor_factories.cpp +++ b/lib/phy/upper/signal_processors/signal_processor_factories.cpp @@ -14,6 +14,7 @@ #include "dmrs_pdsch_processor_impl.h" #include "dmrs_pusch_estimator_impl.h" #include "nzp_csi_rs_generator_impl.h" +#include "nzp_csi_rs_generator_pool.h" #include "port_channel_estimator_average_impl.h" #include "pss_processor_impl.h" #include "pucch/dmrs_pucch_processor_format1_impl.h" @@ -167,6 +168,58 @@ class nzp_csi_rs_generator_factory_sw : public nzp_csi_rs_generator_factory std::shared_ptr prg_factory; }; +class nzp_csi_rs_generator_pool_factory : public nzp_csi_rs_generator_factory +{ +public: + nzp_csi_rs_generator_pool_factory(std::shared_ptr factory_, + unsigned nof_concurrent_threads_) : + factory(std::move(factory_)), nof_concurrent_threads(nof_concurrent_threads_) + { + srsran_assert(factory, "Invalid NZP-CSI-RS generator factory."); + srsran_assert(nof_concurrent_threads > 1, "Number of concurrent threads must be greater than one."); + } + + std::unique_ptr create() override + { + if (!generators) { + std::vector> instances(nof_concurrent_threads); + + for (auto& processor : instances) { + processor = factory->create(); + } + + generators = std::make_shared(std::move(instances)); + } + + return std::make_unique(generators); + } + + std::unique_ptr create(srslog::basic_logger& logger) override + { + if (!generators) { + std::vector> instances(nof_concurrent_threads); + + for (auto& processor : instances) { + processor = factory->create(logger); + } + + generators = std::make_shared(std::move(instances)); + } + + return std::make_unique(generators); + } + + std::unique_ptr create_validator() override + { + return factory->create_validator(); + } + +private: + std::shared_ptr factory; + unsigned nof_concurrent_threads; + std::shared_ptr generators; +}; + class port_channel_estimator_factory_sw : public port_channel_estimator_factory { public: @@ -247,6 +300,13 @@ srsran::create_nzp_csi_rs_generator_factory_sw(std::shared_ptr(std::move(prg_factory)); } +std::shared_ptr +srsran::create_nzp_csi_rs_generator_pool_factory(std::shared_ptr generator_factory, + unsigned nof_concurrent_threads) +{ + return std::make_shared(std::move(generator_factory), nof_concurrent_threads); +} + std::shared_ptr srsran::create_port_channel_estimator_factory_sw(std::shared_ptr dft_f) { diff --git a/lib/phy/upper/upper_phy_factories.cpp b/lib/phy/upper/upper_phy_factories.cpp index 590432dc3b..7b056b9120 100644 --- a/lib/phy/upper/upper_phy_factories.cpp +++ b/lib/phy/upper/upper_phy_factories.cpp @@ -692,10 +692,6 @@ srsran::create_downlink_processor_factory_sw(const downlink_processor_factory_sw *pdsch_processor_config.pdsch_codeblock_task_executor, pdsch_processor_config.nof_pdsch_codeblock_threads); report_fatal_error_if_not(pdsch_proc_factory, "Invalid PDSCH processor factory."); - - // Wrap PDSCH processor factory with a pool to allow concurrent execution. - pdsch_proc_factory = - create_pdsch_processor_pool(std::move(pdsch_proc_factory), pdsch_processor_config.max_nof_simultaneous_pdsch); } else if (variant_holds_alternative(config.pdsch_processor)) { pdsch_proc_factory = create_pdsch_lite_processor_factory_sw( ldpc_seg_tx_factory, ldpc_enc_factory, ldpc_rm_factory, prg_factory, mod_factory, dmrs_pdsch_proc_factory); @@ -717,6 +713,30 @@ srsran::create_downlink_processor_factory_sw(const downlink_processor_factory_sw create_nzp_csi_rs_generator_factory_sw(prg_factory); report_fatal_error_if_not(nzp_csi_rs_factory, "Invalid NZP-CSI-RS generator factory."); + // Wrap the downlink processor dependencies with pools to allow concurrent execution. + if (config.nof_concurrent_threads > 1) { + // If the PDSCH instance is concurrent, the number of instances is given by the PDSCH processor configuration. + unsigned max_nof_simultaneous_pdsch = config.nof_concurrent_threads; + if (variant_holds_alternative(config.pdsch_processor)) { + max_nof_simultaneous_pdsch = + variant_get(config.pdsch_processor).max_nof_simultaneous_pdsch; + } + + pdcch_proc_factory = + create_pdcch_processor_pool_factory(std::move(pdcch_proc_factory), config.nof_concurrent_threads); + report_fatal_error_if_not(pdcch_proc_factory, "Invalid PDCCH processor pool factory."); + + pdsch_proc_factory = create_pdsch_processor_pool(std::move(pdsch_proc_factory), max_nof_simultaneous_pdsch); + report_fatal_error_if_not(pdcch_proc_factory, "Invalid PDSCH processor pool factory."); + + ssb_proc_factory = create_ssb_processor_pool_factory(std::move(ssb_proc_factory), config.nof_concurrent_threads); + report_fatal_error_if_not(pdcch_proc_factory, "Invalid SSB processor pool factory."); + + nzp_csi_rs_factory = + create_nzp_csi_rs_generator_pool_factory(std::move(nzp_csi_rs_factory), config.nof_concurrent_threads); + report_fatal_error_if_not(pdcch_proc_factory, "Invalid NZP-CSI-RS generator pool factory."); + } + return std::make_shared( pdcch_proc_factory, pdsch_proc_factory, ssb_proc_factory, nzp_csi_rs_factory); } From 689b7b1df103c2ceecaab993f48d2dc4cf4cb126 Mon Sep 17 00:00:00 2001 From: qarlosalberto Date: Mon, 8 Jan 2024 16:57:46 +0100 Subject: [PATCH 069/134] ci: enable viavi tests in nightly --- .gitlab/ci/e2e.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.gitlab/ci/e2e.yml b/.gitlab/ci/e2e.yml index 5a55b76bfd..3229fa6efb 100644 --- a/.gitlab/ci/e2e.yml +++ b/.gitlab/ci/e2e.yml @@ -362,10 +362,8 @@ viavi: extends: .e2e-run rules: - if: $CI_DESCRIPTION =~ /Nightly/ - when: manual - allow_failure: true - # when: delayed - # start_in: 7 hours + when: delayed + start_in: 5 hours variables: GROUP: "viavi" TESTBED: "viavi" From 31a02c89de4a90aa248a49e5278e1260388159a0 Mon Sep 17 00:00:00 2001 From: Alejandro Leal Date: Mon, 8 Jan 2024 16:11:37 +0100 Subject: [PATCH 070/134] fapi_adator: minor refactor in the FAPI-PHY adaptor by removing the handle new slot method in the controller manager --- .../phy/fapi_to_phy_translator.cpp | 27 +++------------ lib/fapi_adaptor/phy/fapi_to_phy_translator.h | 14 +++++--- .../phy/fapi_to_phy_translator_test.cpp | 33 ------------------- 3 files changed, 14 insertions(+), 60 deletions(-) diff --git a/lib/fapi_adaptor/phy/fapi_to_phy_translator.cpp b/lib/fapi_adaptor/phy/fapi_to_phy_translator.cpp index 707c9b6474..29c02d9b75 100644 --- a/lib/fapi_adaptor/phy/fapi_to_phy_translator.cpp +++ b/lib/fapi_adaptor/phy/fapi_to_phy_translator.cpp @@ -307,7 +307,7 @@ void fapi_to_phy_translator::dl_tti_request(const fapi::dl_tti_request_message& } // Create controller for the current slot. - slot_based_upper_phy_controller& controller = slot_controller_mngr.adquire_controller(slot); + slot_based_upper_phy_controller& controller = slot_controller_mngr.acquire_controller(slot); // Translate the downlink PDUs. expected pdus = translate_dl_tti_pdus_to_phy_pdus( @@ -651,11 +651,7 @@ void fapi_to_phy_translator::handle_new_slot(slot_point slot) { trace_point tp = l1_tracer.now(); - // Update the atomic variable that holds the slot point. - current_slot_count_val.store(slot.system_slot(), std::memory_order_release); - - // Release old controllers. - slot_controller_mngr.handle_new_slot(slot); + update_current_slot(slot); // Enqueue soft buffer run slot. if (!asynchronous_executor.execute([this, slot]() { buffer_pool.run_slot(slot); })) { @@ -684,20 +680,13 @@ fapi_to_phy_translator::slot_based_upper_phy_controller_manager::get_controller( return controller(slot); } -void fapi_to_phy_translator::slot_based_upper_phy_controller_manager::handle_new_slot(slot_point slot) -{ - // Release the oldest controller. - slot_point oldest_slot = slot - int(controllers.size() - 1); - controller(oldest_slot) = slot_based_upper_phy_controller(); -} - void fapi_to_phy_translator::slot_based_upper_phy_controller_manager::release_controller(slot_point slot) { controller(slot) = slot_based_upper_phy_controller(); } fapi_to_phy_translator::slot_based_upper_phy_controller& -fapi_to_phy_translator::slot_based_upper_phy_controller_manager::adquire_controller(slot_point slot) +fapi_to_phy_translator::slot_based_upper_phy_controller_manager::acquire_controller(slot_point slot) { controller(slot) = slot_based_upper_phy_controller(dl_processor_pool, rg_pool, slot, sector_id); @@ -712,13 +701,7 @@ fapi_to_phy_translator::slot_based_upper_phy_controller_manager::slot_based_uppe dl_processor_pool(dl_processor_pool_), rg_pool(rg_pool_), sector_id(sector_id_), - // The manager should be able to manage the current slot plus the requests headroom size. Also, as it should clean the - // oldest slot when a new SLOT.indication is received, it should have two extra positions for these oldest slots. - // Adding two extra positions makes that if a new SLOT.indication arrives in the middle of a valid processing PDU, the - // controller for that slot will not be released in the middle of processing the messages. - // NOTE: if we can ensure that no messages will be lost, we can remove this extra positions in the manager, as it - // would not be required to release controllers when the slot changes, Also, this would be valid when the time when a - // controller is released does not matter for incomplete/lost messages. - controllers(nof_slots_request_headroom + 3U) + // The manager should be able to manage the current slot plus the requests headroom size. + controllers(nof_slots_request_headroom + 1U) { } diff --git a/lib/fapi_adaptor/phy/fapi_to_phy_translator.h b/lib/fapi_adaptor/phy/fapi_to_phy_translator.h index 59da77bf93..9eb2e3e9b5 100644 --- a/lib/fapi_adaptor/phy/fapi_to_phy_translator.h +++ b/lib/fapi_adaptor/phy/fapi_to_phy_translator.h @@ -18,7 +18,7 @@ #include "srsran/phy/upper/channel_processors/pdsch_processor.h" #include "srsran/phy/upper/tx_buffer_pool.h" #include "srsran/support/executors/task_executor.h" -#include +#include namespace srsran { @@ -154,16 +154,13 @@ class fapi_to_phy_translator : public fapi::slot_message_gateway unsigned nof_slots_request_headroom); /// Acquires and returns the controller for the given slot. - slot_based_upper_phy_controller& adquire_controller(slot_point slot); + slot_based_upper_phy_controller& acquire_controller(slot_point slot); /// \brief Releases the controller for the given slot. /// /// If the controller has already been released, this function does nothing. void release_controller(slot_point slot); - /// Handles a new slot. - void handle_new_slot(slot_point slot); - /// Returns the controller for the given slot. slot_based_upper_phy_controller& get_controller(slot_point slot); }; @@ -237,6 +234,13 @@ class fapi_to_phy_translator : public fapi::slot_message_gateway return slot_point(scs, current_slot_count_val.load(std::memory_order_acquire)); } + /// Updates this adaptor current slot to the given value. + void update_current_slot(slot_point slot) + { + // Update the atomic variable that holds the slot point. + current_slot_count_val.store(slot.system_slot(), std::memory_order_release); + } + private: /// Sector identifier. const unsigned sector_id; diff --git a/tests/unittests/fapi_adaptor/phy/fapi_to_phy_translator_test.cpp b/tests/unittests/fapi_adaptor/phy/fapi_to_phy_translator_test.cpp index 53568c69cb..404283121f 100644 --- a/tests/unittests/fapi_adaptor/phy/fapi_to_phy_translator_test.cpp +++ b/tests/unittests/fapi_adaptor/phy/fapi_to_phy_translator_test.cpp @@ -351,36 +351,3 @@ TEST_F(fapi_to_phy_translator_fixture, message_received_is_sended_when_a_message ASSERT_TRUE(dl_processor_pool.processor(slot).has_finish_processing_pdus_method_been_called()); ASSERT_FALSE(error_notifier_spy.has_on_error_indication_been_called()); } - -TEST_F(fapi_to_phy_translator_fixture, message_received_is_sended_when_the_current_slot_is_bigger_than_the_allowed) -{ - ASSERT_FALSE(dl_processor_pool.processor(slot).has_configure_resource_grid_method_been_called()); - ASSERT_FALSE(grid.has_set_all_zero_method_been_called()); - - fapi::dl_tti_request_message msg; - msg.sfn = slot.sfn(); - msg.slot = slot.slot_index(); - msg.is_last_message_in_slot = false; - - // Send a DL_TTI.request. - translator.dl_tti_request(msg); - - // Assert that the downlink processor is configured. - ASSERT_TRUE(dl_processor_pool.processor(slot).has_configure_resource_grid_method_been_called()); - // Assert that the resource grid has NOT been set to zero. - ASSERT_FALSE(grid.has_set_all_zero_method_been_called()); - - // The manager headroom size is the number of headroom in slots plus 3. - unsigned manager_headroom_size = headroom_in_slots + 3U; - // Increase the slots. - for (unsigned i = 1; i != (manager_headroom_size - 1U); ++i) { - translator.handle_new_slot(slot + i); - ASSERT_FALSE(dl_processor_pool.processor(slot).has_finish_processing_pdus_method_been_called()); - } - - translator.handle_new_slot(slot + (manager_headroom_size - 1U)); - - // Assert that the finish processing PDUs method of the previous slot downlink_processor has been called. - ASSERT_TRUE(dl_processor_pool.processor(slot).has_finish_processing_pdus_method_been_called()); - ASSERT_FALSE(error_notifier_spy.has_on_error_indication_been_called()); -} From 0d47566d8f06f46bef03f7196b9c50283dcd9306 Mon Sep 17 00:00:00 2001 From: Alejandro Leal Date: Thu, 21 Dec 2023 17:49:16 +0100 Subject: [PATCH 071/134] fapi_adaptor: added missing fields when the MAC PDUs are created in the tests --- tests/unittests/fapi/validators/helpers.cpp | 3 +- .../mac/messages/dl_pdsch_pdu_test.cpp | 20 ++++++++- .../fapi_adaptor/mac/messages/helpers.cpp | 44 ++++++++++++++++--- .../phy/fapi_to_phy_translator_test.cpp | 36 +++++++-------- 4 files changed, 73 insertions(+), 30 deletions(-) diff --git a/tests/unittests/fapi/validators/helpers.cpp b/tests/unittests/fapi/validators/helpers.cpp index 56991649ac..1b2b531957 100644 --- a/tests/unittests/fapi/validators/helpers.cpp +++ b/tests/unittests/fapi/validators/helpers.cpp @@ -1190,8 +1190,7 @@ tx_data_request_message unittest::build_valid_tx_data_request() pdu.pdu_index = 4231; pdu.tlv_custom.length = units::bytes{12}; - static uint8_t payload; - pdu.tlv_custom.payload = &payload; + pdu.tlv_custom.payload = &msg.padding[0]; return msg; } diff --git a/tests/unittests/fapi_adaptor/mac/messages/dl_pdsch_pdu_test.cpp b/tests/unittests/fapi_adaptor/mac/messages/dl_pdsch_pdu_test.cpp index 57cfafe676..b54bdf1893 100644 --- a/tests/unittests/fapi_adaptor/mac/messages/dl_pdsch_pdu_test.cpp +++ b/tests/unittests/fapi_adaptor/mac/messages/dl_pdsch_pdu_test.cpp @@ -89,7 +89,7 @@ TEST(mac_fapi_pdsch_pdu_conversor_test, valid_rar_pdu_should_pass) unsigned nof_prbs = 51U; fapi::dl_pdsch_pdu fapi_pdu; - auto pm_tools = generate_precoding_matrix_tables(1); + auto pm_tools = generate_precoding_matrix_tables(2); convert_pdsch_mac_to_fapi(fapi_pdu, pdu, nof_csi_pdus, *std::get<0>(pm_tools), nof_prbs); validate_pdsch_information(pdu.pdsch_cfg, fapi_pdu); @@ -100,6 +100,12 @@ TEST(mac_fapi_pdsch_pdu_conversor_test, valid_rar_pdu_should_pass) for (unsigned i = 0; i != nof_csi_pdus; ++i) { ASSERT_EQ(i, csi_rm[i]); } + + const auto& mac_prec = *pdu.pdsch_cfg.precoding; + const auto& fapi_prec = fapi_pdu.precoding_and_beamforming; + ASSERT_EQ(nof_prbs, fapi_prec.prg_size); + ASSERT_EQ(mac_prec.prg_infos.size(), fapi_prec.prgs.size()); + ASSERT_FALSE(std::get<1>(pm_tools)->get_precoding_matrix(fapi_prec.prgs.front().pm_index).get_nof_layers() == 0); } TEST(mac_fapi_pdsch_pdu_conversor_test, valid_dl_paging_pdu_should_pass) @@ -131,7 +137,7 @@ TEST(mac_fapi_pdsch_pdu_conversor_test, valid_dl_msg_alloc_pdu_should_pass) unsigned nof_prbs = 51U; fapi::dl_pdsch_pdu fapi_pdu; - auto pm_tools = generate_precoding_matrix_tables(1); + auto pm_tools = generate_precoding_matrix_tables(4); convert_pdsch_mac_to_fapi(fapi_pdu, pdu, nof_csi_pdus, *std::get<0>(pm_tools), nof_prbs); validate_pdsch_information(pdu.pdsch_cfg, fapi_pdu); @@ -142,4 +148,14 @@ TEST(mac_fapi_pdsch_pdu_conversor_test, valid_dl_msg_alloc_pdu_should_pass) for (unsigned i = 0; i != nof_csi_pdus; ++i) { ASSERT_EQ(i, csi_rm[i]); } + + // Context. + ASSERT_EQ(pdu.pdsch_cfg.harq_id, fapi_pdu.context->get_h_id()); + ASSERT_EQ(bool(pdu.context.nof_retxs), !fapi_pdu.context->is_new_data()); + + const auto& mac_prec = *pdu.pdsch_cfg.precoding; + const auto& fapi_prec = fapi_pdu.precoding_and_beamforming; + ASSERT_EQ(mac_prec.nof_rbs_per_prg, fapi_prec.prg_size); + ASSERT_EQ(mac_prec.prg_infos.size(), fapi_prec.prgs.size()); + ASSERT_FALSE(std::get<1>(pm_tools)->get_precoding_matrix(fapi_prec.prgs.front().pm_index).get_nof_layers() == 0); } diff --git a/tests/unittests/fapi_adaptor/mac/messages/helpers.cpp b/tests/unittests/fapi_adaptor/mac/messages/helpers.cpp index 4e12482dcb..36a3e7779d 100644 --- a/tests/unittests/fapi_adaptor/mac/messages/helpers.cpp +++ b/tests/unittests/fapi_adaptor/mac/messages/helpers.cpp @@ -216,9 +216,13 @@ static dci_context_information generate_dci_context(const bwp_configuration& bwp info.n_id_pdcch_data = 2; info.n_rnti_pdcch_data = 4; info.cces.ncce = 2; + info.starting_symbol = 2; info.n_id_pdcch_dmrs = 8; info.cces.aggr_lvl = static_cast(generate_case_pattern()); + // NOTE: decision context is not filled as all the members are private in FAPI. + // NOTE: add the precoding information when the struct is defined, now is empty. + return info; } @@ -240,8 +244,10 @@ static void add_dl_pdcch_pdus_to_result(mac_dl_sched_result_test_helper& helper) } } -static pdsch_information -fill_valid_pdsch_information(coreset_configuration& coreset_cfg, bwp_configuration& bwp_config, pdsch_information& info) +static pdsch_information fill_valid_pdsch_information(coreset_configuration& coreset_cfg, + bwp_configuration& bwp_config, + pdsch_information& info, + unsigned nof_ports) { bwp_config = generate_bwp_configuration(); coreset_cfg = generate_coreset_configuration(); @@ -255,10 +261,28 @@ fill_valid_pdsch_information(coreset_configuration& coreset_cfg, bwp_configurati info.n_id = generate_nid_pdsch(); info.nof_layers = 1U; info.is_interleaved = false; + info.harq_id = to_harq_id(4); info.ss_set_type = search_space_set_type::type0; info.dci_fmt = dci_dl_format::f1_0; info.codewords.push_back(pdsch_codeword{{modulation_scheme::QAM16, 220.F}, 5, pdsch_mcs_table::qam64, 2, 128}); + if (nof_ports == 2) { + pdsch_precoding_info& pm = info.precoding.emplace(); + pm.nof_rbs_per_prg = 273U; + csi_report_pmi& csi_report = pm.prg_infos.emplace_back(); + auto& pmi = csi_report.type.emplace(); + pmi.pmi = 1; + } else if (nof_ports == 4) { + pdsch_precoding_info& pm = info.precoding.emplace(); + pm.nof_rbs_per_prg = 273U; + csi_report_pmi& csi_report = pm.prg_infos.emplace_back(); + auto& pmi = csi_report.type.emplace(); + pmi.i_2 = 1; + pmi.i_1_1 = 1; + } + + // By default fill 1 port precofing matrix, which means not configuring the precoding in the 'pdsch_information' + return info; } @@ -287,7 +311,7 @@ sib_information_test_helper unittests::build_valid_sib1_information_pdu() info.si_indicator = sib_information::si_indicator_type::sib1; info.nof_txs = 0; - fill_valid_pdsch_information(helper.coreset_cfg, helper.bwp_cfg, info.pdsch_cfg); + fill_valid_pdsch_information(helper.coreset_cfg, helper.bwp_cfg, info.pdsch_cfg, 1); return helper; } @@ -297,7 +321,7 @@ rar_information_test_helper unittests::build_valid_rar_information_pdu() rar_information_test_helper helper; rar_information& result = helper.pdu; - fill_valid_pdsch_information(helper.coreset_cfg, helper.bwp_cfg, result.pdsch_cfg); + fill_valid_pdsch_information(helper.coreset_cfg, helper.bwp_cfg, result.pdsch_cfg, 2); rar_ul_grant grant; grant.rapid = 2; @@ -320,7 +344,7 @@ dl_paging_allocation_test_helper unittests::build_valid_dl_paging_pdu() dl_paging_allocation_test_helper helper; dl_paging_allocation& result = helper.pdu; - fill_valid_pdsch_information(helper.coreset_cfg, helper.bwp_cfg, result.pdsch_cfg); + fill_valid_pdsch_information(helper.coreset_cfg, helper.bwp_cfg, result.pdsch_cfg, 1); return helper; } @@ -330,7 +354,13 @@ dl_msg_allocation_test_helper unittests::build_valid_dl_msg_alloc_pdu() dl_msg_allocation_test_helper helper; dl_msg_alloc& result = helper.pdu; - fill_valid_pdsch_information(helper.coreset_cfg, helper.bwp_cfg, result.pdsch_cfg); + fill_valid_pdsch_information(helper.coreset_cfg, helper.bwp_cfg, result.pdsch_cfg, 4); + + result.context.ss_id = to_search_space_id(1); + result.context.nof_retxs = 2; + result.context.k1 = 3; + result.context.olla_offset = 4; + result.context.ue_index = to_du_ue_index(5); return helper; } @@ -472,7 +502,7 @@ pucch_info_test_helper srsran::unittests::build_valid_pucch_format_2_pdu() pucch.format = pucch_format::FORMAT_2; pucch.resources.prbs = {1, 4}; pucch.resources.symbols = {0, 1}; - pucch.resources.second_hop_prbs = {}; + pucch.resources.second_hop_prbs = {1, 11}; pucch.format_2.max_code_rate = max_pucch_code_rate::dot_08; pucch.format_2.csi_part1_bits = 102; pucch.format_2.harq_ack_nof_bits = 100; diff --git a/tests/unittests/fapi_adaptor/phy/fapi_to_phy_translator_test.cpp b/tests/unittests/fapi_adaptor/phy/fapi_to_phy_translator_test.cpp index 404283121f..7303273333 100644 --- a/tests/unittests/fapi_adaptor/phy/fapi_to_phy_translator_test.cpp +++ b/tests/unittests/fapi_adaptor/phy/fapi_to_phy_translator_test.cpp @@ -27,8 +27,6 @@ using namespace srsran; using namespace fapi_adaptor; using namespace unittest; -static constexpr subcarrier_spacing scs_common = subcarrier_spacing::kHz15; - namespace { /// Slot error message notifier spy implementation. @@ -104,23 +102,23 @@ class downlink_processor_pool_dummy : public downlink_processor_pool class fapi_to_phy_translator_fixture : public ::testing::Test { protected: - resource_grid_spy grid; - downlink_processor_pool_dummy dl_processor_pool; - resource_grid_pool_dummy rg_pool; - uplink_request_processor_dummy ul_request_processor; - uplink_slot_pdu_repository pdu_repo; - const unsigned sector_id = 0; - const unsigned headroom_in_slots = 2; - const subcarrier_spacing scs = subcarrier_spacing::kHz15; - const slot_point slot = {scs, 1, 0}; - fapi::prach_config prach_cfg; - fapi::carrier_config carrier_cfg = {0, 0, {}, {11, 51, 106, 0, 0}, 0, 0, 0, {}, {}, 0, 0, 0, 0}; - downlink_pdu_validator_dummy dl_pdu_validator; - uplink_pdu_validator_dummy ul_pdu_validator; - slot_error_message_notifier_spy error_notifier_spy; - manual_task_worker worker; - tx_softbuffer_pool_spy softbuffer_pool_spy; - fapi_to_phy_translator_config config = {sector_id, headroom_in_slots, scs, scs_common, &prach_cfg, &carrier_cfg, {0}}; + resource_grid_spy grid; + downlink_processor_pool_dummy dl_processor_pool; + resource_grid_pool_dummy rg_pool; + uplink_request_processor_dummy ul_request_processor; + uplink_slot_pdu_repository pdu_repo; + const unsigned sector_id = 0; + const unsigned headroom_in_slots = 2; + const subcarrier_spacing scs = subcarrier_spacing::kHz15; + const slot_point slot = {scs, 1, 0}; + fapi::prach_config prach_cfg; + fapi::carrier_config carrier_cfg = {0, 0, {}, {11, 51, 106, 0, 0}, 0, 0, 0, {}, {}, 0, 0, 0, 0}; + downlink_pdu_validator_dummy dl_pdu_validator; + uplink_pdu_validator_dummy ul_pdu_validator; + slot_error_message_notifier_spy error_notifier_spy; + manual_task_worker worker; + tx_softbuffer_pool_spy softbuffer_pool_spy; + fapi_to_phy_translator_config config = {sector_id, headroom_in_slots, scs, scs, &prach_cfg, &carrier_cfg, {0}}; fapi_to_phy_translator_dependencies dependencies = { &srslog::fetch_basic_logger("FAPI"), &dl_processor_pool, From 4e717c98ca88b1daf9c9fc6ea18681e3351940d8 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Mon, 11 Dec 2023 17:55:05 +0100 Subject: [PATCH 072/134] sched: use UCI bits to compute PUSCH parameters Signed-off-by: Carlo Galiotto --- lib/scheduler/support/mcs_tbs_calculator.cpp | 7 +- lib/scheduler/support/sch_pdu_builder.cpp | 61 +++++------ lib/scheduler/support/sch_pdu_builder.h | 10 +- lib/scheduler/uci_scheduling/uci_allocator.h | 2 - .../uci_scheduling/uci_allocator_impl.cpp | 100 +++++------------- lib/scheduler/ue_scheduling/ue_cell.cpp | 12 ++- .../ue_scheduling/ue_cell_grid_allocator.cpp | 28 ++--- .../support/mcs_tbs_calculator_test.cpp | 8 +- .../test_utils/dummy_test_components.h | 1 + .../uci_and_pucch/uci_allocator_test.cpp | 84 +-------------- .../ue_scheduling/ta_manager_test.cpp | 3 +- .../ue_harq_link_adaptation_test.cpp | 1 + 12 files changed, 103 insertions(+), 214 deletions(-) diff --git a/lib/scheduler/support/mcs_tbs_calculator.cpp b/lib/scheduler/support/mcs_tbs_calculator.cpp index d5597bc0a6..6da21d7ab8 100644 --- a/lib/scheduler/support/mcs_tbs_calculator.cpp +++ b/lib/scheduler/support/mcs_tbs_calculator.cpp @@ -10,7 +10,6 @@ #include "mcs_tbs_calculator.h" #include "dmrs_helpers.h" -#include "prbs_calculator.h" #include "sch_pdu_builder.h" #include "tbs_calculator.h" #include "srsran/adt/variant.h" @@ -34,7 +33,7 @@ static ulsch_configuration build_ulsch_info(const pusch_config_params& pusch_c .mcs_descr = mcs_info, .nof_harq_ack_bits = static_cast(pusch_cfg.nof_harq_ack_bits), .nof_csi_part1_bits = static_cast(pusch_cfg.nof_csi_part1_bits), - .nof_csi_part2_bits = static_cast(pusch_cfg.nof_csi_part2_bits), + .nof_csi_part2_bits = static_cast(pusch_cfg.max_nof_csi_part2_bits), .nof_rb = nof_prbs, .start_symbol_index = pusch_cfg.symbols.start(), .nof_symbols = static_cast(pusch_cfg.symbols.length()), @@ -114,11 +113,11 @@ static ulsch_configuration build_ulsch_info(const pusch_config_params& pusch_c // CSI Part 2 beta offset. The beta_offset to be used among the indices 1, 2 is determined as per TS38.213, Section // 9.3 and TS38.331, \c BetaOffsets. // If no CSI Part 2 reporting, this value won't be used. - if (pusch_cfg.nof_csi_part2_bits == 0) { + if (pusch_cfg.max_nof_csi_part2_bits == 0) { ulsch_info.beta_offset_csi_part2 = 0; } // Use \c betaOffsetCSI-Part2-Index1 for up to 11 bits CSI Part 2 reporting. - else if (pusch_cfg.nof_csi_part2_bits < 12) { + else if (pusch_cfg.max_nof_csi_part2_bits < 12) { ulsch_info.beta_offset_csi_part2 = beta_csi_to_float(variant_get(ue_cell_cfg.cfg_dedicated() .ul_config.value() diff --git a/lib/scheduler/support/sch_pdu_builder.cpp b/lib/scheduler/support/sch_pdu_builder.cpp index 5e05e629d5..2a3071c8f5 100644 --- a/lib/scheduler/support/sch_pdu_builder.cpp +++ b/lib/scheduler/support/sch_pdu_builder.cpp @@ -13,6 +13,9 @@ #include "pdsch/pdsch_default_time_allocation.h" #include "tbs_calculator.h" #include "srsran/adt/optional.h" +#include "srsran/ran/csi_report/csi_report_config_helpers.h" +#include "srsran/ran/csi_report/csi_report_on_pusch_helpers.h" +#include "srsran/ran/csi_report/csi_report_pusch_size.h" #include "srsran/ran/resource_allocation/resource_allocation_frequency.h" #include "srsran/scheduler/config/serving_cell_config.h" @@ -136,11 +139,9 @@ pusch_config_params srsran::get_pusch_config_f0_0_tc_rnti(const cell_configurati constexpr unsigned tb_scaling_field = 0; // Parameter \c tp-pi2BPSK enabled is not supported yet. constexpr bool tp_pi2bpsk_present = false; - // TODO verify if this is the correct value. + // As with 1 or 2 bits the corresponding beta-offset won't change, we can over-allocate the number of HARQ-ACK bits + // to 2. constexpr unsigned nof_harq_ack_bits = 2; - // There is no need for CSI reporting for TC-RNTI. - constexpr unsigned nof_csi_part1_bits = 0; - constexpr unsigned nof_csi_part2_bits = 0; pusch_config_params pusch; @@ -153,19 +154,17 @@ pusch_config_params srsran::get_pusch_config_f0_0_tc_rnti(const cell_configurati pusch.tp_pi2bpsk_present = tp_pi2bpsk_present; pusch.tb_scaling_field = tb_scaling_field; - pusch.nof_oh_prb = nof_oh_prb; - - // TODO: verify if this needs to be set depending on some configuration. - pusch.nof_harq_ack_bits = nof_harq_ack_bits; - pusch.nof_csi_part1_bits = nof_csi_part1_bits; - pusch.nof_csi_part2_bits = nof_csi_part2_bits; + pusch.nof_oh_prb = nof_oh_prb; + pusch.nof_harq_ack_bits = nof_harq_ack_bits; return pusch; } pusch_config_params srsran::get_pusch_config_f0_0_c_rnti(const ue_cell_configuration& ue_cell_cfg, const bwp_uplink_common& ul_bwp, - const pusch_time_domain_resource_allocation& pusch_td_cfg) + const pusch_time_domain_resource_allocation& pusch_td_cfg, + const unsigned nof_harq_ack_bits, + bool is_csi_report_slot) { const pusch_mcs_table mcs_table = pusch_mcs_table::qam64; constexpr unsigned nof_layers = 1; @@ -174,13 +173,6 @@ pusch_config_params srsran::get_pusch_config_f0_0_c_rnti(const ue_cell_configura constexpr unsigned tb_scaling_field = 0; // Parameter \c tp-pi2BPSK enabled is not supported yet. constexpr bool tp_pi2bpsk_present = false; - // We set 6 bits, assuming a maximum of 1 HARQ-ACK per slot and maximum number of slot corresponding to the number of - // DL slots in TDD, currently 6. - // TODO verify if this is the correct value. - constexpr unsigned nof_harq_ack_bits = 7; - // We assume only 4 bits for CSI Part 1. - constexpr unsigned nof_csi_part1_bits = 4; - constexpr unsigned nof_csi_part2_bits = 0; pusch_config_params pusch; @@ -201,16 +193,23 @@ pusch_config_params srsran::get_pusch_config_f0_0_c_rnti(const ue_cell_configura : static_cast(x_overhead::not_set); // TODO: verify if this needs to be set depending on some configuration. - pusch.nof_harq_ack_bits = nof_harq_ack_bits; - pusch.nof_csi_part1_bits = nof_csi_part1_bits; - pusch.nof_csi_part2_bits = nof_csi_part2_bits; + pusch.nof_harq_ack_bits = nof_harq_ack_bits; + if (is_csi_report_slot) { + csi_report_configuration csi_rep_cfg = + create_csi_report_configuration(ue_cell_cfg.cfg_dedicated().csi_meas_cfg.value()); + csi_report_pusch_size csi_size = get_csi_report_pusch_size(csi_rep_cfg); + pusch.nof_csi_part1_bits = csi_size.part1_size.value(); + pusch.max_nof_csi_part2_bits = csi_size.part2_max_size.value(); + } return pusch; } pusch_config_params srsran::get_pusch_config_f0_1_c_rnti(const ue_cell_configuration& ue_cell_cfg, const pusch_time_domain_resource_allocation& pusch_td_cfg, - unsigned nof_layers) + unsigned nof_layers, + const unsigned nof_harq_ack_bits, + bool is_csi_report_slot) { const pusch_mcs_table mcs_table = ue_cell_cfg.cfg_dedicated().ul_config->init_ul_bwp.pusch_cfg->mcs_table; // As per TS 38.214, Section 5.1.3.2 and 6.1.4.2, and TS 38.212, Section 7.3.1.1 and 7.3.1.2, TB scaling filed is only @@ -218,13 +217,6 @@ pusch_config_params srsran::get_pusch_config_f0_1_c_rnti(const ue_cell_configura constexpr unsigned tb_scaling_field = 0; // Parameter \c tp-pi2BPSK enabled is not supported yet. constexpr bool tp_pi2bpsk_present = false; - // We set 6 bits, assuming a maximum of 1 HARQ-ACK per slot and maximum number of slot corresponding to the number of - // DL slots in TDD, currently 6. - // TODO verify if this is the correct value. - constexpr unsigned nof_harq_ack_bits = 7; - // We assume only 4 bits for CSI Part 1. - constexpr unsigned nof_csi_part1_bits = 4; - constexpr unsigned nof_csi_part2_bits = 0; // TODO: Update the value based on nof. CWs enabled. static const bool are_both_cws_enabled = false; @@ -256,9 +248,14 @@ pusch_config_params srsran::get_pusch_config_f0_1_c_rnti(const ue_cell_configura : static_cast(x_overhead::not_set); // TODO: verify if this needs to be set depending on some configuration. - pusch.nof_harq_ack_bits = nof_harq_ack_bits; - pusch.nof_csi_part1_bits = nof_csi_part1_bits; - pusch.nof_csi_part2_bits = nof_csi_part2_bits; + pusch.nof_harq_ack_bits = nof_harq_ack_bits; + if (is_csi_report_slot) { + csi_report_configuration csi_rep_cfg = + create_csi_report_configuration(ue_cell_cfg.cfg_dedicated().csi_meas_cfg.value()); + csi_report_pusch_size csi_size = get_csi_report_pusch_size(csi_rep_cfg); + pusch.nof_csi_part1_bits = csi_size.part1_size.value(); + pusch.max_nof_csi_part2_bits = csi_size.part2_max_size.value(); + } return pusch; } diff --git a/lib/scheduler/support/sch_pdu_builder.h b/lib/scheduler/support/sch_pdu_builder.h index a400a200c3..cb510adfbf 100644 --- a/lib/scheduler/support/sch_pdu_builder.h +++ b/lib/scheduler/support/sch_pdu_builder.h @@ -41,7 +41,7 @@ struct pusch_config_params { dmrs_information dmrs; unsigned nof_harq_ack_bits{0}; unsigned nof_csi_part1_bits{0}; - unsigned nof_csi_part2_bits{0}; + unsigned max_nof_csi_part2_bits{0}; }; /// \brief Fetches the PDSCH parameters needed for PDSCH PDU for DCI format 1_0, scrambled by TC-RNTI. @@ -74,14 +74,18 @@ pusch_config_params get_pusch_config_f0_0_tc_rnti(const cell_configuration& /// The parameters returned by this function are needed to compute the number of PRBs, MCS and TBS. pusch_config_params get_pusch_config_f0_0_c_rnti(const ue_cell_configuration& ue_cell_cfg, const bwp_uplink_common& ul_bwp, - const pusch_time_domain_resource_allocation& pusch_td_cfg); + const pusch_time_domain_resource_allocation& pusch_td_cfg, + const unsigned nof_harq_ack_bits, + bool is_csi_report_slot); /// \brief Fetches the PUSCH parameters needed for PUSCH PDU for DCI format 0_1, scrambled by C-RNTI. /// /// The parameters returned by this function are needed to compute the number of PRBs, MCS and TBS. pusch_config_params get_pusch_config_f0_1_c_rnti(const ue_cell_configuration& ue_cell_cfg, const pusch_time_domain_resource_allocation& pusch_td_cfg, - unsigned nof_layers); + unsigned nof_layers, + const unsigned nof_harq_ack_bits, + bool is_csi_report_slot); /// \brief Builds PDSCH PDU for DCI format 1_0, scrambled by SI-RNTI. void build_pdsch_f1_0_si_rnti(pdsch_information& pdsch, diff --git a/lib/scheduler/uci_scheduling/uci_allocator.h b/lib/scheduler/uci_scheduling/uci_allocator.h index 4514bd057b..600ab6979a 100644 --- a/lib/scheduler/uci_scheduling/uci_allocator.h +++ b/lib/scheduler/uci_scheduling/uci_allocator.h @@ -8,8 +8,6 @@ * */ -#include "../pucch_scheduling/pucch_allocator.h" - #pragma once namespace srsran { diff --git a/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp b/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp index 3c1dd638db..8e3273b1b3 100644 --- a/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp +++ b/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp @@ -109,88 +109,38 @@ optional uci_allocator_impl::alloc_uci_harq_ue_helper(cell_resou const bool has_pusch_grants = existing_pusch != slot_alloc.result.ul.puschs.end(); - // [Implementation-defined] Skip allocation of UCI if the existing PUSCH grants was scheduled by non-fallback DCI - // format. - // Reason: Allocating UCI on PUSCH would require change in DAI sent in DCI 0_1 which scheduled the PUSCH, - // which is not possible. - if (has_pusch_grants and ue_cell_cfg.find_search_space(existing_pusch->context.ss_id) != nullptr and - ue_cell_cfg.find_search_space(existing_pusch->context.ss_id)->get_ul_dci_format() == dci_ul_format::f0_1) { + // [Implementation-defined] Skip allocation of UCI if any existing PUSCH grants. + if (has_pusch_grants) { return {}; } const bool fallback_mode = fallback_dci_info != nullptr; - // Allocate UCI on PUSCH if any PUSCH grants that was scheduled by fallback DCI format already exist for the UE; - // else, allocate UCI on PUCCH. - // NOTE: Considering the note above, the allocation of UCI on PUSCH is only possible when the PUSCH was scheduled by - // fallback DCI during non-fallback mode. - if (has_pusch_grants) { - // TS 38.213, Section 9.3, is vague about this case. - // "If DCI format 0_0, or DCI format 0_1 that does not include a beta_offset indicator field, schedules the PUSCH - // transmission from the UE and the UE is provided betaOffsets = 'semiStatic', the UE applies the - // beta_offset^HARQ-ACK [...] values that are provided by betaOffsets = 'semiStatic' for the corresponding - // HARQ-ACK information [...]". Note that the \c betaOffsets are only present in the PUSCH-Config, not in the - // PUSCH-ConfigCommon, which raises the doubt of whether the UCI multiplexing on PUSCH can only be done with UE - // dedicated configuration. - // TS 38.213, Section 9.3 does NOT specify what to do when UE is not provided \c betaOffsets. - // On the other hand, \c BetaOffsets description in TS 38.331 states that the value 11 should be used for - // betaOffsetACK-Index1, betaOffsetACK-Index2 and betaOffsetACK-Index3 when these files are absent (inside - // BetaOffsets). - // Due to the lack of clarity, in the following, we avoid scheduling a UCI on PUSCH during fallback mode. - if (fallback_mode) { - logger.debug("UCI for HARQ-ACK allocation on PUSCH skipped for ue={}. Cause: we don't multiplex UCI on " - "PUSCH during fallback mode", - crnti); - return {}; - } - // If we reach this point, we expect no allocated PUCCH grants. - if (not existing_pusch->uci.has_value()) { - existing_pusch->uci.emplace(); - existing_pusch->uci.value().alpha = - ue_cell_cfg.cfg_dedicated().ul_config.value().init_ul_bwp.pusch_cfg.value().uci_cfg.value().scaling; + optional pucch_res_indicator; + if (fallback_mode) { + const auto* pucch_harq_grant_it = std::find_if( + slot_alloc.result.ul.pucchs.begin(), slot_alloc.result.ul.pucchs.end(), [crnti](const pucch_info& pucch_grant) { + srsran_assert(pucch_grant.format == pucch_format::FORMAT_1 or pucch_grant.format == pucch_format::FORMAT_2, + "Only PUCCH Format 1 and Format 2 are supported"); + const bool has_harq_ack_bits = pucch_grant.format == pucch_format::FORMAT_1 + ? pucch_grant.format_1.harq_ack_nof_bits != 0U + : pucch_grant.format_2.harq_ack_nof_bits != 0U; + return pucch_grant.crnti == crnti and has_harq_ack_bits; + }); + + // Do not allocate PUCCH on common resources if there is any pre-allocated grant using PUCCH dedicated resource + // with HARQ-ACK bits, as we don't support multiplexing of bits across common and dedicated resources. + if (pucch_harq_grant_it == slot_alloc.result.ul.pucchs.end()) { + pucch_res_indicator = pucch_alloc.alloc_common_pucch_harq_ack_ue(res_alloc, crnti, k0, k1, *fallback_dci_info); } - if (not existing_pusch->uci.value().harq.has_value()) { - existing_pusch->uci.value().harq.emplace(); - } - // We assume we only report the HARQ-ACK for a single layer, i.e., 1 bit (plus additional previous bits). - ++existing_pusch->uci.value().harq->harq_ack_nof_bits; - - update_uci_on_pusch_harq_offsets( - existing_pusch->uci.value().harq.value(), - ue_cell_cfg.cfg_dedicated().ul_config.value().init_ul_bwp.pusch_cfg.value().uci_cfg.value()); - logger.debug("UCI for HARQ-ACK allocated on PUSCH, for ue={}", crnti); - return {uci_allocation{}}; } - // No PUSCH grants; allocate on PUCCH. + // PUCCH, Non-fallback mode. else { - optional pucch_res_indicator; - if (fallback_mode) { - const auto* pucch_harq_grant_it = std::find_if( - slot_alloc.result.ul.pucchs.begin(), - slot_alloc.result.ul.pucchs.end(), - [crnti](const pucch_info& pucch_grant) { - srsran_assert(pucch_grant.format == pucch_format::FORMAT_1 or pucch_grant.format == pucch_format::FORMAT_2, - "Only PUCCH Format 1 and Format 2 are supported"); - const bool has_harq_ack_bits = pucch_grant.format == pucch_format::FORMAT_1 - ? pucch_grant.format_1.harq_ack_nof_bits != 0U - : pucch_grant.format_2.harq_ack_nof_bits != 0U; - return pucch_grant.crnti == crnti and has_harq_ack_bits; - }); - - // Do not allocate PUCCH on common resources if there is any pre-allocated grant using PUCCH dedicated resource - // with HARQ-ACK bits, as we don't support multiplexing of bits across common and dedicated resources. - if (pucch_harq_grant_it == slot_alloc.result.ul.pucchs.end()) { - pucch_res_indicator = pucch_alloc.alloc_common_pucch_harq_ack_ue(res_alloc, crnti, k0, k1, *fallback_dci_info); - } - } - // PUCCH, Non-fallback mode. - else { - pucch_res_indicator = pucch_alloc.alloc_ded_pucch_harq_ack_ue(res_alloc, crnti, ue_cell_cfg, k0, k1); - } - return pucch_res_indicator.has_value() - ? optional{uci_allocation{.pucch_res_indicator = pucch_res_indicator}} - : nullopt; + pucch_res_indicator = pucch_alloc.alloc_ded_pucch_harq_ack_ue(res_alloc, crnti, ue_cell_cfg, k0, k1); } + return pucch_res_indicator.has_value() + ? optional{uci_allocation{.pucch_res_indicator = pucch_res_indicator}} + : nullopt; } //////////// Public functions //////////// @@ -347,7 +297,9 @@ void uci_allocator_impl::uci_allocate_csi_opportunity(cell_slot_resource_allocat const bool has_pusch_grants = not slot_alloc.result.ul.puschs.empty() and existing_pusch != slot_alloc.result.ul.puschs.end(); - // If there is a PUSCH allocated for this UE, allocate the CSI on the UCI on PUSCH. + // TODO: check if this case is possible. The first PUSCH that is allocated outside the RAR grant is will be allocated + // after the UE objected gets created with the UE dedicated configuration; this means the CSI scheduler should + // start allocating CSI grants before any PUSCH grants (except the PUSCH scheduled in the RAR). if (has_pusch_grants) { // If there is UCI grant allocated, allocate it. srsran_assert(not existing_pusch->uci.has_value(), "UCI on PUSCH grant for CSI cannot be already allocated"); diff --git a/lib/scheduler/ue_scheduling/ue_cell.cpp b/lib/scheduler/ue_scheduling/ue_cell.cpp index 56bf6588d0..0c9bae58d1 100644 --- a/lib/scheduler/ue_scheduling/ue_cell.cpp +++ b/lib/scheduler/ue_scheduling/ue_cell.cpp @@ -129,16 +129,24 @@ grant_prbs_mcs ue_cell::required_ul_prbs(const pusch_time_domain_resource_alloca { const bwp_uplink_common& bwp_ul_cmn = *ue_cfg->bwp(active_bwp_id()).ul_common; + // In the following, we allocate extra bits to account for the possible UCI overhead. At this point, we don't + // differentiate between HARQ-ACK bits and CSI bits, which would be necessary to compute the beta-offset values. + // Here, we only need to allocate some extra space. + const unsigned uci_bits_overallocation = 20U; + const bool is_csi_report_slot = false; + pusch_config_params pusch_cfg; switch (dci_type) { case dci_ul_rnti_config_type::tc_rnti_f0_0: pusch_cfg = get_pusch_config_f0_0_tc_rnti(cell_cfg, pusch_td_cfg); break; case dci_ul_rnti_config_type::c_rnti_f0_0: - pusch_cfg = get_pusch_config_f0_0_c_rnti(*ue_cfg, bwp_ul_cmn, pusch_td_cfg); + pusch_cfg = + get_pusch_config_f0_0_c_rnti(ue_cfg, bwp_ul_cmn, pusch_td_cfg, uci_bits_overallocation, is_csi_report_slot); break; case dci_ul_rnti_config_type::c_rnti_f0_1: - pusch_cfg = get_pusch_config_f0_1_c_rnti(*ue_cfg, pusch_td_cfg, channel_state.get_nof_ul_layers()); + pusch_cfg = get_pusch_config_f0_1_c_rnti( + ue_cfg, pusch_td_cfg, channel_state.get_nof_ul_layers(), uci_bits_overallocation, is_csi_report_slot); break; default: report_fatal_error("Unsupported PDCCH DCI UL format"); diff --git a/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp b/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp index 6ab8c16a1e..1f5354875c 100644 --- a/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp +++ b/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp @@ -516,9 +516,11 @@ alloc_outcome ue_cell_grid_allocator::allocate_ul_grant(const ue_pusch_grant& gr return alloc_outcome::skip_slot; } + const bool is_csi_report_slot = + csi_helper::is_csi_reporting_slot(u.get_pcell().cfg().cfg_dedicated(), pusch_alloc.slot); + // We skip allocation of PUSCH in the slots with the CSI reporting over PUCCH. - if (csi_helper::is_csi_reporting_slot(u.get_pcell().cfg().cfg_dedicated(), pusch_alloc.slot) and - cell_cfg.dl_carrier.nof_ant > 1U) { + if (is_csi_report_slot and cell_cfg.dl_carrier.nof_ant > 1U) { logger.debug("rnti={} Allocation of PUSCH in slot={} skipped. Cause: this slot is for CSI reporting over PUCCH", u.crnti, pusch_alloc.slot); @@ -588,6 +590,9 @@ alloc_outcome ue_cell_grid_allocator::allocate_ul_grant(const ue_pusch_grant& gr return alloc_outcome::skip_ue; } + const unsigned nof_harq_ack_bits = + get_uci_alloc(grant.cell_index).get_scheduled_pdsch_counter_in_ue_uci(pusch_alloc, u.crnti); + // Fetch PUSCH parameters based on type of transmission. pusch_config_params pusch_cfg; switch (dci_type) { @@ -595,11 +600,15 @@ alloc_outcome ue_cell_grid_allocator::allocate_ul_grant(const ue_pusch_grant& gr pusch_cfg = get_pusch_config_f0_0_tc_rnti(cell_cfg, pusch_td_cfg); break; case dci_ul_rnti_config_type::c_rnti_f0_0: - pusch_cfg = get_pusch_config_f0_0_c_rnti(ue_cell_cfg, bwp_ul_cmn, pusch_td_cfg); + pusch_cfg = + get_pusch_config_f0_0_c_rnti(ue_cell_cfg, bwp_ul_cmn, pusch_td_cfg, nof_harq_ack_bits, is_csi_report_slot); break; case dci_ul_rnti_config_type::c_rnti_f0_1: - pusch_cfg = - get_pusch_config_f0_1_c_rnti(ue_cell_cfg, pusch_td_cfg, ue_cc->channel_state_manager().get_nof_ul_layers()); + pusch_cfg = get_pusch_config_f0_1_c_rnti(ue_cell_cfg, + pusch_td_cfg, + ue_cc->channel_state_manager().get_nof_ul_layers(), + nof_harq_ack_bits, + is_csi_report_slot); break; default: report_fatal_error("Unsupported PDCCH DCI UL format"); @@ -632,7 +641,7 @@ alloc_outcome ue_cell_grid_allocator::allocate_ul_grant(const ue_pusch_grant& gr pusch_cfg.tp_pi2bpsk_present ? "yes" : "no", pusch_cfg.nof_harq_ack_bits, pusch_cfg.nof_csi_part1_bits, - pusch_cfg.nof_csi_part2_bits, + pusch_cfg.max_nof_csi_part2_bits, static_cast(pusch_cfg.mcs_table), ue_cell_cfg.cell_cfg_common.dmrs_typeA_pos == dmrs_typeA_position::pos2 ? "pos2" : "pos3", ue_cell_cfg.cfg_dedicated().ul_config->init_ul_bwp.pusch_cfg->pusch_mapping_type_a_dmrs.value().is_dmrs_type2 @@ -670,12 +679,7 @@ alloc_outcome ue_cell_grid_allocator::allocate_ul_grant(const ue_pusch_grant& gr // NOTE: DAI is encoded as per left most column in Table 9.1.3-2 of TS 38.213. unsigned dai = 3; if (dci_type == dci_ul_rnti_config_type::c_rnti_f0_1) { - unsigned total_harq_ack_in_uci = 0; - for (unsigned cell_idx = 0; cell_idx < u.nof_cells(); cell_idx++) { - const ue_cell& ue_cell_info = u.get_cell(static_cast(cell_idx)); - total_harq_ack_in_uci += - get_uci_alloc(ue_cell_info.cell_index).get_scheduled_pdsch_counter_in_ue_uci(pusch_alloc, u.crnti); - } + unsigned total_harq_ack_in_uci = nof_harq_ack_bits; if (total_harq_ack_in_uci != 0) { // See TS 38.213, Table 9.1.3-2. dai value below maps to the leftmost column in the table. dai = ((total_harq_ack_in_uci - 1) % 4); diff --git a/tests/unittests/scheduler/support/mcs_tbs_calculator_test.cpp b/tests/unittests/scheduler/support/mcs_tbs_calculator_test.cpp index fc7d46b55e..bd6657b359 100644 --- a/tests/unittests/scheduler/support/mcs_tbs_calculator_test.cpp +++ b/tests/unittests/scheduler/support/mcs_tbs_calculator_test.cpp @@ -146,7 +146,9 @@ class ul_mcs_tbs_prbs_calculator_dci_0_1_test_bench : public ::testing::TestWith pusch_cfg(get_pusch_config_f0_1_c_rnti( ue_cell_cfg, cell_cfg.ul_cfg_common.init_ul_bwp.pusch_cfg_common.value().pusch_td_alloc_list[time_resource], - 1)) + 1, + 7, + true)) { } @@ -197,7 +199,9 @@ class ul_mcs_tbs_prbs_calculator_low_mcs_test_bench : public ::testing::Test pusch_cfg(get_pusch_config_f0_1_c_rnti( ue_cell_cfg, cell_cfg.ul_cfg_common.init_ul_bwp.pusch_cfg_common.value().pusch_td_alloc_list[time_resource], - 1)) + 1, + 7, + true)) { } diff --git a/tests/unittests/scheduler/test_utils/dummy_test_components.h b/tests/unittests/scheduler/test_utils/dummy_test_components.h index 2f520d9244..55f2d08a42 100644 --- a/tests/unittests/scheduler/test_utils/dummy_test_components.h +++ b/tests/unittests/scheduler/test_utils/dummy_test_components.h @@ -13,6 +13,7 @@ #include "lib/scheduler/logging/scheduler_metrics_ue_configurator.h" #include "lib/scheduler/pdcch_scheduling/pdcch_resource_allocator.h" #include "lib/scheduler/uci_scheduling/uci_allocator.h" +#include "lib/scheduler/ue_scheduling/harq_process.h" #include "srsran/scheduler/scheduler_metrics.h" #include "srsran/support/test_utils.h" diff --git a/tests/unittests/scheduler/uci_and_pucch/uci_allocator_test.cpp b/tests/unittests/scheduler/uci_and_pucch/uci_allocator_test.cpp index 265a919555..18b4fccc4c 100644 --- a/tests/unittests/scheduler/uci_and_pucch/uci_allocator_test.cpp +++ b/tests/unittests/scheduler/uci_and_pucch/uci_allocator_test.cpp @@ -299,11 +299,8 @@ TEST_F(test_uci_allocator, uci_harq_alloc_on_existing_pusch) ASSERT_EQ(0, slot_grid.result.ul.pucchs.size()); // 1 grant expected on PUSCH. ASSERT_EQ(1, slot_grid.result.ul.puschs.size()); - ASSERT_TRUE(slot_grid.result.ul.puschs.back().uci.has_value()); - ASSERT_TRUE(slot_grid.result.ul.puschs.back().uci.value().harq.has_value()); - ASSERT_EQ(1, slot_grid.result.ul.puschs.back().uci.value().harq.value().harq_ack_nof_bits); - ASSERT_FALSE(slot_grid.result.ul.puschs.back().uci.value().csi.has_value()); - ASSERT_TRUE(check_pusch_out_param(slot_grid.result.ul.puschs.back())); + // ... but without any UCI. + ASSERT_FALSE(slot_grid.result.ul.puschs.back().uci.has_value()); } /////// UCI multiplexing on PUSCH /////// @@ -491,83 +488,6 @@ TEST_F(test_tdd_uci_allocator, when_tdd_cfg_then_harq_bit_index_increases_with_n } } -// Allocate multiple HARQ-ACK grants over the same target slot. -TEST_F(test_tdd_uci_allocator, test_tdd_harq_ack_multiplexing) -{ - const unsigned pusch_slot_number = 7; - // Add a PUSCH at slot 7. - add_pusch_alloc(pusch_slot_number); - - // All the allocation allocate a HARQ-ACK grant at slot 7. - // t_bench.sl_tx = 0; k0 = 0; k1 = 7 => t_bench.sl_tx + k0 + k1 = 7. - std::vector k1_candidates = {7}; - auto& slot_grid_1 = t_bench.res_grid[t_bench.k0 + k1_candidates.back()]; - - // Allocate 1 HARQ at k1 = 4. - t_bench.uci_alloc.uci_allocate_csi_opportunity( - slot_grid_1, t_bench.get_main_ue().crnti, t_bench.get_main_ue().get_pcell().cfg()); - ASSERT_EQ(0, slot_grid_1.result.ul.pucchs.size()); - ASSERT_EQ(1, slot_grid_1.result.ul.puschs.size()); - ASSERT_TRUE(slot_grid_1.result.ul.puschs.back().uci.has_value()); - ASSERT_FALSE(slot_grid_1.result.ul.puschs.back().uci.value().harq.has_value()); - ASSERT_TRUE(slot_grid_1.result.ul.puschs.back().uci.value().csi.has_value()); - ASSERT_EQ(4, slot_grid_1.result.ul.puschs.back().uci.value().csi.value().csi_part1_nof_bits); - - // Allocate 1 HARQ at k1 = 7. - t_bench.uci_alloc.alloc_uci_harq_ue(t_bench.res_grid, - t_bench.get_main_ue().crnti, - t_bench.get_main_ue().get_pcell().cfg(), - t_bench.k0, - k1_candidates); - ASSERT_EQ(0, slot_grid_1.result.ul.pucchs.size()); - ASSERT_EQ(1, slot_grid_1.result.ul.puschs.size()); - ASSERT_TRUE(slot_grid_1.result.ul.puschs.back().uci.has_value()); - ASSERT_TRUE(slot_grid_1.result.ul.puschs.back().uci.value().harq.has_value()); - ASSERT_EQ(1, slot_grid_1.result.ul.puschs.back().uci.value().harq.value().harq_ack_nof_bits); - ASSERT_TRUE(slot_grid_1.result.ul.puschs.back().uci.value().csi.has_value()); - ASSERT_EQ(4, slot_grid_1.result.ul.puschs.back().uci.value().csi.value().csi_part1_nof_bits); - - // Advance by 1 slot. - t_bench.slot_indication(++t_bench.sl_tx); - // t_bench.sl_tx = 1; k0 = 0; k1 = 6 => t_bench.sl_tx + k0 + k1 = 6. - k1_candidates = {6}; - auto& slot_grid_2 = t_bench.res_grid[t_bench.k0 + k1_candidates.back()]; - - // Allocate 1 HARQ at k1 = 6. - t_bench.uci_alloc.alloc_uci_harq_ue(t_bench.res_grid, - t_bench.get_main_ue().crnti, - t_bench.get_main_ue().get_pcell().cfg(), - t_bench.k0, - k1_candidates); - ASSERT_EQ(0, slot_grid_2.result.ul.pucchs.size()); - ASSERT_EQ(1, slot_grid_2.result.ul.puschs.size()); - ASSERT_TRUE(slot_grid_2.result.ul.puschs.back().uci.has_value()); - ASSERT_TRUE(slot_grid_2.result.ul.puschs.back().uci.value().harq.has_value()); - ASSERT_EQ(2, slot_grid_2.result.ul.puschs.back().uci.value().harq.value().harq_ack_nof_bits); - ASSERT_TRUE(slot_grid_2.result.ul.puschs.back().uci.value().csi.has_value()); - ASSERT_EQ(4, slot_grid_2.result.ul.puschs.back().uci.value().csi.value().csi_part1_nof_bits); - - // Advance by 1 slot. - t_bench.slot_indication(++t_bench.sl_tx); - // t_bench.sl_tx = 2; k0 = 0; k1 = 5 => t_bench.sl_tx + k0 + k1 = 5. - k1_candidates = {5}; - auto& slot_grid_3 = t_bench.res_grid[t_bench.k0 + k1_candidates.back()]; - - // Allocate 1 HARQ at k1 = 5. This will convert the PUCCH grant to Format 2. - t_bench.uci_alloc.alloc_uci_harq_ue(t_bench.res_grid, - t_bench.get_main_ue().crnti, - t_bench.get_main_ue().get_pcell().cfg(), - t_bench.k0, - k1_candidates); - ASSERT_EQ(0, slot_grid_3.result.ul.pucchs.size()); - ASSERT_EQ(1, slot_grid_3.result.ul.puschs.size()); - ASSERT_TRUE(slot_grid_3.result.ul.puschs.back().uci.has_value()); - ASSERT_TRUE(slot_grid_3.result.ul.puschs.back().uci.value().harq.has_value()); - ASSERT_EQ(3, slot_grid_3.result.ul.puschs.back().uci.value().harq.value().harq_ack_nof_bits); - ASSERT_TRUE(slot_grid_2.result.ul.puschs.back().uci.value().csi.has_value()); - ASSERT_EQ(4, slot_grid_2.result.ul.puschs.back().uci.value().csi.value().csi_part1_nof_bits); -} - class test_uci_allocator_mimo_4x4 : public ::testing::Test { public: diff --git a/tests/unittests/scheduler/ue_scheduling/ta_manager_test.cpp b/tests/unittests/scheduler/ue_scheduling/ta_manager_test.cpp index 92116a4593..07af23b012 100644 --- a/tests/unittests/scheduler/ue_scheduling/ta_manager_test.cpp +++ b/tests/unittests/scheduler/ue_scheduling/ta_manager_test.cpp @@ -8,9 +8,10 @@ * */ +#include "../../../../lib/scheduler/ue_scheduling/dl_logical_channel_manager.h" +#include "../../../../lib/scheduler/ue_scheduling/ta_manager.h" #include "tests/unittests/scheduler/test_utils/config_generators.h" #include "tests/unittests/scheduler/test_utils/indication_generators.h" -#include "tests/unittests/scheduler/test_utils/scheduler_test_bench.h" #include "srsran/ran/duplex_mode.h" #include "srsran/ran/prach/prach_helper.h" #include diff --git a/tests/unittests/scheduler/ue_scheduling/ue_harq_link_adaptation_test.cpp b/tests/unittests/scheduler/ue_scheduling/ue_harq_link_adaptation_test.cpp index 202eee0db2..82fc133622 100644 --- a/tests/unittests/scheduler/ue_scheduling/ue_harq_link_adaptation_test.cpp +++ b/tests/unittests/scheduler/ue_scheduling/ue_harq_link_adaptation_test.cpp @@ -8,6 +8,7 @@ * */ +#include "../../../../lib/scheduler/ue_scheduling/ue.h" #include "../test_utils/config_generators.h" #include "../test_utils/dummy_test_components.h" #include From 7b3ee462c6c42f2d6b077cb03de04b01e622a602 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Mon, 11 Dec 2023 18:38:45 +0100 Subject: [PATCH 073/134] sched: fix csi report generation for PUSCH Signed-off-by: Carlo Galiotto --- .../csi_report/csi_report_config_helpers.h | 7 +++ .../csi_report/csi_report_config_helpers.cpp | 7 +++ lib/scheduler/support/sch_pdu_builder.cpp | 27 +++++++-- .../uci_scheduling/uci_allocator_impl.cpp | 55 ++++++++++++------- lib/scheduler/ue_scheduling/ue_cell.cpp | 6 +- .../ue_scheduling/ue_cell_grid_allocator.cpp | 14 +---- .../uci_and_pucch/uci_allocator_test.cpp | 10 ++-- .../ue_scheduling/ta_manager_test.cpp | 4 +- .../ue_harq_link_adaptation_test.cpp | 2 +- 9 files changed, 85 insertions(+), 47 deletions(-) diff --git a/include/srsran/ran/csi_report/csi_report_config_helpers.h b/include/srsran/ran/csi_report/csi_report_config_helpers.h index ef91c30676..baef958d65 100644 --- a/include/srsran/ran/csi_report/csi_report_config_helpers.h +++ b/include/srsran/ran/csi_report/csi_report_config_helpers.h @@ -23,4 +23,11 @@ csi_report_configuration create_csi_report_configuration(const csi_meas_config& /// CSI report configuration validator. bool is_valid(const csi_report_configuration& config); +/// \brief Tells whether the CSI report is configured for PUSCH. +/// +/// \remark There is no explicit statement defining this in the TS; however, we can infer from \c reportConfigType in \c +/// CSI-ReportConfig, TS 38.331, that the CSI report is configured for PUSCH if it is either \c semiPersistentOnPUSCH or +/// \c aperiodic, while it's configured for PUCCH if it is \c periodic or \c semiPersistentOnPUCCH. +bool is_pusch_configured(const csi_meas_config& csi_meas); + } // namespace srsran diff --git a/lib/ran/csi_report/csi_report_config_helpers.cpp b/lib/ran/csi_report/csi_report_config_helpers.cpp index 8f864ae05c..2d97d6af8f 100644 --- a/lib/ran/csi_report/csi_report_config_helpers.cpp +++ b/lib/ran/csi_report/csi_report_config_helpers.cpp @@ -109,3 +109,10 @@ bool srsran::is_valid(const csi_report_configuration& config) return true; } + +bool srsran::is_pusch_configured(const csi_meas_config& csi_meas) +{ + srsran_assert(csi_meas.csi_report_cfg_list.size() == 1, "Only one CSI report configuration is supported"); + return not variant_holds_alternative( + csi_meas.csi_report_cfg_list[0].report_cfg_type); +} diff --git a/lib/scheduler/support/sch_pdu_builder.cpp b/lib/scheduler/support/sch_pdu_builder.cpp index 2a3071c8f5..30ebaa2cb7 100644 --- a/lib/scheduler/support/sch_pdu_builder.cpp +++ b/lib/scheduler/support/sch_pdu_builder.cpp @@ -14,6 +14,7 @@ #include "tbs_calculator.h" #include "srsran/adt/optional.h" #include "srsran/ran/csi_report/csi_report_config_helpers.h" +#include "srsran/ran/csi_report/csi_report_on_pucch_helpers.h" #include "srsran/ran/csi_report/csi_report_on_pusch_helpers.h" #include "srsran/ran/csi_report/csi_report_pusch_size.h" #include "srsran/ran/resource_allocation/resource_allocation_frequency.h" @@ -197,9 +198,16 @@ pusch_config_params srsran::get_pusch_config_f0_0_c_rnti(const ue_cell_configura if (is_csi_report_slot) { csi_report_configuration csi_rep_cfg = create_csi_report_configuration(ue_cell_cfg.cfg_dedicated().csi_meas_cfg.value()); - csi_report_pusch_size csi_size = get_csi_report_pusch_size(csi_rep_cfg); - pusch.nof_csi_part1_bits = csi_size.part1_size.value(); - pusch.max_nof_csi_part2_bits = csi_size.part2_max_size.value(); + // NOTE: The CSI size depends on whether the CSI is configured on PUSCH or PUCCH, as per Section 5.2.3, TS 38.214: + // "For both Type I and Type II reports configured for PUCCH but transmitted on PUSCH, the determination of the + // payload for CSI part 1 and CSI part 2 follows that of PUCCH as described in clause 5.2.4." + if (is_pusch_configured(ue_cell_cfg.cfg_dedicated().csi_meas_cfg.value())) { + csi_report_pusch_size csi_size = get_csi_report_pusch_size(csi_rep_cfg); + pusch.nof_csi_part1_bits = csi_size.part1_size.value(); + pusch.max_nof_csi_part2_bits = csi_size.part2_max_size.value(); + } else { + pusch.nof_csi_part1_bits = get_csi_report_pucch_size(csi_rep_cfg).value(); + } } return pusch; @@ -252,9 +260,16 @@ pusch_config_params srsran::get_pusch_config_f0_1_c_rnti(const ue_cell_configura if (is_csi_report_slot) { csi_report_configuration csi_rep_cfg = create_csi_report_configuration(ue_cell_cfg.cfg_dedicated().csi_meas_cfg.value()); - csi_report_pusch_size csi_size = get_csi_report_pusch_size(csi_rep_cfg); - pusch.nof_csi_part1_bits = csi_size.part1_size.value(); - pusch.max_nof_csi_part2_bits = csi_size.part2_max_size.value(); + // NOTE: The CSI size depends on whether the CSI is configured on PUSCH or PUCCH, as per Section 5.2.3, TS 38.214: + // "For both Type I and Type II reports configured for PUCCH but transmitted on PUSCH, the determination of the + // payload for CSI part 1 and CSI part 2 follows that of PUCCH as described in clause 5.2.4." + if (is_pusch_configured(ue_cell_cfg.cfg_dedicated().csi_meas_cfg.value())) { + csi_report_pusch_size csi_size = get_csi_report_pusch_size(csi_rep_cfg); + pusch.nof_csi_part1_bits = csi_size.part1_size.value(); + pusch.max_nof_csi_part2_bits = csi_size.part2_max_size.value(); + } else { + pusch.nof_csi_part1_bits = get_csi_report_pucch_size(csi_rep_cfg).value(); + } } return pusch; diff --git a/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp b/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp index 8e3273b1b3..e223842c3b 100644 --- a/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp +++ b/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp @@ -47,25 +47,47 @@ static void update_uci_on_pusch_harq_offsets(uci_info::harq_info& uci_harq, cons static void add_csi_to_uci_on_pusch(uci_info::csi_info& uci_csi, const ue_cell_configuration& ue_cell_cfg) { - uci_csi.csi_rep_cfg = create_csi_report_configuration(ue_cell_cfg.cfg_dedicated().csi_meas_cfg.value()); - csi_report_pusch_size csi_size = get_csi_report_pusch_size(uci_csi.csi_rep_cfg); - uci_csi.csi_part1_nof_bits = csi_size.part1_size.value(); + uci_csi.csi_rep_cfg = create_csi_report_configuration(ue_cell_cfg.cfg_dedicated().csi_meas_cfg.value()); - const auto& uci_cfg = ue_cell_cfg.cfg_dedicated().ul_config.value().init_ul_bwp.pusch_cfg.value().uci_cfg.value(); + // NOTE: The CSI size depends on whether the CSI is configured on PUSCH or PUCCH, as per Section 5.2.3, TS 38.214: + // "For both Type I and Type II reports configured for PUCCH but transmitted on PUSCH, the determination of the + // payload for CSI part 1 and CSI part 2 follows that of PUCCH as described in clause 5.2.4." + if (is_pusch_configured(ue_cell_cfg.cfg_dedicated().csi_meas_cfg.value())) { + csi_report_pusch_size csi_size = get_csi_report_pusch_size(uci_csi.csi_rep_cfg); + uci_csi.csi_part1_nof_bits = csi_size.part1_size.value(); - // We assume the configuration contains the values for beta_offsets. - const auto& beta_offsets = variant_get(uci_cfg.beta_offsets_cfg.value()); + const auto& uci_cfg = ue_cell_cfg.cfg_dedicated().ul_config.value().init_ul_bwp.pusch_cfg.value().uci_cfg.value(); + + // We assume the configuration contains the values for beta_offsets. + const auto& beta_offsets = variant_get(uci_cfg.beta_offsets_cfg.value()); + + // The values of \c beta_offsets are set according to Section 9.3, TS 38.213. + if (uci_csi.csi_part1_nof_bits <= 11) { + uci_csi.beta_offset_csi_1 = beta_offsets.beta_offset_csi_p1_idx_1.value(); + } else { + uci_csi.beta_offset_csi_1 = beta_offsets.beta_offset_csi_p1_idx_2.value(); + } + + if (csi_size.part2_min_size.value() > 0U) { + srsran_assert(csi_size.part2_max_size.value() <= 11U, "CSI Part 2 on UCI-PUSCH is only supported up to 11 bits"); + uci_csi.beta_offset_csi_2.emplace(beta_offsets.beta_offset_csi_p2_idx_1.value()); + } - // The values of \c beta_offsets are set according to Section 9.3, TS 38.213. - if (uci_csi.csi_part1_nof_bits <= 11) { - uci_csi.beta_offset_csi_1 = beta_offsets.beta_offset_csi_p1_idx_1.value(); } else { - uci_csi.beta_offset_csi_1 = beta_offsets.beta_offset_csi_p1_idx_2.value(); - } + uci_csi.csi_part1_nof_bits = get_csi_report_pucch_size(uci_csi.csi_rep_cfg).value(); + // NOTE: with PUCCH-configured CSI report, CSI patrt 2 is not supported. + + const auto& uci_cfg = ue_cell_cfg.cfg_dedicated().ul_config.value().init_ul_bwp.pusch_cfg.value().uci_cfg.value(); + + // We assume the configuration contains the values for beta_offsets. + const auto& beta_offsets = variant_get(uci_cfg.beta_offsets_cfg.value()); - if (csi_size.part2_min_size.value() > 0U) { - srsran_assert(csi_size.part2_max_size.value() <= 11U, "CSI Part 2 on UCI-PUSCH is only supported up to 11 bits"); - uci_csi.beta_offset_csi_2.emplace(beta_offsets.beta_offset_csi_p2_idx_1.value()); + // The values of \c beta_offsets are set according to Section 9.3, TS 38.213. + if (uci_csi.csi_part1_nof_bits <= 11) { + uci_csi.beta_offset_csi_1 = beta_offsets.beta_offset_csi_p1_idx_1.value(); + } else { + uci_csi.beta_offset_csi_1 = beta_offsets.beta_offset_csi_p1_idx_2.value(); + } } } @@ -199,11 +221,6 @@ optional uci_allocator_impl::alloc_uci_harq_ue(cell_resource_all } if (csi_helper::is_csi_reporting_slot(ue_cell_cfg.cfg_dedicated(), uci_slot)) { - // NOTE: For TX with more than 2 antenna, we avoid multiplexing HARQ-ACK with CSI in the slots for CSI because the - // CSI report is 11 bit, and the current PUCCH F2 capacity is exactly 11 bits. - if (cell_cfg.dl_carrier.nof_ant > 2U) { - continue; - } // NOTE: This is only to avoid allocating more than 2 HARQ bits in PUCCH that are expected to carry CSI reporting. // TODO: Remove this when the PUCCH allocator handle properly more than 2 HARQ-ACK bits + CSI. if (get_scheduled_pdsch_counter_in_ue_uci(slot_alloc, crnti) >= max_harq_bits_per_uci) { diff --git a/lib/scheduler/ue_scheduling/ue_cell.cpp b/lib/scheduler/ue_scheduling/ue_cell.cpp index 0c9bae58d1..1b4bb71762 100644 --- a/lib/scheduler/ue_scheduling/ue_cell.cpp +++ b/lib/scheduler/ue_scheduling/ue_cell.cpp @@ -133,7 +133,7 @@ grant_prbs_mcs ue_cell::required_ul_prbs(const pusch_time_domain_resource_alloca // differentiate between HARQ-ACK bits and CSI bits, which would be necessary to compute the beta-offset values. // Here, we only need to allocate some extra space. const unsigned uci_bits_overallocation = 20U; - const bool is_csi_report_slot = false; + const bool is_csi_report_slot = false; pusch_config_params pusch_cfg; switch (dci_type) { @@ -142,11 +142,11 @@ grant_prbs_mcs ue_cell::required_ul_prbs(const pusch_time_domain_resource_alloca break; case dci_ul_rnti_config_type::c_rnti_f0_0: pusch_cfg = - get_pusch_config_f0_0_c_rnti(ue_cfg, bwp_ul_cmn, pusch_td_cfg, uci_bits_overallocation, is_csi_report_slot); + get_pusch_config_f0_0_c_rnti(*ue_cfg, bwp_ul_cmn, pusch_td_cfg, uci_bits_overallocation, is_csi_report_slot); break; case dci_ul_rnti_config_type::c_rnti_f0_1: pusch_cfg = get_pusch_config_f0_1_c_rnti( - ue_cfg, pusch_td_cfg, channel_state.get_nof_ul_layers(), uci_bits_overallocation, is_csi_report_slot); + *ue_cfg, pusch_td_cfg, channel_state.get_nof_ul_layers(), uci_bits_overallocation, is_csi_report_slot); break; default: report_fatal_error("Unsupported PDCCH DCI UL format"); diff --git a/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp b/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp index 1f5354875c..c58bb8b4e2 100644 --- a/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp +++ b/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp @@ -516,17 +516,6 @@ alloc_outcome ue_cell_grid_allocator::allocate_ul_grant(const ue_pusch_grant& gr return alloc_outcome::skip_slot; } - const bool is_csi_report_slot = - csi_helper::is_csi_reporting_slot(u.get_pcell().cfg().cfg_dedicated(), pusch_alloc.slot); - - // We skip allocation of PUSCH in the slots with the CSI reporting over PUCCH. - if (is_csi_report_slot and cell_cfg.dl_carrier.nof_ant > 1U) { - logger.debug("rnti={} Allocation of PUSCH in slot={} skipped. Cause: this slot is for CSI reporting over PUCCH", - u.crnti, - pusch_alloc.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", @@ -593,6 +582,9 @@ alloc_outcome ue_cell_grid_allocator::allocate_ul_grant(const ue_pusch_grant& gr const unsigned nof_harq_ack_bits = get_uci_alloc(grant.cell_index).get_scheduled_pdsch_counter_in_ue_uci(pusch_alloc, u.crnti); + const bool is_csi_report_slot = + csi_helper::is_csi_reporting_slot(u.get_pcell().cfg().cfg_dedicated(), pusch_alloc.slot); + // Fetch PUSCH parameters based on type of transmission. pusch_config_params pusch_cfg; switch (dci_type) { diff --git a/tests/unittests/scheduler/uci_and_pucch/uci_allocator_test.cpp b/tests/unittests/scheduler/uci_and_pucch/uci_allocator_test.cpp index 18b4fccc4c..df82b96122 100644 --- a/tests/unittests/scheduler/uci_and_pucch/uci_allocator_test.cpp +++ b/tests/unittests/scheduler/uci_and_pucch/uci_allocator_test.cpp @@ -541,8 +541,8 @@ TEST_F(test_uci_allocator_mimo_4x4, uci_alloc_csi_part2_over_existing_pusch) ASSERT_TRUE(slot_grid.result.ul.puschs.back().uci.has_value()); ASSERT_FALSE(slot_grid.result.ul.puschs.back().uci.value().harq.has_value()); ASSERT_TRUE(slot_grid.result.ul.puschs.back().uci.value().csi.has_value()); - ASSERT_EQ(6, slot_grid.result.ul.puschs.back().uci.value().csi.value().csi_part1_nof_bits); - ASSERT_TRUE(slot_grid.result.ul.puschs.back().uci.value().csi.value().beta_offset_csi_2.has_value()); + ASSERT_EQ(11, slot_grid.result.ul.puschs.back().uci.value().csi.value().csi_part1_nof_bits); + ASSERT_FALSE(slot_grid.result.ul.puschs.back().uci.value().csi.value().beta_offset_csi_2.has_value()); } TEST_F(test_uci_allocator_mimo_4x4, uci_mplex_csi_part2_over_existing_pusch) @@ -573,7 +573,7 @@ TEST_F(test_uci_allocator_mimo_4x4, uci_mplex_csi_part2_over_existing_pusch) ASSERT_TRUE(slot_grid.result.ul.puschs.back().uci.has_value()); ASSERT_FALSE(slot_grid.result.ul.puschs.back().uci.value().harq.has_value()); ASSERT_TRUE(slot_grid.result.ul.puschs.back().uci.value().csi.has_value()); - ASSERT_EQ(6, slot_grid.result.ul.puschs.back().uci.value().csi.value().csi_part1_nof_bits); - ASSERT_TRUE(slot_grid.result.ul.puschs.back().uci.value().csi.value().beta_offset_csi_2.has_value()); + ASSERT_EQ(11, slot_grid.result.ul.puschs.back().uci.value().csi.value().csi_part1_nof_bits); + ASSERT_FALSE(slot_grid.result.ul.puschs.back().uci.value().csi.value().beta_offset_csi_2.has_value()); ASSERT_TRUE(check_pusch_out_param(slot_grid.result.ul.puschs.back())); -} \ No newline at end of file +} diff --git a/tests/unittests/scheduler/ue_scheduling/ta_manager_test.cpp b/tests/unittests/scheduler/ue_scheduling/ta_manager_test.cpp index 07af23b012..e8eaa1e273 100644 --- a/tests/unittests/scheduler/ue_scheduling/ta_manager_test.cpp +++ b/tests/unittests/scheduler/ue_scheduling/ta_manager_test.cpp @@ -8,8 +8,8 @@ * */ -#include "../../../../lib/scheduler/ue_scheduling/dl_logical_channel_manager.h" -#include "../../../../lib/scheduler/ue_scheduling/ta_manager.h" +#include "lib/scheduler/ue_scheduling/dl_logical_channel_manager.h" +#include "lib/scheduler/ue_scheduling/ta_manager.h" #include "tests/unittests/scheduler/test_utils/config_generators.h" #include "tests/unittests/scheduler/test_utils/indication_generators.h" #include "srsran/ran/duplex_mode.h" diff --git a/tests/unittests/scheduler/ue_scheduling/ue_harq_link_adaptation_test.cpp b/tests/unittests/scheduler/ue_scheduling/ue_harq_link_adaptation_test.cpp index 82fc133622..db1e2b9fe2 100644 --- a/tests/unittests/scheduler/ue_scheduling/ue_harq_link_adaptation_test.cpp +++ b/tests/unittests/scheduler/ue_scheduling/ue_harq_link_adaptation_test.cpp @@ -8,9 +8,9 @@ * */ -#include "../../../../lib/scheduler/ue_scheduling/ue.h" #include "../test_utils/config_generators.h" #include "../test_utils/dummy_test_components.h" +#include "lib/scheduler/ue_scheduling/ue.h" #include using namespace srsran; From b9588733cb9a3218c6bc385eabf17b59a317d6e5 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Mon, 8 Jan 2024 21:22:13 +0100 Subject: [PATCH 074/134] support: make byte_buffer::append no discard --- include/srsran/adt/byte_buffer.h | 228 +++--------------- include/srsran/psup/psup_packing.h | 2 +- .../fixed_size_memory_block_pool.h | 2 +- lib/asn1/asn1_utils.cpp | 11 +- lib/psup/psup_packing.cpp | 7 +- lib/support/byte_buffer.cpp | 201 ++++++++++++++- .../benchmarks/du_high/du_high_benchmark.cpp | 14 +- .../udp_network_gateway_benchmark.cpp | 6 +- tests/benchmarks/pdcp/pdcp_rx_benchmark.cpp | 4 +- tests/benchmarks/pdcp/pdcp_tx_benchmark.cpp | 2 +- tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp | 4 +- .../rlc/rlc_handle_status_report.cpp | 2 +- .../integrationtests/rlc/rlc_stress_test_f1.h | 2 +- .../rlc/rlc_stress_test_traffic.cpp | 2 +- .../unittests/adt/byte_buffer_chain_test.cpp | 2 +- tests/unittests/adt/byte_buffer_test.cpp | 6 +- tests/unittests/asn1/asn1_utils_test.cpp | 6 +- .../procedures/ue_configuration_test.cpp | 4 +- .../f1u/cu_up/f1u_cu_up_bearer_test.cpp | 5 +- tests/unittests/f1u/du/f1u_du_bearer_test.cpp | 5 +- tests/unittests/gateways/test_helpers.h | 5 +- .../gtpu/gtpu_tunnel_ngu_rx_test.cpp | 42 ++-- .../mac/dl_sch_pdu_assembler_test.cpp | 8 +- tests/unittests/mac/mac_test_helpers.h | 2 +- tests/unittests/pcap/rlc_pcap_test.cpp | 5 +- tests/unittests/pdcp/pdcp_rx_metrics_test.cpp | 2 +- tests/unittests/pdcp/pdcp_rx_test.cpp | 2 +- tests/unittests/rlc/rlc_rx_am_test.cpp | 6 +- tests/unittests/rlc/rlc_sdu_queue_test.cpp | 16 +- tests/unittests/rlc/rlc_test_helpers.h | 2 +- tests/unittests/rlc/rlc_um_test.cpp | 26 +- .../support/fixed_size_memory_pool_test.cpp | 1 + 32 files changed, 338 insertions(+), 294 deletions(-) diff --git a/include/srsran/adt/byte_buffer.h b/include/srsran/adt/byte_buffer.h index b830614614..86e1955c5a 100644 --- a/include/srsran/adt/byte_buffer.h +++ b/include/srsran/adt/byte_buffer.h @@ -210,116 +210,34 @@ class byte_buffer /// Append bytes of a iterator range. template - void append(Iterator begin, Iterator end) + bool append(Iterator begin, Iterator end) { static_assert(std::is_same, uint8_t>::value or std::is_same, const uint8_t>::value, "Iterator value type is not uint8_t"); // TODO: use segment-wise copy if it is a span. for (auto it = begin; it != end; ++it) { - append(*it); - } - } - - /// Appends bytes to the byte buffer. This function may retrieve new segments from a memory pool. - bool append(span bytes) - { - if (empty() and not bytes.empty()) { - if (not append_segment(DEFAULT_FIRST_SEGMENT_HEADROOM)) { + if (not append(*it)) { return false; } } - // segment-wise copy. - for (size_t count = 0; count < bytes.size();) { - if (ctrl_blk_ptr->segments.tail->tailroom() == 0) { - if (not append_segment(0)) { - return false; - } - } - size_t to_write = std::min(ctrl_blk_ptr->segments.tail->tailroom(), bytes.size() - count); - span subspan = bytes.subspan(count, to_write); - ctrl_blk_ptr->segments.tail->append(subspan); - count += to_write; - ctrl_blk_ptr->pkt_len += to_write; - } return true; } + /// Appends bytes to the byte buffer. This function may retrieve new segments from a memory pool. + bool append(span bytes); + /// Appends an initializer list of bytes. void append(const std::initializer_list& bytes) { append(span{bytes.begin(), bytes.size()}); } /// Appends bytes from another byte_buffer. This function may allocate new segments. - SRSRAN_NODISCARD bool append(const byte_buffer& other) - { - srsran_assert(&other != this, "Self-append not supported"); - if (empty() and not other.empty()) { - if (not append_segment(other.ctrl_blk_ptr->segments.head->headroom())) { - return false; - } - } - for (node_t* seg = other.ctrl_blk_ptr->segments.head; seg != nullptr; seg = seg->next) { - auto other_it = seg->begin(); - while (other_it != seg->end()) { - if (ctrl_blk_ptr->segments.tail->tailroom() == 0) { - if (not append_segment(0)) { - return false; - } - } - auto to_append = - std::min(seg->end() - other_it, (iterator::difference_type)ctrl_blk_ptr->segments.tail->tailroom()); - ctrl_blk_ptr->segments.tail->append(other_it, other_it + to_append); - other_it += to_append; - } - ctrl_blk_ptr->pkt_len += seg->length(); - } - return true; - } + SRSRAN_NODISCARD bool append(const byte_buffer& other); /// Appends bytes from another rvalue byte_buffer. This function may allocate new segments. - bool append(byte_buffer&& other) - { - srsran_assert(&other != this, "Self-append not supported"); - if (other.empty()) { - return true; - } - if (empty()) { - *this = std::move(other); - return true; - } - if (not other.ctrl_blk_ptr.unique()) { - // Use lvalue append. - return append(other); - } - // This is the last reference to "after". Shallow copy, except control segment. - node_t* node = create_segment(0); - if (node == nullptr) { - return false; - } - node->append(span{other.ctrl_blk_ptr->segments.head->data(), - other.ctrl_blk_ptr->segment_in_cb_memory_block->length()}); - ctrl_blk_ptr->pkt_len += other.ctrl_blk_ptr->pkt_len; - node_t* last_tail = ctrl_blk_ptr->segments.tail; - last_tail->next = other.ctrl_blk_ptr->segments.head; - ctrl_blk_ptr->segments.tail = other.ctrl_blk_ptr->segments.tail; - node->next = other.ctrl_blk_ptr->segment_in_cb_memory_block->next; - if (other.ctrl_blk_ptr->segment_in_cb_memory_block == other.ctrl_blk_ptr->segments.tail) { - ctrl_blk_ptr->segments.tail = node; - } - for (node_t* seg = last_tail; seg->next != nullptr; seg = seg->next) { - if (seg->next == other.ctrl_blk_ptr->segment_in_cb_memory_block) { - seg->next = node; - break; - } - } - other.ctrl_blk_ptr->segments.head = other.ctrl_blk_ptr->segment_in_cb_memory_block; - other.ctrl_blk_ptr->segments.tail = other.ctrl_blk_ptr->segment_in_cb_memory_block; - other.ctrl_blk_ptr->segments.head->next = nullptr; - other.ctrl_blk_ptr.reset(); - return true; - } + SRSRAN_NODISCARD bool append(byte_buffer&& other); /// Appends bytes to the byte buffer. This function may allocate new segments. - bool append(uint8_t byte) + SRSRAN_NODISCARD bool append(uint8_t byte) { if (empty() or ctrl_blk_ptr->segments.tail->tailroom() == 0) { if (not append_segment(DEFAULT_FIRST_SEGMENT_HEADROOM)) { @@ -366,53 +284,12 @@ class byte_buffer void clear() { ctrl_blk_ptr.reset(); } /// Removes "nof_bytes" from the head of the byte_buffer. - void trim_head(size_t nof_bytes) - { - srsran_assert(length() >= nof_bytes, "Trying to trim more bytes than those available"); - for (size_t trimmed = 0; trimmed != nof_bytes;) { - size_t to_trim = std::min(nof_bytes - trimmed, ctrl_blk_ptr->segments.head->length()); - ctrl_blk_ptr->segments.head->trim_head(to_trim); - ctrl_blk_ptr->pkt_len -= to_trim; - trimmed += to_trim; - if (ctrl_blk_ptr->segments.head->length() == 0) { - // Remove the first segment. - ctrl_blk_ptr->segments.head = ctrl_blk_ptr->segments.head->next; - } - } - } + void trim_head(size_t nof_bytes); /// \brief Remove "nof_bytes" bytes at the end of the byte_buffer. /// If the length is greater than the length of the last segment, the function will fail and return -1 without /// modifying the byte_buffer. - void trim_tail(size_t nof_bytes) - { - srsran_assert(length() >= nof_bytes, "Trimming too many bytes from byte_buffer"); - if (nof_bytes == 0) { - return; - } - - if (ctrl_blk_ptr->segments.tail->length() >= nof_bytes) { - // Simplest scenario where the last segment is larger than the number of bytes to trim. - ctrl_blk_ptr->segments.tail->trim_tail(nof_bytes); - ctrl_blk_ptr->pkt_len -= nof_bytes; - if (ctrl_blk_ptr->segments.tail->length() == 0) { - pop_last_segment(); - } - return; - } - size_t new_len = length() - nof_bytes; - node_t* seg = ctrl_blk_ptr->segments.head; - for (size_t count = 0; seg != nullptr; seg = seg->next) { - if (count + seg->length() >= new_len) { - seg->next = nullptr; - seg->resize(new_len - count); - ctrl_blk_ptr->segments.tail = seg; - ctrl_blk_ptr->pkt_len = new_len; - break; - } - count += seg->length(); - } - } + void trim_tail(size_t nof_bytes); /// Checks whether byte_buffer is empty. bool empty() const { return length() == 0; } @@ -443,61 +320,10 @@ class byte_buffer bool is_contiguous() const { return empty() or ctrl_blk_ptr->segments.head == ctrl_blk_ptr->segments.tail; } /// Moves the bytes stored in different segments of the byte_buffer into first segment. - bool linearize() - { - if (is_contiguous()) { - return true; - } - size_t sz = length(); - if (sz > ctrl_blk_ptr->segments.head->capacity() - ctrl_blk_ptr->segments.head->headroom()) { - return false; - } - for (node_t* seg = ctrl_blk_ptr->segments.head->next; seg != nullptr;) { - node_t* next = seg->next; - ctrl_blk_ptr->segments.head->append(seg->begin(), seg->end()); - ctrl_blk_ptr->destroy_node(seg); - seg = next; - } - ctrl_blk_ptr->segments.head->next = nullptr; - ctrl_blk_ptr->segments.tail = ctrl_blk_ptr->segments.head; - return true; - } + bool linearize(); /// Set byte_buffer length. Note: It doesn't initialize newly created bytes. - bool resize(size_t new_sz) - { - size_t prev_len = length(); - if (new_sz == prev_len) { - return true; - } - if (new_sz > prev_len) { - for (size_t to_add = new_sz - prev_len; to_add > 0;) { - if (empty() or ctrl_blk_ptr->segments.tail->tailroom() == 0) { - if (not append_segment(0)) { - return false; - } - } - size_t added = std::min(ctrl_blk_ptr->segments.tail->tailroom(), to_add); - ctrl_blk_ptr->segments.tail->resize(added); - to_add -= added; - } - } else { - size_t count = 0; - for (node_t* seg = ctrl_blk_ptr->segments.head; count < new_sz; seg = seg->next) { - size_t new_seg_len = std::min(seg->length(), new_sz - count); - if (new_seg_len != seg->length()) { - seg->resize(new_seg_len); - } - count += new_seg_len; - if (count == new_sz) { - seg->next = nullptr; - ctrl_blk_ptr->segments.tail = seg; - } - } - } - ctrl_blk_ptr->pkt_len = new_sz; - return true; - } + bool resize(size_t new_sz); /// Returns a non-owning list of segments that compose the byte_buffer. byte_buffer_segment_span_range segments() @@ -533,13 +359,15 @@ class byte_buffer } private: - node_t* create_head_segment(size_t headroom); + bool has_ctrl_block() const { return ctrl_blk_ptr != nullptr; } - static node_t* create_segment(size_t headroom); + SRSRAN_NODISCARD node_t* create_head_segment(size_t headroom); - bool append_segment(size_t headroom_suggestion); + static SRSRAN_NODISCARD node_t* create_segment(size_t headroom); - bool prepend_segment(size_t headroom_suggestion); + SRSRAN_NODISCARD bool append_segment(size_t headroom_suggestion); + + SRSRAN_NODISCARD bool prepend_segment(size_t headroom_suggestion); /// \brief Removes last segment of the byte_buffer. /// Note: This operation is O(N), as it requires recomputing the tail. @@ -738,13 +566,7 @@ class byte_buffer_writer byte_buffer_view view() const { return *buffer; } /// Appends bytes. - void append(byte_buffer_view bytes) - { - // TODO: do batch append. - for (uint8_t byte : bytes) { - buffer->append(byte); - } - } + bool append(byte_buffer_view bytes) { return buffer->append(bytes); } /// Appends initializer list of bytes. void append(const std::initializer_list& bytes) @@ -758,12 +580,15 @@ class byte_buffer_writer /// Appends single byte. SRSRAN_NODISCARD bool append(uint8_t byte) { return buffer->append(byte); } - void append_zeros(size_t nof_zeros) + SRSRAN_NODISCARD bool append_zeros(size_t nof_zeros) { // TODO: optimize. for (size_t i = 0; i < nof_zeros; ++i) { - buffer->append(0); + if (not buffer->append(0)) { + return false; + } } + return true; } /// Checks last appended byte. @@ -787,7 +612,10 @@ inline byte_buffer make_byte_buffer(const std::string& hex_str) for (size_t i = 0; i < hex_str.size(); i += 2) { uint8_t val; sscanf(hex_str.data() + i, "%02hhX", &val); - ret.append(val); + if (not ret.append(val)) { + ret.clear(); + break; + } } return ret; } diff --git a/include/srsran/psup/psup_packing.h b/include/srsran/psup/psup_packing.h index 3a5576693d..f454846079 100644 --- a/include/srsran/psup/psup_packing.h +++ b/include/srsran/psup/psup_packing.h @@ -26,7 +26,7 @@ class psup_packing psup_packing(srslog::basic_logger& logger_) : logger(logger_) {} bool unpack(psup_dl_pdu_session_information& dl_pdu_session_information, byte_buffer_view container) const; - void pack(byte_buffer& out_buf, const psup_dl_pdu_session_information& dl_pdu_session_information) const; + bool pack(byte_buffer& out_buf, const psup_dl_pdu_session_information& dl_pdu_session_information) const; private: srslog::basic_logger& logger; 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 6835e2c555..514ad092e4 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 @@ -195,7 +195,7 @@ class fixed_size_memory_block_pool } fmt::print("There are {}/{} buffers in central memory block cache. This thread contains {} in its local cache.\n", - central_mem_cache.size(), + central_mem_cache.size() * block_batch_size, nof_memory_blocks(), count); } diff --git a/lib/asn1/asn1_utils.cpp b/lib/asn1/asn1_utils.cpp index 91f20cdd25..33fa78a401 100644 --- a/lib/asn1/asn1_utils.cpp +++ b/lib/asn1/asn1_utils.cpp @@ -941,7 +941,10 @@ void octet_string_helper::to_octet_string(srsran::byte_buffer& buf, uint64_t num buf.clear(); size_t nbytes = sizeof(number); for (uint32_t i = 0; i < nbytes; ++i) { - buf.append((number >> (uint64_t)((nbytes - 1 - i) * 8U)) & 0xffu); + if (not buf.append((number >> (uint64_t)((nbytes - 1 - i) * 8U)) & 0xffu)) { + log_error("Failed to append octet string byte to buffer"); + return; + } } } @@ -998,7 +1001,9 @@ void octet_string_helper::append_hex_string(byte_buffer& buf, const std::string& char cstr[] = "\0\0\0"; for (unsigned i = 0; i < str.size(); i += 2) { memcpy(&cstr[0], &str[i], 2); - buf.append(strtoul(cstr, nullptr, 16)); + if (not buf.append(strtoul(cstr, nullptr, 16))) { + log_error("Failed to append octet string byte to buffer"); + } } } @@ -1041,7 +1046,7 @@ SRSASN_CODE unbounded_octstring::unpack(cbit_ref& bref) for (unsigned i = 0; i != len; ++i) { uint8_t b; HANDLE_CODE(bref.unpack(b, 8)); - append(b); + HANDLE_CODE(append(b) ? SRSASN_SUCCESS : SRSASN_ERROR_DECODE_FAIL); } return SRSASN_SUCCESS; } diff --git a/lib/psup/psup_packing.cpp b/lib/psup/psup_packing.cpp index f0639bdf0d..c208930ff9 100644 --- a/lib/psup/psup_packing.cpp +++ b/lib/psup/psup_packing.cpp @@ -87,7 +87,7 @@ bool psup_packing::unpack(psup_dl_pdu_session_information& dl_pdu_session_inform return true; } -void psup_packing::pack(byte_buffer& out_buf, const psup_dl_pdu_session_information& dl_pdu_session_information) const +bool psup_packing::pack(byte_buffer& out_buf, const psup_dl_pdu_session_information& dl_pdu_session_information) const { size_t start_len = out_buf.length(); bit_encoder encoder{out_buf}; @@ -132,8 +132,11 @@ void psup_packing::pack(byte_buffer& out_buf, const psup_dl_pdu_session_informat // Add padding such that length is (n*4-2) octets, where n is a positive integer. while (((out_buf.length() - start_len) + 2) % 4) { - out_buf.append(0x0); + if (not out_buf.append(0x0)) { + return false; + } } + return true; } } // namespace srsran diff --git a/lib/support/byte_buffer.cpp b/lib/support/byte_buffer.cpp index abb9f9753e..723de10726 100644 --- a/lib/support/byte_buffer.cpp +++ b/lib/support/byte_buffer.cpp @@ -138,6 +138,98 @@ byte_buffer::control_block::~control_block() } } +bool byte_buffer::append(span bytes) +{ + if (bytes.empty()) { + // no bytes to append. + return true; + } + if (not has_ctrl_block() and not append_segment(DEFAULT_FIRST_SEGMENT_HEADROOM)) { + // failed to allocate head segment. + return false; + } + + // segment-wise copy. + for (size_t count = 0; count < bytes.size();) { + if (ctrl_blk_ptr->segments.tail->tailroom() == 0 and not append_segment(0)) { + return false; + } + size_t to_write = std::min(ctrl_blk_ptr->segments.tail->tailroom(), bytes.size() - count); + span subspan = bytes.subspan(count, to_write); + ctrl_blk_ptr->segments.tail->append(subspan); + count += to_write; + ctrl_blk_ptr->pkt_len += to_write; + } + return true; +} + +bool byte_buffer::append(const byte_buffer& other) +{ + srsran_assert(&other != this, "Self-append not supported"); + if (other.empty()) { + return true; + } + if (not has_ctrl_block() and not append_segment(other.ctrl_blk_ptr->segments.head->headroom())) { + return false; + } + for (node_t* seg = other.ctrl_blk_ptr->segments.head; seg != nullptr; seg = seg->next) { + auto other_it = seg->begin(); + while (other_it != seg->end()) { + if (ctrl_blk_ptr->segments.tail->tailroom() == 0 and not append_segment(0)) { + return false; + } + auto to_append = + std::min(seg->end() - other_it, (iterator::difference_type)ctrl_blk_ptr->segments.tail->tailroom()); + ctrl_blk_ptr->segments.tail->append(other_it, other_it + to_append); + other_it += to_append; + } + ctrl_blk_ptr->pkt_len += seg->length(); + } + return true; +} + +bool byte_buffer::append(byte_buffer&& other) +{ + srsran_assert(&other != this, "Self-append not supported"); + if (other.empty()) { + return true; + } + if (empty()) { + *this = std::move(other); + return true; + } + if (not other.ctrl_blk_ptr.unique()) { + // Use lvalue append. + return append(other); + } + // This is the last reference to "after". Shallow copy, except control segment. + node_t* node = create_segment(0); + if (node == nullptr) { + return false; + } + node->append(span{other.ctrl_blk_ptr->segments.head->data(), + other.ctrl_blk_ptr->segment_in_cb_memory_block->length()}); + ctrl_blk_ptr->pkt_len += other.ctrl_blk_ptr->pkt_len; + node_t* last_tail = ctrl_blk_ptr->segments.tail; + last_tail->next = other.ctrl_blk_ptr->segments.head; + ctrl_blk_ptr->segments.tail = other.ctrl_blk_ptr->segments.tail; + node->next = other.ctrl_blk_ptr->segment_in_cb_memory_block->next; + if (other.ctrl_blk_ptr->segment_in_cb_memory_block == other.ctrl_blk_ptr->segments.tail) { + ctrl_blk_ptr->segments.tail = node; + } + for (node_t* seg = last_tail; seg->next != nullptr; seg = seg->next) { + if (seg->next == other.ctrl_blk_ptr->segment_in_cb_memory_block) { + seg->next = node; + break; + } + } + other.ctrl_blk_ptr->segments.head = other.ctrl_blk_ptr->segment_in_cb_memory_block; + other.ctrl_blk_ptr->segments.tail = other.ctrl_blk_ptr->segment_in_cb_memory_block; + other.ctrl_blk_ptr->segments.head->next = nullptr; + other.ctrl_blk_ptr.reset(); + return true; +} + byte_buffer::node_t* byte_buffer::create_head_segment(size_t headroom) { static auto& pool = detail::get_default_byte_buffer_segment_pool(); @@ -189,7 +281,8 @@ byte_buffer::node_t* byte_buffer::create_segment(size_t headroom) bool byte_buffer::append_segment(size_t headroom_suggestion) { - node_t* segment = empty() ? create_head_segment(headroom_suggestion) : create_segment(headroom_suggestion); + node_t* segment = + not has_ctrl_block() ? create_head_segment(headroom_suggestion) : create_segment(headroom_suggestion); if (segment == nullptr) { return false; } @@ -202,7 +295,8 @@ bool byte_buffer::append_segment(size_t headroom_suggestion) bool byte_buffer::prepend_segment(size_t headroom_suggestion) { // Note: Add HEADROOM for first segment. - node_t* segment = empty() ? create_head_segment(headroom_suggestion) : create_segment(headroom_suggestion); + node_t* segment = + not has_ctrl_block() ? create_head_segment(headroom_suggestion) : create_segment(headroom_suggestion); if (segment == nullptr) { return false; } @@ -264,8 +358,7 @@ bool byte_buffer::prepend(byte_buffer&& other) } if (empty()) { // the byte buffer is empty. Prepending is the same as appending. - append(std::move(other)); - return true; + return append(std::move(other)); } if (not other.ctrl_blk_ptr.unique()) { // Deep copy of segments. @@ -317,6 +410,106 @@ byte_buffer_view byte_buffer::reserve_prepend(size_t nof_bytes) return byte_buffer_view{begin(), begin() + nof_bytes}; } +void byte_buffer::trim_head(size_t nof_bytes) +{ + srsran_assert(length() >= nof_bytes, "Trying to trim more bytes than those available"); + for (size_t trimmed = 0; trimmed != nof_bytes;) { + size_t to_trim = std::min(nof_bytes - trimmed, ctrl_blk_ptr->segments.head->length()); + ctrl_blk_ptr->segments.head->trim_head(to_trim); + ctrl_blk_ptr->pkt_len -= to_trim; + trimmed += to_trim; + if (ctrl_blk_ptr->segments.head->length() == 0) { + // Remove the first segment. + ctrl_blk_ptr->segments.head = ctrl_blk_ptr->segments.head->next; + } + } +} + +void byte_buffer::trim_tail(size_t nof_bytes) +{ + srsran_assert(length() >= nof_bytes, "Trimming too many bytes from byte_buffer"); + if (nof_bytes == 0) { + return; + } + + if (ctrl_blk_ptr->segments.tail->length() >= nof_bytes) { + // Simplest scenario where the last segment is larger than the number of bytes to trim. + ctrl_blk_ptr->segments.tail->trim_tail(nof_bytes); + ctrl_blk_ptr->pkt_len -= nof_bytes; + if (ctrl_blk_ptr->segments.tail->length() == 0) { + pop_last_segment(); + } + return; + } + size_t new_len = length() - nof_bytes; + node_t* seg = ctrl_blk_ptr->segments.head; + for (size_t count = 0; seg != nullptr; seg = seg->next) { + if (count + seg->length() >= new_len) { + seg->next = nullptr; + seg->resize(new_len - count); + ctrl_blk_ptr->segments.tail = seg; + ctrl_blk_ptr->pkt_len = new_len; + break; + } + count += seg->length(); + } +} + +bool byte_buffer::linearize() +{ + if (is_contiguous()) { + return true; + } + size_t sz = length(); + if (sz > ctrl_blk_ptr->segments.head->capacity() - ctrl_blk_ptr->segments.head->headroom()) { + return false; + } + for (node_t* seg = ctrl_blk_ptr->segments.head->next; seg != nullptr;) { + node_t* next = seg->next; + ctrl_blk_ptr->segments.head->append(seg->begin(), seg->end()); + ctrl_blk_ptr->destroy_node(seg); + seg = next; + } + ctrl_blk_ptr->segments.head->next = nullptr; + ctrl_blk_ptr->segments.tail = ctrl_blk_ptr->segments.head; + return true; +} + +bool byte_buffer::resize(size_t new_sz) +{ + size_t prev_len = length(); + if (new_sz == prev_len) { + return true; + } + if (new_sz > prev_len) { + for (size_t to_add = new_sz - prev_len; to_add > 0;) { + if (empty() or ctrl_blk_ptr->segments.tail->tailroom() == 0) { + if (not append_segment(0)) { + return false; + } + } + size_t added = std::min(ctrl_blk_ptr->segments.tail->tailroom(), to_add); + ctrl_blk_ptr->segments.tail->resize(added); + to_add -= added; + } + } else { + size_t count = 0; + for (node_t* seg = ctrl_blk_ptr->segments.head; count < new_sz; seg = seg->next) { + size_t new_seg_len = std::min(seg->length(), new_sz - count); + if (new_seg_len != seg->length()) { + seg->resize(new_seg_len); + } + count += new_seg_len; + if (count == new_sz) { + seg->next = nullptr; + ctrl_blk_ptr->segments.tail = seg; + } + } + } + ctrl_blk_ptr->pkt_len = new_sz; + return true; +} + void byte_buffer::warn_alloc_failure() { static srslog::basic_logger& logger = srslog::fetch_basic_logger("ALL"); diff --git a/tests/benchmarks/du_high/du_high_benchmark.cpp b/tests/benchmarks/du_high/du_high_benchmark.cpp index 2c481495aa..0d41aeac12 100644 --- a/tests/benchmarks/du_high/du_high_benchmark.cpp +++ b/tests/benchmarks/du_high/du_high_benchmark.cpp @@ -513,7 +513,7 @@ class du_high_bench } } // Append the LBSR buffer size to the BSR subPDU. - bsr_mac_subpdu.append(lbsr_buff_sz); + report_fatal_error_if_not(bsr_mac_subpdu.append(lbsr_buff_sz), "Failed to allocate PDU"); // Instantiate a DU-high object. cfg.gnb_du_id = 1; @@ -829,15 +829,15 @@ class du_high_bench mac_rx_pdu rx_pdu{pusch.pusch_cfg.rnti, 0, pusch.pusch_cfg.harq_id, {}}; // Pack header and payload length. if (payload_len > 255) { - rx_pdu.pdu.append(0x40 | drb_lcid); - rx_pdu.pdu.append((payload_len & 0xff00) >> 8); - rx_pdu.pdu.append(payload_len & 0x00ff); + report_fatal_error_if_not(rx_pdu.pdu.append(0x40 | drb_lcid), "Failed to allocate PDU"); + report_fatal_error_if_not(rx_pdu.pdu.append((payload_len & 0xff00) >> 8), "Failed to allocate PDU"); + report_fatal_error_if_not(rx_pdu.pdu.append(payload_len & 0x00ff), "Failed to allocate PDU"); } else { - rx_pdu.pdu.append(drb_lcid); - rx_pdu.pdu.append(payload_len & 0x00ff); + report_fatal_error_if_not(rx_pdu.pdu.append(drb_lcid), "Failed to allocate PDU"); + report_fatal_error_if_not(rx_pdu.pdu.append(payload_len & 0x00ff), "Failed to allocate PDU"); } static const uint8_t rlc_um_complete_pdu_header = 0x00; - rx_pdu.pdu.append(rlc_um_complete_pdu_header); + report_fatal_error_if_not(rx_pdu.pdu.append(rlc_um_complete_pdu_header), "Failed to allocate PDU"); // Exclude RLC header from payload length. rx_pdu.pdu.append(mac_pdu.begin(), mac_pdu.begin() + (payload_len - 1)); // Append Long BSR bytes. diff --git a/tests/benchmarks/gateways/udp_network_gateway_benchmark.cpp b/tests/benchmarks/gateways/udp_network_gateway_benchmark.cpp index d450259fee..d549f03c1c 100644 --- a/tests/benchmarks/gateways/udp_network_gateway_benchmark.cpp +++ b/tests/benchmarks/gateways/udp_network_gateway_benchmark.cpp @@ -103,14 +103,16 @@ class dummy_network_gateway_data_notifier_with_src_addr : public network_gateway std::chrono::microseconds t_min = std::chrono::microseconds::max(); std::chrono::microseconds t_max = std::chrono::microseconds::min(); std::chrono::microseconds t_sum = std::chrono::microseconds::zero(); - ; }; byte_buffer make_tx_byte_buffer(uint32_t length) { byte_buffer pdu{}; for (uint32_t i = 0; i < length; ++i) { - pdu.append((uint8_t)i); + if (not pdu.append((uint8_t)i)) { + pdu.clear(); + break; + } } return pdu; } diff --git a/tests/benchmarks/pdcp/pdcp_rx_benchmark.cpp b/tests/benchmarks/pdcp/pdcp_rx_benchmark.cpp index bcc4a81e30..555c3d7b5e 100644 --- a/tests/benchmarks/pdcp/pdcp_rx_benchmark.cpp +++ b/tests/benchmarks/pdcp/pdcp_rx_benchmark.cpp @@ -130,7 +130,7 @@ std::vector gen_pdu_list(security::integrity_enabled int_en for (int i = 0; i < num_sdus; i++) { byte_buffer sdu_buf = {}; for (int j = 0; j < num_bytes; ++j) { - sdu_buf.append(rand()); + report_error_if_not(sdu_buf.append(rand()), "Failed to allocate SDU"); } pdcp_tx->handle_sdu(std::move(sdu_buf)); } @@ -195,7 +195,7 @@ void benchmark_pdcp_rx(bench_params params, for (int i = 0; i < num_sdus; i++) { byte_buffer sdu_buf = {}; for (int j = 0; j < num_bytes; ++j) { - sdu_buf.append(rand()); + report_error_if_not(sdu_buf.append(rand()), "Failed to allocate SDU"); } sdu_list.push_back(std::move(sdu_buf)); } diff --git a/tests/benchmarks/pdcp/pdcp_tx_benchmark.cpp b/tests/benchmarks/pdcp/pdcp_tx_benchmark.cpp index 7b28d99b80..e328a8db85 100644 --- a/tests/benchmarks/pdcp/pdcp_tx_benchmark.cpp +++ b/tests/benchmarks/pdcp/pdcp_tx_benchmark.cpp @@ -119,7 +119,7 @@ void benchmark_pdcp_tx(security::integrity_enabled int_enabled, for (int i = 0; i < num_sdus; i++) { byte_buffer sdu_buf = {}; for (int j = 0; j < num_bytes; ++j) { - sdu_buf.append(rand()); + report_fatal_error_if_not(sdu_buf.append(rand()), "Failed to allocate SDU buffer"); } sdu_list.push_back(std::move(sdu_buf)); } diff --git a/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp b/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp index fa275204c9..2c91d00a05 100644 --- a/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp +++ b/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp @@ -152,7 +152,7 @@ std::vector generate_pdus(bench_params params, rx_order order) for (int i = 0; i < num_sdus; i++) { byte_buffer sdu_buf = {}; for (int j = 0; j < num_bytes; ++j) { - sdu_buf.append(rand()); + report_error_if_not(sdu_buf.append(rand()), "Failed to allocate SDU"); } sdu_list.push_back(std::move(sdu_buf)); } @@ -163,7 +163,7 @@ std::vector generate_pdus(bench_params params, rx_order order) byte_buffer sdu_buf = std::move(sdu_list[i]); sdu.pdcp_sn = i; sdu.buf = std::move(pdcp_hdr_buf); - sdu.buf.append(std::move(sdu_buf)); + report_error_if_not(sdu.buf.append(std::move(sdu_buf)), "Failed to allocate SDU"); rlc_tx->handle_sdu(std::move(sdu)); std::vector pdu_buf; pdu_buf.resize(1550); diff --git a/tests/benchmarks/rlc/rlc_handle_status_report.cpp b/tests/benchmarks/rlc/rlc_handle_status_report.cpp index b12efd8698..1fbbcbc0de 100644 --- a/tests/benchmarks/rlc/rlc_handle_status_report.cpp +++ b/tests/benchmarks/rlc/rlc_handle_status_report.cpp @@ -130,7 +130,7 @@ void benchmark_status_pdu_handling(rlc_am_status_pdu status, const bench_params& byte_buffer sdu_buf = {0x00, 0x01, 0x02, 0x04}; sdu.pdcp_sn = i; sdu.buf = std::move(pdcp_hdr_buf); - sdu.buf.append(std::move(sdu_buf)); + report_error_if_not(sdu.buf.append(std::move(sdu_buf)), "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 92f74591cf..7185b0b77a 100644 --- a/tests/integrationtests/rlc/rlc_stress_test_f1.h +++ b/tests/integrationtests/rlc/rlc_stress_test_f1.h @@ -69,7 +69,7 @@ class f1ap_dummy : public pdcp_tx_lower_notifier, // TODO for now we copy to a new byte buffer byte_buffer buf; for (uint8_t byte : pdu) { - buf.append(byte); + report_error_if_not(buf.append(byte), "Failed to allocate byte buffer"); } pdcp_rx_lower->handle_pdu(byte_buffer_chain{std::move(buf)}); } diff --git a/tests/integrationtests/rlc/rlc_stress_test_traffic.cpp b/tests/integrationtests/rlc/rlc_stress_test_traffic.cpp index 545c5bd883..5b78cb78c2 100644 --- a/tests/integrationtests/rlc/rlc_stress_test_traffic.cpp +++ b/tests/integrationtests/rlc/rlc_stress_test_traffic.cpp @@ -31,7 +31,7 @@ void stress_traffic_source::send_pdu() } for (uint32_t i = 0; i < sdu_size; i++) { - sdu.append(payload); + report_fatal_error_if_not(sdu.append(payload), "Failed to allocate SDU"); payload++; } diff --git a/tests/unittests/adt/byte_buffer_chain_test.cpp b/tests/unittests/adt/byte_buffer_chain_test.cpp index a555313855..25797e2f7a 100644 --- a/tests/unittests/adt/byte_buffer_chain_test.cpp +++ b/tests/unittests/adt/byte_buffer_chain_test.cpp @@ -50,7 +50,7 @@ TEST(byte_buffer_chain_test, append_byte_buffer) byte_buffer other_buffer{1, 2, 3, 4, 5}; byte_buffer other_buffer2{6, 7, 8}; byte_buffer buf_concat = other_buffer.deep_copy(); - buf_concat.append(other_buffer2.deep_copy()); + ASSERT_TRUE(buf_concat.append(other_buffer2.deep_copy())); buf.append(other_buffer.copy()); buf.append(other_buffer2.copy()); diff --git a/tests/unittests/adt/byte_buffer_test.cpp b/tests/unittests/adt/byte_buffer_test.cpp index 832529df15..f1d2d901b2 100644 --- a/tests/unittests/adt/byte_buffer_test.cpp +++ b/tests/unittests/adt/byte_buffer_test.cpp @@ -399,7 +399,7 @@ TEST(byte_buffer_test, prepend_and_trim_tail) constexpr uint32_t trim_len = 4; constexpr uint32_t prefix_len = 3; for (uint32_t i = 0; i < pdu_len; i++) { - pdu.append(i); + ASSERT_TRUE(pdu.append(i)); } sdu.append(pdu.begin() + prefix_len, pdu.end()); @@ -454,7 +454,7 @@ TEST(byte_buffer_test, is_contiguous) pdu.append(bytes); ASSERT_TRUE(pdu.is_contiguous()); - pdu.append(byte_buffer(bytes2)); + ASSERT_TRUE(pdu.append(byte_buffer(bytes2))); ASSERT_TRUE(not pdu.is_contiguous()); ASSERT_EQ_BUFFER(pdu, bytes_concat); @@ -871,7 +871,7 @@ TEST(byte_buffer_slice_test, deep_slice) ASSERT_EQ(slice, vec); // Test slice doesn't get altered by underlying byte_buffer extension. - pdu.append(1); + ASSERT_TRUE(pdu.append(1)); ASSERT_NE(slice, pdu); byte_buffer_view v{pdu, 0, pdu.length() - 1}; ASSERT_EQ(slice, v); diff --git a/tests/unittests/asn1/asn1_utils_test.cpp b/tests/unittests/asn1/asn1_utils_test.cpp index 195f510c07..22d4278126 100644 --- a/tests/unittests/asn1/asn1_utils_test.cpp +++ b/tests/unittests/asn1/asn1_utils_test.cpp @@ -396,8 +396,8 @@ TEST(asn1_bit_string_test, pack_unpack_operators) /* Test Pack/Unpack 2 */ buf.clear(); - buf.append(0); - buf.append(7); + ASSERT_TRUE(buf.append(0)); + ASSERT_TRUE(buf.append(7)); bref2 = cbit_ref(buf); fixed_bitstring<16> bstr3; bstr3.unpack(bref2); @@ -605,7 +605,7 @@ TEST(asn1_enumerated, pack_unpack) e = EnumTest::nulltype; TESTASSERT(pack_enum(bref, e) == SRSASN_ERROR_ENCODE_FAIL); ASSERT_EQ(0, bref.distance()); - buffer.append(255); + ASSERT_TRUE(buffer.append(255)); bref2 = cbit_ref(buffer); TESTASSERT(unpack_enum(e, bref2) == SRSASN_ERROR_DECODE_FAIL); diff --git a/tests/unittests/du_manager/procedures/ue_configuration_test.cpp b/tests/unittests/du_manager/procedures/ue_configuration_test.cpp index b631235c1e..63bd008d17 100644 --- a/tests/unittests/du_manager/procedures/ue_configuration_test.cpp +++ b/tests/unittests/du_manager/procedures/ue_configuration_test.cpp @@ -197,7 +197,7 @@ TEST_F(ue_config_tester, when_du_manager_finishes_processing_ue_config_request_t // > Add dummy RLC data header. byte_buffer mac_rx_sdu(dummy_rlc_header); // > Append data buffer. - mac_rx_sdu.append(test_payload.copy()); + ASSERT_TRUE(mac_rx_sdu.append(test_payload.copy())); // > Push MAC Rx SDU through MAC logical channel. mac.last_ue_reconf_msg->bearers_to_addmod[0].ul_bearer->on_new_sdu({mac_rx_sdu.copy()}); // > Check arrival of F1-C Tx SDU to F1-C bearer. @@ -229,7 +229,7 @@ TEST_F(ue_config_tester, when_du_manager_finishes_processing_ue_config_request_t // > Add dummy RLC data header. byte_buffer mac_sdu(dummy_rlc_header); // > Append data buffer. - mac_sdu.append(test_payload.copy()); + ASSERT_TRUE(mac_sdu.append(test_payload.copy())); // > Push MAC Rx SDU through MAC logical channel. mac.last_ue_reconf_msg->bearers_to_addmod[0].ul_bearer->on_new_sdu({mac_sdu.copy()}); // > Check arrival of F1-U Tx SDU to F1-U bearer. 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 b97dd8942b..c33d0af5a6 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 @@ -57,7 +57,10 @@ class f1u_trx_test { byte_buffer sdu_buf; for (uint32_t k = 0; k < sdu_size; ++k) { - sdu_buf.append(first_byte + k); + if (not sdu_buf.append(first_byte + k)) { + sdu_buf.clear(); + break; + } } return sdu_buf; } diff --git a/tests/unittests/f1u/du/f1u_du_bearer_test.cpp b/tests/unittests/f1u/du/f1u_du_bearer_test.cpp index 56e865aa71..78edc49cbe 100644 --- a/tests/unittests/f1u/du/f1u_du_bearer_test.cpp +++ b/tests/unittests/f1u/du/f1u_du_bearer_test.cpp @@ -40,7 +40,10 @@ class f1u_trx_test { byte_buffer sdu_buf; for (uint32_t k = 0; k < sdu_size; ++k) { - sdu_buf.append(first_byte + k); + if (not sdu_buf.append(first_byte + k)) { + sdu_buf.clear(); + break; + } } return sdu_buf; } diff --git a/tests/unittests/gateways/test_helpers.h b/tests/unittests/gateways/test_helpers.h index 1591f50d51..81ea7f31aa 100644 --- a/tests/unittests/gateways/test_helpers.h +++ b/tests/unittests/gateways/test_helpers.h @@ -33,7 +33,10 @@ byte_buffer make_tx_byte_buffer(uint32_t length) { byte_buffer pdu{}; for (uint32_t i = 0; i < length; ++i) { - pdu.append((uint8_t)i); + if (not pdu.append((uint8_t)i)) { + pdu.clear(); + break; + } } return pdu; } diff --git a/tests/unittests/gtpu/gtpu_tunnel_ngu_rx_test.cpp b/tests/unittests/gtpu/gtpu_tunnel_ngu_rx_test.cpp index bcab7376a2..a11eeace35 100644 --- a/tests/unittests/gtpu/gtpu_tunnel_ngu_rx_test.cpp +++ b/tests/unittests/gtpu/gtpu_tunnel_ngu_rx_test.cpp @@ -211,7 +211,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_no_sn) for (unsigned i = 0; i < 3; i++) { byte_buffer sdu; - sdu.append(0x11); + 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, {}); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -236,7 +236,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_in_order) for (unsigned i = 0; i < 3; i++) { byte_buffer sdu; - sdu.append(0x11); + 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); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -261,7 +261,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_out_of_order) { // SN = 0 byte_buffer sdu; - sdu.append(0x0); + 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); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -274,7 +274,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_out_of_order) { // SN = 2 byte_buffer sdu; - sdu.append(0x2); + 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); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -286,7 +286,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_out_of_order) { // SN = 4 byte_buffer sdu; - sdu.append(0x4); + 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); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -297,7 +297,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_out_of_order) { // SN = 1 byte_buffer sdu; - sdu.append(0x1); + 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); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -309,7 +309,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_out_of_order) { // SN = 3 byte_buffer sdu; - sdu.append(0x3); + 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); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -337,7 +337,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_out_of_order_two_holes) { // SN = 0 byte_buffer sdu; - sdu.append(0x0); + 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); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -350,7 +350,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_out_of_order_two_holes) { // SN = 2 byte_buffer sdu; - sdu.append(0x2); + 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); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -362,7 +362,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_out_of_order_two_holes) { // SN = 4 byte_buffer sdu; - sdu.append(0x4); + 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); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -373,7 +373,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_out_of_order_two_holes) { // SN = 3 byte_buffer sdu; - sdu.append(0x3); + 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); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -385,7 +385,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_out_of_order_two_holes) { // SN = 1 byte_buffer sdu; - sdu.append(0x1); + 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); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -411,7 +411,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_t_reordering_expiration) { // SN = 0 byte_buffer sdu; - sdu.append(0x0); + 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); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -424,7 +424,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_t_reordering_expiration) { // SN = 2 byte_buffer sdu; - sdu.append(0x2); + 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); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -435,7 +435,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_t_reordering_expiration) { // SN = 4 byte_buffer sdu; - sdu.append(0x4); + 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); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -456,7 +456,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_t_reordering_expiration) { // SN = 1 byte_buffer sdu; - sdu.append(0x1); + 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); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -483,7 +483,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_t_reordering_two_holes) { // SN = 0 byte_buffer sdu; - sdu.append(0x0); + 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); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -496,7 +496,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_t_reordering_two_holes) { // SN = 2 byte_buffer sdu; - sdu.append(0x2); + 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); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -507,7 +507,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_t_reordering_two_holes) { // SN = 4 byte_buffer sdu; - sdu.append(0x4); + 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); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -518,7 +518,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_t_reordering_two_holes) { // SN = 3 byte_buffer sdu; - sdu.append(0x3); + 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); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -535,7 +535,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_t_reordering_two_holes) { // SN = 1 byte_buffer sdu; - sdu.append(0x1); + 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); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); diff --git a/tests/unittests/mac/dl_sch_pdu_assembler_test.cpp b/tests/unittests/mac/dl_sch_pdu_assembler_test.cpp index 5ac58f0a10..9f51fca2cf 100644 --- a/tests/unittests/mac/dl_sch_pdu_assembler_test.cpp +++ b/tests/unittests/mac/dl_sch_pdu_assembler_test.cpp @@ -45,7 +45,7 @@ TEST(mac_dl_sch_pdu, mac_ce_con_res_id_pack) span result = pdu.get(); byte_buffer expected{0b00111110}; - expected.append(conres); + ASSERT_TRUE(expected.append(conres)); ASSERT_EQ(result, expected); } @@ -65,7 +65,7 @@ TEST(mac_dl_sch_pdu, mac_sdu_8bit_L_pack) unsigned payload_len = test_rgen::uniform_int(1, 255); byte_buffer payload; for (unsigned i = 0; i != payload_len; ++i) { - payload.append(test_rgen::uniform_int()); + 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()}); @@ -98,7 +98,7 @@ TEST(mac_dl_sch_pdu, mac_sdu_16bit_L_pack) unsigned payload_len = test_rgen::uniform_int(256, bytes.size() - HEADER_LEN); byte_buffer payload; for (unsigned i = 0; i != payload_len; ++i) { - payload.append(test_rgen::uniform_int()); + 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); @@ -146,7 +146,7 @@ class mac_dl_sch_assembler_tester : public testing::Test srslog::init(); for (unsigned i = 0; i != UE_CON_RES_ID_LEN; ++i) { - msg3_pdu.append(test_rgen::uniform_int()); + report_fatal_error_if_not(msg3_pdu.append(test_rgen::uniform_int()), "failed to allocate bytes"); } // Create UE. diff --git a/tests/unittests/mac/mac_test_helpers.h b/tests/unittests/mac/mac_test_helpers.h index 5a9c66d1f3..54d01cab72 100644 --- a/tests/unittests/mac/mac_test_helpers.h +++ b/tests/unittests/mac/mac_test_helpers.h @@ -43,7 +43,7 @@ inline mac_cell_creation_request make_default_mac_cell_config(const cell_config_ byte_buffer dummy_sib1; for (unsigned i = 0; i != 100; ++i) { - dummy_sib1.append(i); + report_fatal_error_if_not(dummy_sib1.append(i), "Failed to append to create dummy SIB1"); } req.bcch_dl_sch_payloads.push_back(std::move(dummy_sib1)); return req; diff --git a/tests/unittests/pcap/rlc_pcap_test.cpp b/tests/unittests/pcap/rlc_pcap_test.cpp index 3c970773da..44786ef626 100644 --- a/tests/unittests/pcap/rlc_pcap_test.cpp +++ b/tests/unittests/pcap/rlc_pcap_test.cpp @@ -63,7 +63,10 @@ class pcap_rlc_test : public ::testing::Test { byte_buffer sdu_buf; for (uint32_t k = 0; k < sdu_size; ++k) { - sdu_buf.append(first_byte + k); + if (not sdu_buf.append(first_byte + k)) { + sdu_buf.clear(); + break; + } } return sdu_buf; } diff --git a/tests/unittests/pdcp/pdcp_rx_metrics_test.cpp b/tests/unittests/pdcp/pdcp_rx_metrics_test.cpp index ec1cef666f..c7222316c4 100644 --- a/tests/unittests/pdcp/pdcp_rx_metrics_test.cpp +++ b/tests/unittests/pdcp/pdcp_rx_metrics_test.cpp @@ -81,7 +81,7 @@ TEST_P(pdcp_rx_metrics_test, integrity_metrics) byte_buffer test_pdu; get_test_pdu(count, test_pdu); - test_pdu.append(0); // mess up the MAC + ASSERT_TRUE(test_pdu.append(0)); // mess up the MAC // Get expected values uint32_t exp_pdu_size = test_pdu.length(); diff --git a/tests/unittests/pdcp/pdcp_rx_test.cpp b/tests/unittests/pdcp/pdcp_rx_test.cpp index 3f649214d8..23e5d46b3c 100644 --- a/tests/unittests/pdcp/pdcp_rx_test.cpp +++ b/tests/unittests/pdcp/pdcp_rx_test.cpp @@ -293,7 +293,7 @@ TEST_P(pdcp_rx_test, rx_integrity_fail) byte_buffer test_pdu1; get_test_pdu(count, test_pdu1); - test_pdu1.append(0); // mess up MAC-I + 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)}); diff --git a/tests/unittests/rlc/rlc_rx_am_test.cpp b/tests/unittests/rlc/rlc_rx_am_test.cpp index b85a628135..dd096d4a42 100644 --- a/tests/unittests/rlc/rlc_rx_am_test.cpp +++ b/tests/unittests/rlc/rlc_rx_am_test.cpp @@ -539,7 +539,7 @@ TEST_P(rlc_rx_am_test, rx_data_pdu_with_short_header) // Create a short header of a data PDU with polling bit set byte_buffer pdu_buf = {}; - pdu_buf.append(0b11000000); // D/C = 1; P = 1 + ASSERT_TRUE(pdu_buf.append(0b11000000)); // D/C = 1; P = 1 // Push into RLC byte_buffer_slice pdu = {std::move(pdu_buf)}; @@ -558,10 +558,10 @@ TEST_P(rlc_rx_am_test, rx_data_pdu_without_payload) // Create a complete header of a data PDU with polling bit set and with SO byte_buffer pdu_buf = {}; - pdu_buf.append(0b11110000); // D/C = 1; P = 1; SI = 0b11 + ASSERT_TRUE(pdu_buf.append(0b11110000)); // D/C = 1; P = 1; SI = 0b11 pdu_buf.append({0x00, 0x00, 0x00}); if (sn_size == rlc_am_sn_size::size18bits) { - pdu_buf.append(0x00); + ASSERT_TRUE(pdu_buf.append(0x00)); } // Push into RLC diff --git a/tests/unittests/rlc/rlc_sdu_queue_test.cpp b/tests/unittests/rlc/rlc_sdu_queue_test.cpp index 1cf9ad076a..1486fef227 100644 --- a/tests/unittests/rlc/rlc_sdu_queue_test.cpp +++ b/tests/unittests/rlc/rlc_sdu_queue_test.cpp @@ -53,8 +53,8 @@ void full_capacity_test() // Write Capacity + 1 SDUs for (uint32_t pdcp_sn = 0; pdcp_sn < capacity + 1; pdcp_sn++) { byte_buffer buf = {}; - buf.append(pdcp_sn); - buf.append(pdcp_sn); + TESTASSERT(buf.append(pdcp_sn)); + TESTASSERT(buf.append(pdcp_sn)); rlc_sdu write_sdu = {std::move(buf), pdcp_sn}; if (pdcp_sn != capacity) { TESTASSERT(tx_queue.write(std::move(write_sdu)) == true); @@ -68,8 +68,8 @@ void full_capacity_test() // Read all SDUs and try to read on SDU over capacity for (uint32_t pdcp_sn = 0; pdcp_sn < capacity + 1; pdcp_sn++) { byte_buffer expected_msg = {}; - expected_msg.append(pdcp_sn); - expected_msg.append(pdcp_sn); + TESTASSERT(expected_msg.append(pdcp_sn)); + TESTASSERT(expected_msg.append(pdcp_sn)); rlc_sdu read_sdu = {}; if (pdcp_sn != capacity) { TESTASSERT(tx_queue.read(read_sdu)); @@ -93,8 +93,8 @@ void discard_test() // Fill SDU queue with SDUs for (uint32_t pdcp_sn = 0; pdcp_sn < n_sdus; pdcp_sn++) { byte_buffer buf = {}; - buf.append(pdcp_sn); - buf.append(pdcp_sn); + TESTASSERT(buf.append(pdcp_sn)); + TESTASSERT(buf.append(pdcp_sn)); rlc_sdu write_sdu = {std::move(buf), pdcp_sn}; TESTASSERT(tx_queue.write(std::move(write_sdu)) == true); } @@ -132,8 +132,8 @@ void discard_all_test() // Fill SDU queue with SDUs for (uint32_t pdcp_sn = 0; pdcp_sn < n_sdus; pdcp_sn++) { byte_buffer buf = {}; - buf.append(pdcp_sn); - buf.append(pdcp_sn); + TESTASSERT(buf.append(pdcp_sn)); + TESTASSERT(buf.append(pdcp_sn)); rlc_sdu write_sdu = {std::move(buf), pdcp_sn}; TESTASSERT(tx_queue.write(std::move(write_sdu)) == true); } diff --git a/tests/unittests/rlc/rlc_test_helpers.h b/tests/unittests/rlc/rlc_test_helpers.h index 9179534cc1..165365af10 100644 --- a/tests/unittests/rlc/rlc_test_helpers.h +++ b/tests/unittests/rlc/rlc_test_helpers.h @@ -32,7 +32,7 @@ class rlc_trx_test { byte_buffer sdu_buf; for (uint32_t k = 0; k < sdu_size; ++k) { - sdu_buf.append(first_byte + k); + report_error_if_not(sdu_buf.append(first_byte + k), "Failed to allocate byte buffer"); } return sdu_buf; } diff --git a/tests/unittests/rlc/rlc_um_test.cpp b/tests/unittests/rlc/rlc_um_test.cpp index 791a13c6ad..108ff0a372 100644 --- a/tests/unittests/rlc/rlc_um_test.cpp +++ b/tests/unittests/rlc/rlc_um_test.cpp @@ -139,7 +139,7 @@ class rlc_um_test : public ::testing::Test, public ::testing::WithParamInterface { byte_buffer sdu = {}; for (uint32_t k = 0; k < length; ++k) { - sdu.append(first_byte + k); + report_error_if_not(sdu.append(first_byte + k), "Failed to allocate byte buffer"); } return sdu; } @@ -157,7 +157,7 @@ class rlc_um_test : public ::testing::Test, public ::testing::WithParamInterface sdu_bufs[i] = byte_buffer(); // Write the index into the buffer for (uint32_t k = 0; k < sdu_size; ++k) { - sdu_bufs[i].append(i + k); + ASSERT_TRUE(sdu_bufs[i].append(i + k)); } // write SDU into upper end @@ -287,7 +287,7 @@ TEST_P(rlc_um_test, rx_pdu_with_short_header) { // Create a short header of a PDU segment byte_buffer pdu_buf = {}; - pdu_buf.append(0b11000000); // SI = 0b11 + ASSERT_TRUE(pdu_buf.append(0b11000000)); // SI = 0b11 // Push into RLC byte_buffer_slice pdu = {std::move(pdu_buf)}; @@ -301,10 +301,10 @@ TEST_P(rlc_um_test, rx_pdu_without_payload) { // Create a complete header of a PDU segment byte_buffer pdu_buf = {}; - pdu_buf.append(0b11000000); // SI = 0b11 + ASSERT_TRUE(pdu_buf.append(0b11000000)); // SI = 0b11 pdu_buf.append({0x11, 0x22}); if (sn_size == rlc_um_sn_size::size12bits) { - pdu_buf.append(0x33); + ASSERT_TRUE(pdu_buf.append(0x33)); } // Push into RLC @@ -326,7 +326,7 @@ TEST_P(rlc_um_test, tx_without_segmentation) for (uint32_t i = 0; i < num_sdus; i++) { sdu_bufs[i] = byte_buffer(); for (uint32_t k = 0; k < sdu_size; ++k) { - sdu_bufs[i].append(i + k); + ASSERT_TRUE(sdu_bufs[i].append(i + k)); } // write SDU into upper end @@ -395,7 +395,7 @@ TEST_P(rlc_um_test, tx_with_segmentation) sdu_bufs[i] = byte_buffer(); // Write the index into the buffer for (uint32_t k = 0; k < sdu_size; ++k) { - sdu_bufs[i].append(i + k); + ASSERT_TRUE(sdu_bufs[i].append(i + k)); } // write SDU into upper end @@ -474,7 +474,7 @@ TEST_P(rlc_um_test, sdu_discard) for (uint32_t i = 0; i < num_sdus; i++) { sdu_bufs[i] = byte_buffer(); for (uint32_t k = 0; k < sdu_size; ++k) { - sdu_bufs[i].append(i + k); + ASSERT_TRUE(sdu_bufs[i].append(i + k)); } // write SDU into upper end @@ -578,7 +578,7 @@ TEST_P(rlc_um_test, sdu_discard_with_pdcp_sn_wraparound) for (uint32_t i = 0; i < num_sdus; i++) { sdu_bufs[i] = byte_buffer(); for (uint32_t k = 0; k < sdu_size; ++k) { - sdu_bufs[i].append(i + k); + ASSERT_TRUE(sdu_bufs[i].append(i + k)); } // write SDU into upper end @@ -679,7 +679,7 @@ TEST_P(rlc_um_test, tx_with_segmentation_reverse_rx) sdu_bufs[i] = byte_buffer(); // Write the index into the buffer for (uint32_t k = 0; k < sdu_size; ++k) { - sdu_bufs[i].append(i + k); + ASSERT_TRUE(sdu_bufs[i].append(i + k)); } // write SDU into upper end @@ -759,7 +759,7 @@ TEST_P(rlc_um_test, tx_multiple_SDUs_with_segmentation) sdu_bufs[i] = byte_buffer(); // Write the index into the buffer for (uint32_t k = 0; k < sdu_size; ++k) { - sdu_bufs[i].append(i + k); + ASSERT_TRUE(sdu_bufs[i].append(i + k)); } // write SDU into upper end @@ -1011,7 +1011,7 @@ TEST_P(rlc_um_test, lost_segment_outside_reassembly_window) sdu_bufs[i] = byte_buffer(); // Write the index into the buffer for (uint32_t k = 0; k < sdu_size; ++k) { - sdu_bufs[i].append(i + k); + ASSERT_TRUE(sdu_bufs[i].append(i + k)); } // write SDU into upper end @@ -1090,7 +1090,7 @@ TEST_P(rlc_um_test, out_of_order_segments_across_SDUs) sdu_bufs[i] = byte_buffer(); // Write the index into the buffer for (uint32_t k = 0; k < sdu_size; ++k) { - sdu_bufs[i].append(i + k); + ASSERT_TRUE(sdu_bufs[i].append(i + k)); } // write SDU into upper end diff --git a/tests/unittests/support/fixed_size_memory_pool_test.cpp b/tests/unittests/support/fixed_size_memory_pool_test.cpp index 96e02e167d..373b4e35f1 100644 --- a/tests/unittests/support/fixed_size_memory_pool_test.cpp +++ b/tests/unittests/support/fixed_size_memory_pool_test.cpp @@ -32,6 +32,7 @@ TEST(fixed_memory_block_pool_test, allocated_block_is_valid) void* block = pool.allocate_node(256); ASSERT_NE(block, nullptr); pool.deallocate_node(block); + pool.print_all_buffers(); } TEST(fixed_memory_block_pool_test, number_of_alloc_blocks_matches_pool_size) From 8c32ec56144cfca062c7bde62c88afa757f9f212 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 9 Jan 2024 10:54:57 +0100 Subject: [PATCH 075/134] support: add more nodiscard to byte_buffer append methods --- include/srsran/adt/byte_buffer.h | 37 ++++++--- include/srsran/support/bit_encoding.h | 4 +- lib/asn1/asn1_utils.cpp | 8 +- .../adapters/mac_test_mode_adapter.cpp | 6 +- lib/f1ap/du/ue_context/f1c_du_bearer_impl.cpp | 12 ++- lib/support/bit_encoding.cpp | 26 ++++-- .../benchmarks/du_high/du_high_benchmark.cpp | 14 ++-- .../test_doubles/f1ap/f1ap_test_messages.cpp | 4 +- .../unittests/adt/byte_buffer_chain_test.cpp | 4 +- tests/unittests/adt/byte_buffer_test.cpp | 80 +++++++++---------- .../f1ap/du/f1ap_du_test_helpers.cpp | 8 +- tests/unittests/mac/mac_ul_pdu_test.cpp | 2 +- tests/unittests/mac/mac_ul_processor_test.cpp | 4 +- tests/unittests/rlc/rlc_rx_am_test.cpp | 2 +- tests/unittests/rlc/rlc_um_pdu_test.cpp | 2 +- tests/unittests/rlc/rlc_um_test.cpp | 2 +- 16 files changed, 130 insertions(+), 85 deletions(-) diff --git a/include/srsran/adt/byte_buffer.h b/include/srsran/adt/byte_buffer.h index 86e1955c5a..bd23d8c7d8 100644 --- a/include/srsran/adt/byte_buffer.h +++ b/include/srsran/adt/byte_buffer.h @@ -164,7 +164,12 @@ class byte_buffer explicit byte_buffer(const byte_buffer&) noexcept = default; /// Creates a byte_buffer with content provided by a span of bytes. - byte_buffer(span bytes) { append(bytes); } + byte_buffer(span bytes) + { + if (not append(bytes)) { + clear(); + } + } /// Creates a byte_buffer with data intialized via a initializer list. byte_buffer(std::initializer_list lst) : byte_buffer(span{lst.begin(), lst.size()}) {} @@ -173,7 +178,9 @@ class byte_buffer template byte_buffer(It other_begin, It other_end) { - append(other_begin, other_end); + if (not append(other_begin, other_end)) { + clear(); + } } /// Move constructor. @@ -189,7 +196,9 @@ class byte_buffer byte_buffer& operator=(span bytes) noexcept { clear(); - append(bytes); + if (not append(bytes)) { + clear(); + } return *this; } @@ -199,7 +208,10 @@ class byte_buffer byte_buffer buf; if (ctrl_blk_ptr != nullptr) { for (node_t* seg = ctrl_blk_ptr->segments.head; seg != nullptr; seg = seg->next) { - buf.append(span{seg->data(), seg->length()}); + if (not buf.append(span{seg->data(), seg->length()})) { + buf.clear(); + break; + } } } return buf; @@ -210,7 +222,7 @@ class byte_buffer /// Append bytes of a iterator range. template - bool append(Iterator begin, Iterator end) + SRSRAN_NODISCARD bool append(Iterator begin, Iterator end) { static_assert(std::is_same, uint8_t>::value or std::is_same, const uint8_t>::value, @@ -225,10 +237,13 @@ class byte_buffer } /// Appends bytes to the byte buffer. This function may retrieve new segments from a memory pool. - bool append(span bytes); + SRSRAN_NODISCARD bool append(span bytes); /// Appends an initializer list of bytes. - void append(const std::initializer_list& bytes) { append(span{bytes.begin(), bytes.size()}); } + SRSRAN_NODISCARD bool append(const std::initializer_list& bytes) + { + return append(span{bytes.begin(), bytes.size()}); + } /// Appends bytes from another byte_buffer. This function may allocate new segments. SRSRAN_NODISCARD bool append(const byte_buffer& other); @@ -566,16 +581,16 @@ class byte_buffer_writer byte_buffer_view view() const { return *buffer; } /// Appends bytes. - bool append(byte_buffer_view bytes) { return buffer->append(bytes); } + SRSRAN_NODISCARD bool append(byte_buffer_view bytes) { return buffer->append(bytes); } /// Appends initializer list of bytes. - void append(const std::initializer_list& bytes) + SRSRAN_NODISCARD bool append(const std::initializer_list& bytes) { - buffer->append(span{bytes.begin(), bytes.size()}); + return buffer->append(span{bytes.begin(), bytes.size()}); } /// Appends span of bytes. - void append(span bytes) { buffer->append(bytes); } + SRSRAN_NODISCARD bool append(span bytes) { return buffer->append(bytes); } /// Appends single byte. SRSRAN_NODISCARD bool append(uint8_t byte) { return buffer->append(byte); } diff --git a/include/srsran/support/bit_encoding.h b/include/srsran/support/bit_encoding.h index 0755085a99..9b24d7a3b2 100644 --- a/include/srsran/support/bit_encoding.h +++ b/include/srsran/support/bit_encoding.h @@ -47,10 +47,10 @@ class bit_encoder /// Append range of bytes into byte_buffer held by bit_encoder. /// \param bytes span of bytes. - void pack_bytes(srsran::span bytes); + bool pack_bytes(srsran::span bytes); /// Append bytes of a byte_buffer into byte_buffer held by bit_encoder. - void pack_bytes(srsran::byte_buffer_view bytes); + bool pack_bytes(srsran::byte_buffer_view bytes); /// Pads held buffer with zeros until the next byte. void align_bytes_zero(); diff --git a/lib/asn1/asn1_utils.cpp b/lib/asn1/asn1_utils.cpp index 33fa78a401..f7737a99e3 100644 --- a/lib/asn1/asn1_utils.cpp +++ b/lib/asn1/asn1_utils.cpp @@ -150,10 +150,10 @@ SRSASN_CODE bit_ref::pack_bytes(srsran::span bytes) } if (offset == 0) { // Aligned case - writer.append(bytes); + HANDLE_CODE(writer.append(bytes) ? SRSASN_SUCCESS : SRSASN_ERROR_ENCODE_FAIL); } else { for (uint8_t byte : bytes) { - pack(byte, 8U); + HANDLE_CODE(pack(byte, 8U)); } } return SRSASN_SUCCESS; @@ -166,10 +166,10 @@ SRSASN_CODE bit_ref::pack_bytes(srsran::byte_buffer_view bytes) } if (offset == 0) { // Aligned case. - writer.append(bytes); + HANDLE_CODE(writer.append(bytes) ? SRSASN_SUCCESS : SRSASN_ERROR_ENCODE_FAIL); } else { for (uint8_t byte : bytes) { - pack(byte, 8U); + HANDLE_CODE(pack(byte, 8U)); } } return SRSASN_SUCCESS; diff --git a/lib/du_high/adapters/mac_test_mode_adapter.cpp b/lib/du_high/adapters/mac_test_mode_adapter.cpp index 95635e414c..7553e6a448 100644 --- a/lib/du_high/adapters/mac_test_mode_adapter.cpp +++ b/lib/du_high/adapters/mac_test_mode_adapter.cpp @@ -45,7 +45,11 @@ class test_ue_mac_sdu_tx_builder_adapter : public mac_sdu_tx_builder static constexpr unsigned TX_SDU_MAX_SIZE = 5000; public: - test_ue_mac_sdu_tx_builder_adapter() { tx_sdu.append(std::vector(TX_SDU_MAX_SIZE, 0)); } + test_ue_mac_sdu_tx_builder_adapter() + { + report_fatal_error_if_not(tx_sdu.append(std::vector(TX_SDU_MAX_SIZE, 0)), + "Unable to allocate byte buffer"); + } size_t on_new_tx_sdu(span mac_sdu_buf) override { diff --git a/lib/f1ap/du/ue_context/f1c_du_bearer_impl.cpp b/lib/f1ap/du/ue_context/f1c_du_bearer_impl.cpp index af549e1136..9f0494ed56 100644 --- a/lib/f1ap/du/ue_context/f1c_du_bearer_impl.cpp +++ b/lib/f1ap/du/ue_context/f1c_du_bearer_impl.cpp @@ -50,7 +50,10 @@ void f1c_srb0_du_bearer::handle_sdu(byte_buffer_chain sdu) init_msg->nr_cgi.plmn_id.from_number(plmn_string_to_bcd(nr_cgi.plmn)); init_msg->nr_cgi.nr_cell_id.from_number(nr_cgi.nci); init_msg->c_rnti = to_value(ue_ctxt.rnti); - init_msg->rrc_container.append(sdu.begin(), sdu.end()); + if (not init_msg->rrc_container.append(sdu.begin(), sdu.end())) { + logger.error("UL {} SRB0 Tx PDU: Discarding Tx PDU. Cause: Failed to append SDU to RRC container.", ue_ctxt); + return; + } init_msg->du_to_cu_rrc_container_present = true; init_msg->du_to_cu_rrc_container = std::move(du_cu_rrc_container); init_msg->sul_access_ind_present = false; @@ -116,7 +119,12 @@ void f1c_other_srb_du_bearer::handle_sdu(byte_buffer_chain sdu) ul_msg->gnb_du_ue_f1ap_id = gnb_du_ue_f1ap_id_to_uint(ue_ctxt.gnb_du_ue_f1ap_id); ul_msg->gnb_cu_ue_f1ap_id = gnb_cu_ue_f1ap_id_to_uint(ue_ctxt.gnb_cu_ue_f1ap_id); ul_msg->srb_id = srb_id_to_uint(srb_id); - ul_msg->rrc_container.append(sdu.begin(), sdu.end()); + if (not ul_msg->rrc_container.append(sdu.begin(), sdu.end())) { + logger.error("UL {} SRB{} Tx PDU: Discarding Tx PDU. Cause: Failed to append SDU to RRC container.", + ue_ctxt, + srb_id_to_uint(srb_id)); + return; + } ul_msg->sel_plmn_id_present = false; ul_msg->new_gnb_du_ue_f1ap_id_present = false; diff --git a/lib/support/bit_encoding.cpp b/lib/support/bit_encoding.cpp index b645f48130..97cf495a1c 100644 --- a/lib/support/bit_encoding.cpp +++ b/lib/support/bit_encoding.cpp @@ -44,34 +44,44 @@ bool bit_encoder::pack(uint64_t val, uint32_t n_bits) return true; } -void bit_encoder::pack_bytes(srsran::span bytes) +bool bit_encoder::pack_bytes(srsran::span bytes) { if (bytes.empty()) { - return; + return true; } if (offset == 0) { // Aligned case - writer.append(bytes); + if (not writer.append(bytes)) { + return false; + } } else { for (uint8_t byte : bytes) { - pack(byte, 8U); + if (not pack(byte, 8U)) { + return false; + } } } + return true; } -void bit_encoder::pack_bytes(srsran::byte_buffer_view bytes) +bool bit_encoder::pack_bytes(srsran::byte_buffer_view bytes) { if (bytes.empty()) { - return; + return true; } if (offset == 0) { // Aligned case. - writer.append(bytes); + if (not writer.append(bytes)) { + return false; + } } else { for (uint8_t byte : bytes) { - pack(byte, 8U); + if (not pack(byte, 8U)) { + return false; + } } } + return true; } void bit_encoder::align_bytes_zero() diff --git a/tests/benchmarks/du_high/du_high_benchmark.cpp b/tests/benchmarks/du_high/du_high_benchmark.cpp index 0d41aeac12..95251b0232 100644 --- a/tests/benchmarks/du_high/du_high_benchmark.cpp +++ b/tests/benchmarks/du_high/du_high_benchmark.cpp @@ -544,10 +544,12 @@ class du_high_bench du_hi = std::make_unique(cfg); // Create PDCP PDU. - pdcp_pdu.append(test_rgen::random_vector(MAX_DL_PDU_SIZE)); + report_fatal_error_if_not(pdcp_pdu.append(test_rgen::random_vector(MAX_DL_PDU_SIZE)), + "Unable to allocate PDU"); // Create MAC PDU. - mac_pdu.append( - test_rgen::random_vector(buff_size_field_to_bytes(lbsr_buff_sz, srsran::bsr_format::LONG_BSR))); + report_fatal_error_if_not(mac_pdu.append(test_rgen::random_vector( + buff_size_field_to_bytes(lbsr_buff_sz, srsran::bsr_format::LONG_BSR))), + "Unable to allocate PDU"); // Start DU-high operation. du_hi->start(); @@ -839,9 +841,11 @@ class du_high_bench static const uint8_t rlc_um_complete_pdu_header = 0x00; report_fatal_error_if_not(rx_pdu.pdu.append(rlc_um_complete_pdu_header), "Failed to allocate PDU"); // Exclude RLC header from payload length. - rx_pdu.pdu.append(mac_pdu.begin(), mac_pdu.begin() + (payload_len - 1)); + report_fatal_error_if_not(rx_pdu.pdu.append(mac_pdu.begin(), mac_pdu.begin() + (payload_len - 1)), + "Failed to allocate PDU"); // Append Long BSR bytes. - rx_pdu.pdu.append(bsr_mac_subpdu.begin(), bsr_mac_subpdu.end()); + report_fatal_error_if_not(rx_pdu.pdu.append(bsr_mac_subpdu.begin(), bsr_mac_subpdu.end()), + "Failed to allocate PDU"); rx_ind.pdus.push_back(rx_pdu); diff --git a/tests/test_doubles/f1ap/f1ap_test_messages.cpp b/tests/test_doubles/f1ap/f1ap_test_messages.cpp index 0a737cf676..83802753e5 100644 --- a/tests/test_doubles/f1ap/f1ap_test_messages.cpp +++ b/tests/test_doubles/f1ap/f1ap_test_messages.cpp @@ -78,7 +78,9 @@ f1ap_message srsran::test_helpers::create_ue_context_setup_request(gnb_cu_ue_f1a } dl_msg->rrc_container_present = true; - dl_msg->rrc_container.append(test_rgen::random_vector(test_rgen::uniform_int(3, 100))); + report_error_if_not( + dl_msg->rrc_container.append(test_rgen::random_vector(test_rgen::uniform_int(3, 100))), + "Failed to allocate RRC containe"); return msg; } diff --git a/tests/unittests/adt/byte_buffer_chain_test.cpp b/tests/unittests/adt/byte_buffer_chain_test.cpp index 25797e2f7a..2b591f32aa 100644 --- a/tests/unittests/adt/byte_buffer_chain_test.cpp +++ b/tests/unittests/adt/byte_buffer_chain_test.cpp @@ -186,8 +186,8 @@ TEST(byte_buffer_chain_test, slice_chain_formatter) { byte_buffer pdu, pdu2; std::vector bytes = {1, 2, 3, 4, 15, 16, 255}; - pdu.append(bytes); - pdu2.append(bytes); + ASSERT_TRUE(pdu.append(bytes)); + ASSERT_TRUE(pdu2.append(bytes)); byte_buffer_chain chain; chain.append(byte_buffer_slice{std::move(pdu), 3, 2}); diff --git a/tests/unittests/adt/byte_buffer_test.cpp b/tests/unittests/adt/byte_buffer_test.cpp index f1d2d901b2..75a4218c28 100644 --- a/tests/unittests/adt/byte_buffer_test.cpp +++ b/tests/unittests/adt/byte_buffer_test.cpp @@ -111,7 +111,7 @@ TEST(byte_buffer_test, empty_byte_buffer_in_valid_state) ASSERT_EQ_LEN(pdu, 0); ASSERT_EQ(pdu, pdu.deep_copy()); ASSERT_EQ(pdu, pdu.copy()); - pdu.append(std::vector{}); + ASSERT_TRUE(pdu.append(std::vector{})); ASSERT_EQ_LEN(pdu, 0); ASSERT_EQ(pdu.segments().begin(), pdu.segments().end()); } @@ -174,7 +174,7 @@ TEST_P(one_vector_size_param_test, equality_comparison) TEST_P(one_vector_size_param_test, move_ctor) { byte_buffer pdu; - pdu.append(this->bytes); + ASSERT_TRUE(pdu.append(this->bytes)); byte_buffer pdu2{std::move(pdu)}; ASSERT_TRUE(pdu.empty()); @@ -196,7 +196,7 @@ TEST_P(two_vector_size_param_test, append) byte_buffer pdu; // Append span of bytes (that may occupy more than one segment). - pdu.append(this->bytes1); + ASSERT_TRUE(pdu.append(this->bytes1)); ASSERT_EQ_LEN(pdu, bytes1.size()); ASSERT_EQ_BUFFER(pdu, bytes1); @@ -227,7 +227,7 @@ TEST_P(two_vector_size_param_test, prepend) TEST_P(one_vector_size_param_test, clear) { byte_buffer pdu; - pdu.append(this->bytes); + ASSERT_TRUE(pdu.append(this->bytes)); ASSERT_TRUE(not pdu.empty()); pdu.clear(); @@ -243,7 +243,7 @@ TEST(byte_buffer_test, iterator) byte_buffer pdu; std::vector bytes = test_rgen::random_vector(small_vec_size); - pdu.append(bytes); + ASSERT_TRUE(pdu.append(bytes)); // iterator size_t i = 0; @@ -266,7 +266,7 @@ TEST(byte_buffer_test, iterator) // multiple segments std::vector bytes2 = test_rgen::random_vector(random_vec_size()); - pdu.append(bytes2); + ASSERT_TRUE(pdu.append(bytes2)); std::vector bytes_concat = concat_vec(bytes, bytes2); // iterator @@ -301,7 +301,7 @@ TEST(byte_buffer_test, deep_copy_for_empty_byte_buffer) TEST_P(two_vector_size_param_test, deep_copy_for_non_empty_byte_buffer) { byte_buffer pdu; - pdu.append(bytes1); + ASSERT_TRUE(pdu.append(bytes1)); auto bytes_concat = concat_vec(bytes1, bytes2); // Deep copy. @@ -312,7 +312,7 @@ TEST_P(two_vector_size_param_test, deep_copy_for_non_empty_byte_buffer) ASSERT_EQ_BUFFER(pdu, pdu2); ASSERT_EQ_BUFFER(pdu2, bytes1); - pdu2.append(bytes2); + ASSERT_TRUE(pdu2.append(bytes2)); ASSERT_EQ_BUFFER(pdu, bytes1); ASSERT_NE(pdu, pdu2); ASSERT_EQ_BUFFER(pdu2, bytes_concat); @@ -321,13 +321,13 @@ TEST_P(two_vector_size_param_test, deep_copy_for_non_empty_byte_buffer) TEST_P(two_vector_size_param_test, shallow_copy_and_append) { byte_buffer pdu; - pdu.append(bytes1); + ASSERT_TRUE(pdu.append(bytes1)); { byte_buffer pdu2 = pdu.copy(); ASSERT_EQ_BUFFER(pdu2, pdu); ASSERT_EQ_BUFFER(pdu2, bytes1); - pdu2.append(bytes2); + ASSERT_TRUE(pdu2.append(bytes2)); ASSERT_EQ(pdu2, pdu); ASSERT_EQ(pdu.length(), pdu.end() - pdu.begin()) << "shallow copied-from byte_buffer::length() got corrupted"; ASSERT_EQ(pdu2.length(), pdu2.end() - pdu2.begin()) << "shallow copy byte_buffer::length() got corrupted"; @@ -339,7 +339,7 @@ TEST_P(two_vector_size_param_test, shallow_copy_and_append) TEST_P(three_vector_size_param_test, shallow_copy_prepend_and_append) { byte_buffer pdu; - pdu.append(bytes1); + ASSERT_TRUE(pdu.append(bytes1)); { byte_buffer pdu2 = pdu.copy(); @@ -347,7 +347,7 @@ TEST_P(three_vector_size_param_test, shallow_copy_prepend_and_append) ASSERT_EQ_BUFFER(pdu2, bytes1); pdu2.prepend(bytes2); ASSERT_EQ(pdu2, pdu); - pdu2.append(bytes3); + ASSERT_TRUE(pdu2.append(bytes3)); ASSERT_EQ(pdu2, pdu); ASSERT_EQ(pdu.length(), pdu.end() - pdu.begin()) << "shallow copied-from byte_buffer::length() got corrupted"; ASSERT_EQ(pdu2.length(), pdu2.end() - pdu2.begin()) << "shallow copy byte_buffer::length() got corrupted"; @@ -360,7 +360,7 @@ TEST(byte_buffer_test, formatter) { byte_buffer pdu; std::vector bytes = {1, 2, 3, 4, 15, 16, 255}; - pdu.append(bytes); + ASSERT_TRUE(pdu.append(bytes)); fmt::print("PDU: {}\n", pdu); std::string result = fmt::format("{}", pdu); @@ -371,14 +371,14 @@ TEST(byte_buffer_test, trim) { byte_buffer pdu; std::vector bytes = test_rgen::random_vector(small_vec_size); - pdu.append(bytes); + ASSERT_TRUE(pdu.append(bytes)); ASSERT_EQ(pdu, bytes); pdu.trim_head(2); ASSERT_EQ(pdu, span{bytes}.subspan(2, bytes.size() - 2)); std::vector bytes2 = test_rgen::random_vector(random_vec_size(2)); - pdu.append(bytes2); + ASSERT_TRUE(pdu.append(bytes2)); auto bytes_concat = concat_vec(bytes, bytes2); ASSERT_EQ(pdu, span{bytes_concat}.subspan(2, bytes_concat.size() - 2)); @@ -402,7 +402,7 @@ TEST(byte_buffer_test, prepend_and_trim_tail) ASSERT_TRUE(pdu.append(i)); } - sdu.append(pdu.begin() + prefix_len, pdu.end()); + ASSERT_TRUE(sdu.append(pdu.begin() + prefix_len, pdu.end())); std::array hdr_buf; std::copy(pdu.begin(), pdu.begin() + prefix_len, hdr_buf.begin()); sdu.prepend(hdr_buf); @@ -423,7 +423,7 @@ TEST_P(three_vector_size_param_test, shallow_copy_prepend_and_append_keeps_valid byte_buffer pdu2{pdu.copy()}; pdu.prepend(bytes2); - pdu.append(bytes3); + ASSERT_TRUE(pdu.append(bytes3)); ASSERT_EQ(pdu, concat_vec(concat_vec(bytes2, bytes1), bytes3)); ASSERT_EQ(pdu2.length(), pdu2.end() - pdu2.begin()) << "shallow copied-from byte_buffer::length() got corrupted"; @@ -438,7 +438,7 @@ TEST_P(three_vector_size_param_test, shallow_copy_reserve_prepend_and_append_kee byte_buffer pdu2{pdu.copy()}; byte_buffer_view v = pdu.reserve_prepend(bytes2.size()); - pdu.append(bytes3); + ASSERT_TRUE(pdu.append(bytes3)); std::copy(bytes2.begin(), bytes2.end(), v.begin()); ASSERT_EQ(pdu, concat_vec(concat_vec(bytes2, bytes1), bytes3)); @@ -452,7 +452,7 @@ TEST(byte_buffer_test, is_contiguous) std::vector bytes2 = test_rgen::random_vector(large_vec_size); auto bytes_concat = concat_vec(bytes, bytes2); - pdu.append(bytes); + ASSERT_TRUE(pdu.append(bytes)); ASSERT_TRUE(pdu.is_contiguous()); ASSERT_TRUE(pdu.append(byte_buffer(bytes2))); ASSERT_TRUE(not pdu.is_contiguous()); @@ -492,7 +492,7 @@ TEST(byte_buffer_test, copy_byte_buffer_to_span) ASSERT_TRUE(std::all_of(dst_span.begin(), dst_span.end(), [](uint8_t v) { return v == 0xfe; })); // test copy of small buffer - pdu.append(bytes); + ASSERT_TRUE(pdu.append(bytes)); len = copy_segments(pdu, dst_span); ASSERT_EQ(len, pdu.length()); ASSERT_TRUE(std::equal(pdu.begin(), pdu.end(), dst_span.begin(), dst_span.begin() + len)); @@ -500,7 +500,7 @@ TEST(byte_buffer_test, copy_byte_buffer_to_span) ASSERT_EQ(dst_span.data()[len], 0xfe); // test copy of large buffer - pdu.append(bytes2); + ASSERT_TRUE(pdu.append(bytes2)); len = copy_segments(pdu, dst_span); ASSERT_EQ(len, pdu.length()); ASSERT_EQ(dst_span, pdu); @@ -532,7 +532,7 @@ TEST(byte_buffer_test, copy_byte_buffer_view_to_span) ASSERT_TRUE(std::all_of(dst_span.begin(), dst_span.end(), [](uint8_t v) { return v == 0xfe; })); // test copy of small buffer - pdu.append(bytes); + ASSERT_TRUE(pdu.append(bytes)); len = copy_segments(byte_buffer_view{pdu}, dst_span); ASSERT_EQ(len, pdu.length()); ASSERT_TRUE(std::equal(pdu.begin(), pdu.end(), dst_span.begin(), dst_span.begin() + len)); @@ -540,7 +540,7 @@ TEST(byte_buffer_test, copy_byte_buffer_view_to_span) ASSERT_EQ(dst_span.data()[len], 0xfe); // test copy of large buffer - pdu.append(bytes2); + ASSERT_TRUE(pdu.append(bytes2)); len = copy_segments(byte_buffer_view{pdu}, dst_span); ASSERT_EQ(len, pdu.length()); ASSERT_EQ(dst_span, pdu); @@ -570,13 +570,13 @@ TEST(byte_buffer_test, to_span) ASSERT_EQ(dst, pdu); // test view of small buffer (no copy) - pdu.append(bytes); + ASSERT_TRUE(pdu.append(bytes)); dst = to_span(pdu, tmp_mem); ASSERT_EQ(pdu, dst); ASSERT_EQ(dst, span{*pdu.segments().begin()}); // test copy of large buffer (with copy) - pdu.append(bytes2); + ASSERT_TRUE(pdu.append(bytes2)); dst = to_span(pdu, tmp_mem); ASSERT_EQ(pdu, dst); ASSERT_EQ(dst, span{tmp_mem}); @@ -588,7 +588,7 @@ TEST(byte_buffer_test, iterator_plus_equal_op) // Make initial vector byte_buffer pdu; std::vector bytes = test_rgen::random_vector(small_vec_size); - pdu.append(bytes); + ASSERT_TRUE(pdu.append(bytes)); auto it = pdu.begin(); ASSERT_NE(it, pdu.cend()); @@ -605,7 +605,7 @@ TEST(byte_buffer_test, iterator_plus_equal_op) // Test with big vector of bytes bytes = test_rgen::random_vector(large_vec_size); pdu.clear(); - pdu.append(bytes); + ASSERT_TRUE(pdu.append(bytes)); it = pdu.begin(); ASSERT_NE(it, pdu.cend()); @@ -620,8 +620,8 @@ TEST(byte_buffer_test, iterator_plus_equal_op) ASSERT_EQ(it, pdu.cend()); // Test with byte buffer made of several segments - pdu.append(bytes); - pdu.append(bytes); + ASSERT_TRUE(pdu.append(bytes)); + ASSERT_TRUE(pdu.append(bytes)); it = pdu.begin(); ASSERT_NE(pdu.cend(), it); @@ -645,13 +645,13 @@ TEST(byte_buffer_test, iterator_of_segments) ASSERT_EQ(pdu.segments().begin(), pdu.segments().end()); // one-segment buffer - pdu.append(small_vec_bytes); + ASSERT_TRUE(pdu.append(small_vec_bytes)); ASSERT_NE(pdu.segments().begin(), pdu.segments().end()); ASSERT_EQ(*pdu.segments().begin(), span(small_vec_bytes)); ASSERT_EQ(++pdu.segments().begin(), pdu.segments().end()); // multiple-segment buffer. - pdu.append(test_rgen::random_vector(random_vec_size(1, 10000))); + ASSERT_TRUE(pdu.append(test_rgen::random_vector(random_vec_size(1, 10000)))); std::vector total_bytes(pdu.begin(), pdu.end()); unsigned seg_offset = 0; for (auto seg_it = pdu.segments().begin(); seg_it != pdu.segments().end(); ++seg_it) { @@ -703,14 +703,14 @@ TEST(byte_buffer_test, append_rvalue_byte_buffer) ASSERT_TRUE(pdu2.empty()); // Chain byte_buffer before another non-empty byte_buffer. - pdu2.append(big_vec); + ASSERT_TRUE(pdu2.append(big_vec)); pdu.prepend(std::move(pdu2)); ASSERT_TRUE(pdu2.empty()); ASSERT_EQ_LEN(pdu, big_vec.size() + small_vec.size()); ASSERT_EQ(pdu, bytes_concat); // Chain byte_buffer after another non-empty byte_buffer. - pdu2.append(big_vec); + ASSERT_TRUE(pdu2.append(big_vec)); ASSERT_TRUE(pdu.append(std::move(pdu2))); ASSERT_TRUE(pdu2.empty()); ASSERT_EQ_LEN(pdu, big_vec.size() * 2 + small_vec.size()); @@ -754,7 +754,7 @@ TEST(byte_buffer_view_test, length) byte_buffer pdu; unsigned len = test_rgen::uniform_int(1, 100000); std::vector bytes = test_rgen::random_vector(len); - pdu.append(bytes); + ASSERT_TRUE(pdu.append(bytes)); byte_buffer_view view = pdu; @@ -911,7 +911,7 @@ TEST(byte_buffer_slice_test, formatter) { byte_buffer pdu; std::vector bytes = {1, 2, 3, 4, 15, 16, 255}; - pdu.append(bytes); + ASSERT_TRUE(pdu.append(bytes)); byte_buffer_slice slice{std::move(pdu), 1, 4}; std::string result = fmt::format("{}", slice); @@ -926,7 +926,7 @@ TEST(byte_buffer_reader_test, split_advance) // Make initial vector byte_buffer pdu; std::vector bytes = test_rgen::random_vector(small_vec_size); - pdu.append(bytes); + ASSERT_TRUE(pdu.append(bytes)); auto it = pdu.begin(); TESTASSERT(it != pdu.cend()); @@ -952,9 +952,9 @@ TEST(byte_buffer_reader_test, split_advance) // Make initial vector bytes = test_rgen::random_vector(large_vec_size); pdu.clear(); - pdu.append(bytes); - pdu.append(bytes); - pdu.append(bytes); + ASSERT_TRUE(pdu.append(bytes)); + ASSERT_TRUE(pdu.append(bytes)); + ASSERT_TRUE(pdu.append(bytes)); it = pdu.begin(); TESTASSERT(it != pdu.cend()); @@ -991,7 +991,7 @@ TEST(byte_buffer_writer_test, all) TESTASSERT_EQ(1, pdu.length()); TESTASSERT_EQ(1, writer.length()); - writer.append({0, 1, 2, 3, 4}); + ASSERT_TRUE(writer.append({0, 1, 2, 3, 4})); TESTASSERT_EQ(6, pdu.length()); TESTASSERT_EQ(6, writer.length()); bool is_eq = pdu == std::vector{5, 0, 1, 2, 3, 4}; diff --git a/tests/unittests/f1ap/du/f1ap_du_test_helpers.cpp b/tests/unittests/f1ap/du/f1ap_du_test_helpers.cpp index 8453872a9a..dc496105a6 100644 --- a/tests/unittests/f1ap/du/f1ap_du_test_helpers.cpp +++ b/tests/unittests/f1ap/du/f1ap_du_test_helpers.cpp @@ -91,7 +91,8 @@ f1ap_message srsran::srs_du::generate_ue_context_setup_request(const std::initia } dl_msg->rrc_container_present = true; - dl_msg->rrc_container.append(test_rgen::random_vector(test_rgen::uniform_int(3, 100))); + EXPECT_TRUE( + dl_msg->rrc_container.append(test_rgen::random_vector(test_rgen::uniform_int(3, 100)))); return msg; } @@ -144,7 +145,8 @@ srsran::srs_du::generate_ue_context_modification_request(const std::initializer_ } dl_msg->rrc_container_present = true; - dl_msg->rrc_container.append(test_rgen::random_vector(test_rgen::uniform_int(1, 100))); + EXPECT_TRUE( + dl_msg->rrc_container.append(test_rgen::random_vector(test_rgen::uniform_int(1, 100)))); return msg; } @@ -237,7 +239,7 @@ f1ap_du_test::ue_test_context* f1ap_du_test::run_f1ap_ue_create(du_ue_index_t ue msg.ue_index = ue_index; msg.pcell_index = to_du_cell_index(0); msg.c_rnti = test_ues[ue_index].crnti; - msg.du_cu_rrc_container.append({0x1, 0x2, 0x3}); + EXPECT_TRUE(msg.du_cu_rrc_container.append({0x1, 0x2, 0x3})); for (auto& f1c_bearer : test_ues[ue_index].f1c_bearers) { f1c_bearer_to_addmod b; b.srb_id = f1c_bearer.srb_id; diff --git a/tests/unittests/mac/mac_ul_pdu_test.cpp b/tests/unittests/mac/mac_ul_pdu_test.cpp index cad5fcdb4c..6a327186a3 100644 --- a/tests/unittests/mac/mac_ul_pdu_test.cpp +++ b/tests/unittests/mac/mac_ul_pdu_test.cpp @@ -406,7 +406,7 @@ TEST(mac_ul_pdu, decode_crnti_ce_and_sbsr) // subPDU_2 = [ R/LCID MAC subheader (1 byte) | MAC CE Short BSR ] // R/LCID MAC subheader = R|R|LCID = 0x3d or LCID=63 - msg.append({0x3d, 0x59}); + ASSERT_TRUE(msg.append({0x3d, 0x59})); mac_ul_sch_pdu pdu; ASSERT_TRUE(pdu.unpack(msg)); diff --git a/tests/unittests/mac/mac_ul_processor_test.cpp b/tests/unittests/mac/mac_ul_processor_test.cpp index 885de7ffc0..282af9dee2 100644 --- a/tests/unittests/mac/mac_ul_processor_test.cpp +++ b/tests/unittests/mac/mac_ul_processor_test.cpp @@ -242,7 +242,7 @@ TEST(mac_ul_processor, decode_ul_ccch_48bit) ul_ccch_msg.slot_rx = slot_point{0, 1}; ul_ccch_msg.tc_rnti = tc_rnti; // Remove R/R/LCID header (0x34) from PDU - ul_ccch_msg.subpdu.append({0x1e, 0x4f, 0xc0, 0x04, 0xa6, 0x06}); + ASSERT_TRUE(ul_ccch_msg.subpdu.append({0x1e, 0x4f, 0xc0, 0x04, 0xa6, 0x06})); // Test if notification sent to DU manager has been received and it is correct. ASSERT_TRUE(t_bench.verify_du_ul_ccch_msg(ul_ccch_msg)); @@ -270,7 +270,7 @@ TEST(mac_ul_processor, decode_ul_ccch_64bit) ul_ccch_msg.slot_rx = slot_point{0, 1}; ul_ccch_msg.tc_rnti = tc_rnti; // Remove R/R/LCID header (0x00) from PDU - ul_ccch_msg.subpdu.append({0x1e, 0x4f, 0xc0, 0x04, 0xa6, 0x06, 0x13, 0x54}); + ASSERT_TRUE(ul_ccch_msg.subpdu.append({0x1e, 0x4f, 0xc0, 0x04, 0xa6, 0x06, 0x13, 0x54})); // Test if notification sent to DU manager has been received and it is correct. ASSERT_TRUE(t_bench.verify_du_ul_ccch_msg(ul_ccch_msg)); diff --git a/tests/unittests/rlc/rlc_rx_am_test.cpp b/tests/unittests/rlc/rlc_rx_am_test.cpp index dd096d4a42..50e5877148 100644 --- a/tests/unittests/rlc/rlc_rx_am_test.cpp +++ b/tests/unittests/rlc/rlc_rx_am_test.cpp @@ -559,7 +559,7 @@ TEST_P(rlc_rx_am_test, rx_data_pdu_without_payload) // Create a complete header of a data PDU with polling bit set and with SO byte_buffer pdu_buf = {}; ASSERT_TRUE(pdu_buf.append(0b11110000)); // D/C = 1; P = 1; SI = 0b11 - pdu_buf.append({0x00, 0x00, 0x00}); + ASSERT_TRUE(pdu_buf.append({0x00, 0x00, 0x00})); if (sn_size == rlc_am_sn_size::size18bits) { ASSERT_TRUE(pdu_buf.append(0x00)); } diff --git a/tests/unittests/rlc/rlc_um_pdu_test.cpp b/tests/unittests/rlc/rlc_um_pdu_test.cpp index 374bbcefa5..2642664575 100644 --- a/tests/unittests/rlc/rlc_um_pdu_test.cpp +++ b/tests/unittests/rlc/rlc_um_pdu_test.cpp @@ -18,7 +18,7 @@ template byte_buffer make_pdu_and_log(const std::array& tv) { byte_buffer pdu; - pdu.append(tv); + report_error_if_not(pdu.append(tv), "Failed to append to byte_buffer"); // write_pdu_to_pcap(4, tv.data(), tv.size()); TODO return pdu; } diff --git a/tests/unittests/rlc/rlc_um_test.cpp b/tests/unittests/rlc/rlc_um_test.cpp index 108ff0a372..6fe66179e7 100644 --- a/tests/unittests/rlc/rlc_um_test.cpp +++ b/tests/unittests/rlc/rlc_um_test.cpp @@ -302,7 +302,7 @@ TEST_P(rlc_um_test, rx_pdu_without_payload) // Create a complete header of a PDU segment byte_buffer pdu_buf = {}; ASSERT_TRUE(pdu_buf.append(0b11000000)); // SI = 0b11 - pdu_buf.append({0x11, 0x22}); + ASSERT_TRUE(pdu_buf.append({0x11, 0x22})); if (sn_size == rlc_um_sn_size::size12bits) { ASSERT_TRUE(pdu_buf.append(0x33)); } From 21b905390a83c296b7aae1b1aca88c0d09e3b8ad Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Thu, 4 Jan 2024 16:34:43 +0100 Subject: [PATCH 076/134] gnb,sched: cfg and apply max UL and PUCCH grants limit Signed-off-by: Carlo Galiotto --- apps/gnb/gnb_appconfig.h | 11 +++ apps/gnb/gnb_appconfig_cli11_schema.cpp | 19 +++- apps/gnb/gnb_appconfig_translators.cpp | 4 + .../config/scheduler_expert_config.h | 4 + lib/scheduler/cell_scheduler.cpp | 2 +- .../pucch_scheduling/pucch_allocator_impl.cpp | 88 ++++++++++++++++++- .../pucch_scheduling/pucch_allocator_impl.h | 6 +- .../ue_scheduling/ue_cell_grid_allocator.cpp | 6 ++ .../pucch_alloc_harq_sr_csi_test.cpp | 73 ++++++++++++++- .../uci_and_pucch/uci_test_utils.cpp | 8 +- .../scheduler/uci_and_pucch/uci_test_utils.h | 6 +- .../ue_scheduling/srb0_scheduler_test.cpp | 2 +- 12 files changed, 217 insertions(+), 12 deletions(-) diff --git a/apps/gnb/gnb_appconfig.h b/apps/gnb/gnb_appconfig.h index 9fdc1185dd..3ec700ab52 100644 --- a/apps/gnb/gnb_appconfig.h +++ b/apps/gnb/gnb_appconfig.h @@ -298,6 +298,9 @@ struct pucch_appconfig { /// Maximum number of consecutive undecoded PUCCH Format 2 for CSI before an RLF is reported. unsigned max_consecutive_kos = 100; + + /// Maximum number of PUCCH grants per slot. + unsigned max_pucchs_per_slot = 31U; }; /// Parameters that are used to initialize or build the \c PhysicalCellGroupConfig, TS 38.331. @@ -438,6 +441,12 @@ struct mac_cell_group_appconfig { mac_sr_appconfig sr_cfg; }; +/// Scheduler expert configuration. +struct sched_expert_appconfig { + /// Maximum number of PUSCH + PUCCH grants per slot. + unsigned max_ul_grants_per_slot = 32U; +}; + /// Base cell configuration. struct base_cell_appconfig { /// Physical cell identifier. @@ -488,6 +497,8 @@ struct base_cell_appconfig { paging_appconfig paging_cfg; /// CSI configuration. csi_appconfig csi_cfg; + /// Scheduler expert configuration. + sched_expert_appconfig sched_expert; }; /// Cell configuration diff --git a/apps/gnb/gnb_appconfig_cli11_schema.cpp b/apps/gnb/gnb_appconfig_cli11_schema.cpp index 4133f676bb..7fad6a1b62 100644 --- a/apps/gnb/gnb_appconfig_cli11_schema.cpp +++ b/apps/gnb/gnb_appconfig_cli11_schema.cpp @@ -884,6 +884,11 @@ static void configure_cli11_pucch_args(CLI::App& app, pucch_appconfig& pucch_par pucch_params.max_consecutive_kos, "Maximum number of consecutive undecoded PUCCH F2 for CSI before an Radio Link Failure is reported") ->capture_default_str(); + app.add_option("--max_pucchs_per_slot", + pucch_params.max_pucchs_per_slot, + "Maximum number of PUCCH grants that can be allocated per slot.") + ->capture_default_str() + ->check(CLI::Range(1U, static_cast(MAX_PUCCH_PDUS_PER_SLOT))); } static void configure_cli11_ul_common_args(CLI::App& app, ul_common_appconfig& ul_common_params) @@ -1240,6 +1245,14 @@ static void configure_cli11_mac_cell_group_args(CLI::App& app, mac_cell_group_ap configure_cli11_mac_sr_args(*sr_subcmd, mcg_params.sr_cfg); } +static void configure_cli11_sched_expert_args(CLI::App& app, sched_expert_appconfig& sched_exp_params) +{ + app.add_option( + "--max_ul_grants_per_slot", sched_exp_params.max_ul_grants_per_slot, "Maximum number of UL grants per slot") + ->capture_default_str() + ->check(CLI::Range(1U, (unsigned)(MAX_PUSCH_PDUS_PER_SLOT + MAX_PUCCH_PDUS_PER_SLOT))); +} + static void configure_cli11_common_cell_args(CLI::App& app, base_cell_appconfig& cell_params) { app.add_option("--pci", cell_params.pci, "PCI")->capture_default_str()->check(CLI::Range(0, 1007)); @@ -1367,9 +1380,13 @@ static void configure_cli11_common_cell_args(CLI::App& app, base_cell_appconfig& CLI::App* paging_subcmd = app.add_subcommand("paging", "Paging parameters"); configure_cli11_paging_args(*paging_subcmd, cell_params.paging_cfg); - // CSI configuration; + // CSI configuration. CLI::App* csi_subcmd = app.add_subcommand("csi", "CSI-Meas parameters"); configure_cli11_csi_args(*csi_subcmd, cell_params.csi_cfg); + + // Scheduler expert configuration. + CLI::App* sched_expert_subcmd = app.add_subcommand("sched_expert", "Scheduler parameters"); + configure_cli11_sched_expert_args(*sched_expert_subcmd, cell_params.sched_expert); } static void configure_cli11_cells_args(CLI::App& app, cell_appconfig& cell_params) diff --git a/apps/gnb/gnb_appconfig_translators.cpp b/apps/gnb/gnb_appconfig_translators.cpp index c45251bd4b..9b6808c908 100644 --- a/apps/gnb/gnb_appconfig_translators.cpp +++ b/apps/gnb/gnb_appconfig_translators.cpp @@ -1674,6 +1674,10 @@ scheduler_expert_config srsran::generate_scheduler_expert_config(const gnb_appco out_cfg.ue.olla_ul_snr_inc = pusch.olla_snr_inc; out_cfg.ue.olla_max_ul_snr_offset = pusch.olla_max_snr_offset; + // PUCCH and scheduler expert parameters. + out_cfg.ue.max_ul_grants_per_slot = cell.sched_expert.max_ul_grants_per_slot; + out_cfg.ue.max_pucchs_per_slot = cell.pucch_cfg.max_pucchs_per_slot; + // RA parameters. const prach_appconfig& prach = cell.prach_cfg; diff --git a/include/srsran/scheduler/config/scheduler_expert_config.h b/include/srsran/scheduler/config/scheduler_expert_config.h index b4f870838e..da6a4db0ca 100644 --- a/include/srsran/scheduler/config/scheduler_expert_config.h +++ b/include/srsran/scheduler/config/scheduler_expert_config.h @@ -59,6 +59,10 @@ struct scheduler_ue_expert_config { unsigned max_pdschs_per_slot = MAX_PDSCH_PDUS_PER_SLOT; /// Maximum number of PUSCH grants per slot. unsigned max_puschs_per_slot = MAX_PUSCH_PDUS_PER_SLOT; + /// Maximum number of PUCCH grants per slot. + unsigned max_pucchs_per_slot = MAX_PUCCH_PDUS_PER_SLOT; + /// Maximum number of PUSCH + PUCCH grants per slot. + unsigned max_ul_grants_per_slot{32U}; /// Maximum number of PDCCH grant allocation attempts per slot. Default: Unlimited. unsigned max_pdcch_alloc_attempts_per_slot = std::max(MAX_DL_PDCCH_PDUS_PER_SLOT, MAX_UL_PDCCH_PDUS_PER_SLOT); /// CQI offset increment used in outer loop link adaptation (OLLA) algorithm. If set to zero, OLLA is disabled. diff --git a/lib/scheduler/cell_scheduler.cpp b/lib/scheduler/cell_scheduler.cpp index 11f5470418..7c1a2313dc 100644 --- a/lib/scheduler/cell_scheduler.cpp +++ b/lib/scheduler/cell_scheduler.cpp @@ -32,7 +32,7 @@ cell_scheduler::cell_scheduler(const scheduler_expert_config& s csi_sch(cell_cfg), ra_sch(sched_cfg.ra, cell_cfg, pdcch_sch, ev_logger), prach_sch(cell_cfg), - pucch_alloc(cell_cfg), + pucch_alloc(cell_cfg, sched_cfg.ue.max_pucchs_per_slot, sched_cfg.ue.max_ul_grants_per_slot), uci_alloc(pucch_alloc), sib1_sch(sched_cfg.si, cell_cfg, pdcch_sch, msg), si_msg_sch(sched_cfg.si, cell_cfg, pdcch_sch, msg), diff --git a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp index 0132812c37..1e5c393e0a 100644 --- a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp +++ b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp @@ -79,8 +79,13 @@ static unsigned get_n_id0_scrambling(const ue_cell_configuration& ue_cell_cfg, u ////////////// Public functions ////////////// -pucch_allocator_impl::pucch_allocator_impl(const cell_configuration& cell_cfg_) : - cell_cfg(cell_cfg_), logger(srslog::fetch_basic_logger("SCHED")) +pucch_allocator_impl::pucch_allocator_impl(const cell_configuration& cell_cfg_, + unsigned max_pucchs_per_slot, + unsigned max_ul_grants_per_slot_) : + cell_cfg(cell_cfg_), + max_pucch_grants_per_slot(max_pucchs_per_slot), + max_ul_grants_per_slot(max_ul_grants_per_slot_), + logger(srslog::fetch_basic_logger("SCHED")) { } @@ -95,7 +100,12 @@ optional pucch_allocator_impl::alloc_common_pucch_harq_ack_ue(cell_res // Get the slot allocation grid considering the PDSCH delay (k0) and the PUCCH delay wrt PDSCH (k1). cell_slot_resource_allocator& pucch_slot_alloc = slot_alloc[k0 + k1 + slot_alloc.cfg.ntn_cs_koffset]; - if (pucch_slot_alloc.result.ul.pucchs.full() or + // [Implementation-defined] We only allow a max number of PUCCH + PUSCH grants per slot. + const unsigned max_pucchs_on_this_slot = + std::min(max_pucch_grants_per_slot, + max_ul_grants_per_slot - static_cast(pucch_slot_alloc.result.ul.puschs.size())); + + if (pucch_slot_alloc.result.ul.pucchs.full() or pucch_slot_alloc.result.ul.pucchs.size() >= max_pucchs_on_this_slot or pucch_common_alloc_grid[slot_alloc[k0 + k1 + slot_alloc.cfg.ntn_cs_koffset].slot.to_uint()].full()) { return nullopt; } @@ -213,6 +223,17 @@ void pucch_allocator_impl::pucch_allocate_sr_opportunity(cell_slot_resource_allo rnti_t crnti, const ue_cell_configuration& ue_cell_cfg) { + // [Implementation-defined] We only allow a max number of PUCCH + PUSCH grants per slot. + const unsigned max_pucchs_on_this_slot = + std::min(max_pucch_grants_per_slot, + max_ul_grants_per_slot - static_cast(pucch_slot_alloc.result.ul.puschs.size())); + + if (pucch_slot_alloc.result.ul.pucchs.size() >= max_pucchs_on_this_slot) { + logger.warning( + "rnti={}: SR occasion allocation for slot={} skipped. Cause: UL grants reached", crnti, pucch_slot_alloc.slot); + return; + } + if (pucch_slot_alloc.result.ul.pucchs.full()) { logger.warning("rnti={}: SR occasion allocation for slot={} skipped. Cause: no more PUCCH grants available in " "the scheduler", @@ -504,6 +525,18 @@ optional pucch_allocator_impl::allocate_new_format1_harq_grant(cell_sl const ue_cell_configuration& ue_cell_cfg, pucch_info* existing_sr_grant) { + // [Implementation-defined] We only allow a max number of PUCCH + PUSCH grants per slot. + const unsigned max_pucchs_on_this_slot = + std::min(max_pucch_grants_per_slot, + max_ul_grants_per_slot - static_cast(pucch_slot_alloc.result.ul.puschs.size())); + + if (pucch_slot_alloc.result.ul.pucchs.size() >= max_pucchs_on_this_slot) { + logger.info("rnti={}: HARQ-ACK allocation on PUCCH Format1 for slot={} skipped. Cause: UL grants reached", + crnti, + pucch_slot_alloc.slot); + return nullopt; + } + // Check if there is space for one more additional PUCCH HARQ grant. if (pucch_slot_alloc.result.ul.pucchs.full()) { logger.warning("rnti={}: PUCCH HARQ-ACK grant for slot={} not allocated. Cause: no more PUCCH grants available " @@ -585,7 +618,18 @@ void pucch_allocator_impl::convert_to_format2_csi(cell_slot_resource_allocator& remove_pucch_format1_from_grants( pucch_slot_alloc, rnti, ue_cell_cfg.cfg_dedicated().ul_config.value().init_ul_bwp.pucch_cfg.value()); - // Allocate PUCCH SR grant only. + // [Implementation-defined] We only allow a max number of PUCCH + PUSCH grants per slot. + const unsigned max_pucchs_on_this_slot = + std::min(max_pucch_grants_per_slot, + max_ul_grants_per_slot - static_cast(pucch_slot_alloc.result.ul.puschs.size())); + + if (pucch_slot_alloc.result.ul.pucchs.size() >= max_pucchs_on_this_slot) { + logger.warning("rnti={}: UCI allocation on PUCCH Format2 for slot={} skipped. Cause: UL grants reached", + rnti, + pucch_slot_alloc.slot); + return; + } + if (pucch_slot_alloc.result.ul.pucchs.full()) { logger.warning("rnti={}: UCI could not be allocated on PUCCH Format2 for slot={}. Cause: List still full after " "removing PUCCH F1 grant", @@ -666,6 +710,18 @@ optional pucch_allocator_impl::convert_to_format2_harq(cell_slot_resou remove_pucch_format1_from_grants( pucch_slot_alloc, rnti, ue_cell_cfg.cfg_dedicated().ul_config.value().init_ul_bwp.pucch_cfg.value()); + // [Implementation-defined] We only allow a max number of PUCCH + PUSCH grants per slot. + const unsigned max_pucchs_on_this_slot = + std::min(max_pucch_grants_per_slot, + max_ul_grants_per_slot - static_cast(pucch_slot_alloc.result.ul.puschs.size())); + + if (pucch_slot_alloc.result.ul.pucchs.size() >= max_pucchs_on_this_slot) { + logger.info("rnti={}: HARQ-ACK allocation on PUCCH Format2 for slot={} skipped. Cause: UL grants reached", + rnti, + pucch_slot_alloc.slot); + return nullopt; + } + // Allocate PUCCH SR grant only. if (pucch_slot_alloc.result.ul.pucchs.full()) { logger.warning("rnti={}: UCI could not be allocated on PUCCH Format2 for slot={}. Cause: List still full after " @@ -762,6 +818,18 @@ optional pucch_allocator_impl::change_format2_resource(cell_slot_resou // TODO: instead of removing the grant, change the data according to the new resource used. remove_format2_csi_from_grants(pucch_slot_alloc, rnti, ue_cell_cfg); + // [Implementation-defined] We only allow a max number of PUCCH + PUSCH grants per slot. + const unsigned max_pucchs_on_this_slot = + std::min(max_pucch_grants_per_slot, + max_ul_grants_per_slot - static_cast(pucch_slot_alloc.result.ul.puschs.size())); + + if (pucch_slot_alloc.result.ul.pucchs.size() >= max_pucchs_on_this_slot) { + logger.info("rnti={}: HARQ-ACK allocation on PUCCH Format2 for slot={} skipped. Cause: UL grants reached", + rnti, + pucch_slot_alloc.slot); + return nullopt; + } + if (pucch_slot_alloc.result.ul.pucchs.full()) { logger.warning( "rnti={}: HARQ-ACK could not be allocated on PUCCH Format2 for slot={}. Cause: List still full after " @@ -872,6 +940,18 @@ void pucch_allocator_impl::allocate_new_csi_grant(cell_slot_resource_allocator& { srsran_assert(csi_part1_bits != 0, "This function can only be called to allocate a PUCCH F2 resource for CSI"); + // [Implementation-defined] We only allow a max number of PUCCH + PUSCH grants per slot. + const unsigned max_pucchs_on_this_slot = + std::min(max_pucch_grants_per_slot, + max_ul_grants_per_slot - static_cast(pucch_slot_alloc.result.ul.puschs.size())); + + if (pucch_slot_alloc.result.ul.pucchs.size() >= max_pucchs_on_this_slot) { + logger.warning("rnti={}: CSI allocation on PUCCH Format2 for slot={} skipped. Cause: UL grants reached", + crnti, + pucch_slot_alloc.slot); + return; + } + // Check if there is space for new PUCCH grants in the scheduler. if (pucch_slot_alloc.result.ul.pucchs.full()) { logger.warning( diff --git a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.h b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.h index 460c315e18..604c3bf1b2 100644 --- a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.h +++ b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.h @@ -22,7 +22,9 @@ namespace srsran { class pucch_allocator_impl final : public pucch_allocator { public: - explicit pucch_allocator_impl(const cell_configuration& cell_cfg_); + explicit pucch_allocator_impl(const cell_configuration& cell_cfg_, + unsigned max_pucchs_per_slot, + unsigned max_ul_grants_per_slot_); ~pucch_allocator_impl() override; @@ -173,6 +175,8 @@ class pucch_allocator_impl final : public pucch_allocator const unsigned PUCCH_FORMAT_1_NOF_PRBS{1}; const cell_configuration& cell_cfg; + const unsigned max_pucch_grants_per_slot; + const unsigned max_ul_grants_per_slot; slot_point last_sl_ind; pucch_resource_manager resource_manager; diff --git a/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp b/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp index c58bb8b4e2..0d14dfefa4 100644 --- a/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp +++ b/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp @@ -515,6 +515,12 @@ alloc_outcome ue_cell_grid_allocator::allocate_ul_grant(const ue_pusch_grant& gr expert_cfg.max_puschs_per_slot); return alloc_outcome::skip_slot; } + if (pusch_alloc.result.ul.puschs.size() >= + expert_cfg.max_ul_grants_per_slot - static_cast(pusch_alloc.result.ul.pucchs.size())) { + logger.info("Failed to allocate PUSCH. Cause: Max number of UL grants per slot {} was reached.", + 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()) { diff --git a/tests/unittests/scheduler/uci_and_pucch/pucch_alloc_harq_sr_csi_test.cpp b/tests/unittests/scheduler/uci_and_pucch/pucch_alloc_harq_sr_csi_test.cpp index a0313932d4..9057a0106b 100644 --- a/tests/unittests/scheduler/uci_and_pucch/pucch_alloc_harq_sr_csi_test.cpp +++ b/tests/unittests/scheduler/uci_and_pucch/pucch_alloc_harq_sr_csi_test.cpp @@ -21,7 +21,8 @@ const unsigned NOF_RBS = 52; class test_pucch_allocator_ded_resources : public ::testing::Test { public: - test_pucch_allocator_ded_resources() + test_pucch_allocator_ded_resources(unsigned max_pucchs_per_slot_ = 32U, unsigned max_ul_grants_per_slot_ = 32U) : + t_bench(test_bench_params{}, max_pucchs_per_slot_, max_ul_grants_per_slot_) { // Set expected grant for PUCCH Format 1 SR. pucch_expected_f1_sr.format = pucch_format::FORMAT_1; @@ -1126,6 +1127,76 @@ TEST_F(test_pucch_allocator_ded_resources, test_for_private_fnc_retrieving_exist ASSERT_EQ(3, slot_grid.result.ul.pucchs[2].format_1.harq_ack_nof_bits); } +/////// Test UL grants reached and PUCCH fails. /////// + +class test_pucch_allocator_ded_resources_reached_ul_grants : public test_pucch_allocator_ded_resources +{ +public: + test_pucch_allocator_ded_resources_reached_ul_grants() : test_pucch_allocator_ded_resources(3U, 6U) {} +}; + +TEST_F(test_pucch_allocator_ded_resources_reached_ul_grants, test_max_pucch_allocation_reached) +{ + auto& slot_grid = t_bench.res_grid[t_bench.k0 + t_bench.k1]; + + add_csi_grant(); + ASSERT_EQ(1, slot_grid.result.ul.pucchs.size()); + + add_ue_with_harq_grant(); + ASSERT_EQ(2, slot_grid.result.ul.pucchs.size()); + + add_ue_with_harq_grant(); + ASSERT_EQ(3, slot_grid.result.ul.pucchs.size()); + + add_ue_with_harq_grant(); + ASSERT_EQ(3, slot_grid.result.ul.pucchs.size()); +} + +TEST_F(test_pucch_allocator_ded_resources_reached_ul_grants, test_max_ul_allocations_reached) +{ + auto& slot_grid = t_bench.res_grid[t_bench.k0 + t_bench.k1]; + + slot_grid.result.ul.puschs.emplace_back(); + slot_grid.result.ul.puschs.emplace_back(); + slot_grid.result.ul.puschs.emplace_back(); + + add_csi_grant(); + ASSERT_EQ(1, slot_grid.result.ul.pucchs.size()); + + add_ue_with_harq_grant(); + ASSERT_EQ(2, slot_grid.result.ul.pucchs.size()); + + add_ue_with_harq_grant(); + ASSERT_EQ(3, slot_grid.result.ul.pucchs.size()); + + add_ue_with_harq_grant(); + ASSERT_EQ(3, slot_grid.result.ul.pucchs.size()); +} + +TEST_F(test_pucch_allocator_ded_resources_reached_ul_grants, test_sr_max_ul_allocations_reached) +{ + auto& slot_grid = t_bench.res_grid[t_bench.k0 + t_bench.k1]; + + for (unsigned n = 0; n != 6U; ++n) { + slot_grid.result.ul.puschs.emplace_back(); + } + + add_sr_grant(); + ASSERT_EQ(0, slot_grid.result.ul.pucchs.size()); +} + +TEST_F(test_pucch_allocator_ded_resources_reached_ul_grants, test_csi_max_ul_allocations_reached) +{ + auto& slot_grid = t_bench.res_grid[t_bench.k0 + t_bench.k1]; + + for (unsigned n = 0; n != 6U; ++n) { + slot_grid.result.ul.puschs.emplace_back(); + } + + add_csi_grant(); + ASSERT_EQ(0, slot_grid.result.ul.pucchs.size()); +} + int main(int argc, char** argv) { srslog::fetch_basic_logger("TEST").set_level(srslog::basic_levels::info); diff --git a/tests/unittests/scheduler/uci_and_pucch/uci_test_utils.cpp b/tests/unittests/scheduler/uci_and_pucch/uci_test_utils.cpp index ff952a801d..d446bd08ef 100644 --- a/tests/unittests/scheduler/uci_and_pucch/uci_test_utils.cpp +++ b/tests/unittests/scheduler/uci_and_pucch/uci_test_utils.cpp @@ -110,7 +110,9 @@ bool srsran::assess_ul_pucch_info(const pucch_info& expected, const pucch_info& // Test bench with all that is needed for the PUCCH. -test_bench::test_bench(const test_bench_params& params) : +test_bench::test_bench(const test_bench_params& params, + unsigned max_pucchs_per_slot_, + unsigned max_ul_grants_per_slot_) : expert_cfg{config_helpers::make_default_scheduler_expert_config()}, cell_cfg{[this, ¶ms]() -> const cell_configuration& { cell_cfg_list.emplace( @@ -121,8 +123,10 @@ test_bench::test_bench(const test_bench_params& params) : }()}, dci_info{make_default_dci(params.n_cces, &cell_cfg.dl_cfg_common.init_dl_bwp.pdcch_common.coreset0.value())}, k0(cell_cfg.dl_cfg_common.init_dl_bwp.pdsch_common.pdsch_td_alloc_list[0].k0), + max_pucchs_per_slot{max_pucchs_per_slot_}, + max_ul_grants_per_slot{max_ul_grants_per_slot_}, pucch_f2_more_prbs{params.pucch_f2_more_prbs}, - pucch_alloc{cell_cfg}, + pucch_alloc{cell_cfg, max_pucchs_per_slot, max_ul_grants_per_slot}, uci_alloc(pucch_alloc), uci_sched{cell_cfg, uci_alloc, ues}, sl_tx{to_numerology_value(cell_cfg.dl_cfg_common.init_dl_bwp.generic_params.scs), 0} diff --git a/tests/unittests/scheduler/uci_and_pucch/uci_test_utils.h b/tests/unittests/scheduler/uci_and_pucch/uci_test_utils.h index 03249e4c96..7be8154269 100644 --- a/tests/unittests/scheduler/uci_and_pucch/uci_test_utils.h +++ b/tests/unittests/scheduler/uci_and_pucch/uci_test_utils.h @@ -96,7 +96,9 @@ struct test_bench_params { class test_bench { public: - explicit test_bench(const test_bench_params& params = {}); + explicit test_bench(const test_bench_params& params = {}, + unsigned max_pucchs_per_slot_ = 32U, + unsigned max_ul_grants_per_slot_ = 32U); // Return the main UE, which has RNTI 0x4601. const ue& get_main_ue() const; @@ -120,6 +122,8 @@ class test_bench pdcch_dl_information dci_info; const unsigned k0; const unsigned k1{4}; + const unsigned max_pucchs_per_slot; + const unsigned max_ul_grants_per_slot; du_ue_index_t main_ue_idx{du_ue_index_t::MIN_DU_UE_INDEX}; ue_repository ues; bool pucch_f2_more_prbs; diff --git a/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp b/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp index cc446c0d7b..7bd6e62dd9 100644 --- a/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp +++ b/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp @@ -84,7 +84,7 @@ struct test_bench { cell_resource_allocator res_grid{cell_cfg}; pdcch_resource_allocator_impl pdcch_sch{cell_cfg}; - pucch_allocator_impl pucch_alloc{cell_cfg}; + pucch_allocator_impl pucch_alloc{cell_cfg, 31U, 32U}; uci_allocator_impl uci_alloc{pucch_alloc}; ue_repository ue_db; ue_cell_grid_allocator ue_alloc; From 355194e880021cd54e068d355884f739174472fe Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Fri, 5 Jan 2024 12:29:33 +0100 Subject: [PATCH 077/134] sched: replace code with private function on pucch_alloc Signed-off-by: Carlo Galiotto --- .../pucch_scheduling/pucch_allocator_impl.cpp | 99 ++++--------------- .../pucch_scheduling/pucch_allocator_impl.h | 2 + 2 files changed, 22 insertions(+), 79 deletions(-) diff --git a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp index 1e5c393e0a..3b31ef5fe6 100644 --- a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp +++ b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp @@ -101,11 +101,8 @@ optional pucch_allocator_impl::alloc_common_pucch_harq_ack_ue(cell_res cell_slot_resource_allocator& pucch_slot_alloc = slot_alloc[k0 + k1 + slot_alloc.cfg.ntn_cs_koffset]; // [Implementation-defined] We only allow a max number of PUCCH + PUSCH grants per slot. - const unsigned max_pucchs_on_this_slot = - std::min(max_pucch_grants_per_slot, - max_ul_grants_per_slot - static_cast(pucch_slot_alloc.result.ul.puschs.size())); - - if (pucch_slot_alloc.result.ul.pucchs.full() or pucch_slot_alloc.result.ul.pucchs.size() >= max_pucchs_on_this_slot or + if (pucch_slot_alloc.result.ul.pucchs.size() >= + get_max_pucch_grants(static_cast(pucch_slot_alloc.result.ul.puschs.size())) or pucch_common_alloc_grid[slot_alloc[k0 + k1 + slot_alloc.cfg.ntn_cs_koffset].slot.to_uint()].full()) { return nullopt; } @@ -224,19 +221,9 @@ void pucch_allocator_impl::pucch_allocate_sr_opportunity(cell_slot_resource_allo const ue_cell_configuration& ue_cell_cfg) { // [Implementation-defined] We only allow a max number of PUCCH + PUSCH grants per slot. - const unsigned max_pucchs_on_this_slot = - std::min(max_pucch_grants_per_slot, - max_ul_grants_per_slot - static_cast(pucch_slot_alloc.result.ul.puschs.size())); - - if (pucch_slot_alloc.result.ul.pucchs.size() >= max_pucchs_on_this_slot) { - logger.warning( - "rnti={}: SR occasion allocation for slot={} skipped. Cause: UL grants reached", crnti, pucch_slot_alloc.slot); - return; - } - - if (pucch_slot_alloc.result.ul.pucchs.full()) { - logger.warning("rnti={}: SR occasion allocation for slot={} skipped. Cause: no more PUCCH grants available in " - "the scheduler", + if (pucch_slot_alloc.result.ul.pucchs.size() >= + get_max_pucch_grants(static_cast(pucch_slot_alloc.result.ul.puschs.size()))) { + logger.warning("rnti={}: SR occasion allocation for slot={} skipped. Cause: max number of UL grants reached", crnti, pucch_slot_alloc.slot); return; @@ -526,26 +513,14 @@ optional pucch_allocator_impl::allocate_new_format1_harq_grant(cell_sl pucch_info* existing_sr_grant) { // [Implementation-defined] We only allow a max number of PUCCH + PUSCH grants per slot. - const unsigned max_pucchs_on_this_slot = - std::min(max_pucch_grants_per_slot, - max_ul_grants_per_slot - static_cast(pucch_slot_alloc.result.ul.puschs.size())); - - if (pucch_slot_alloc.result.ul.pucchs.size() >= max_pucchs_on_this_slot) { + if (pucch_slot_alloc.result.ul.pucchs.size() >= + get_max_pucch_grants(static_cast(pucch_slot_alloc.result.ul.puschs.size()))) { logger.info("rnti={}: HARQ-ACK allocation on PUCCH Format1 for slot={} skipped. Cause: UL grants reached", crnti, pucch_slot_alloc.slot); return nullopt; } - // Check if there is space for one more additional PUCCH HARQ grant. - if (pucch_slot_alloc.result.ul.pucchs.full()) { - logger.warning("rnti={}: PUCCH HARQ-ACK grant for slot={} not allocated. Cause: no more PUCCH grants available " - "in the scheduler", - crnti, - pucch_slot_alloc.slot); - return nullopt; - } - const pucch_harq_resource_alloc_record pucch_harq_res_info = resource_manager.reserve_next_f1_harq_res_available( pucch_slot_alloc.slot, crnti, ue_cell_cfg.cfg_dedicated().ul_config.value().init_ul_bwp.pucch_cfg.value()); if (pucch_harq_res_info.pucch_res == nullptr) { @@ -619,11 +594,8 @@ void pucch_allocator_impl::convert_to_format2_csi(cell_slot_resource_allocator& pucch_slot_alloc, rnti, ue_cell_cfg.cfg_dedicated().ul_config.value().init_ul_bwp.pucch_cfg.value()); // [Implementation-defined] We only allow a max number of PUCCH + PUSCH grants per slot. - const unsigned max_pucchs_on_this_slot = - std::min(max_pucch_grants_per_slot, - max_ul_grants_per_slot - static_cast(pucch_slot_alloc.result.ul.puschs.size())); - - if (pucch_slot_alloc.result.ul.pucchs.size() >= max_pucchs_on_this_slot) { + if (pucch_slot_alloc.result.ul.pucchs.size() >= + get_max_pucch_grants(static_cast(pucch_slot_alloc.result.ul.puschs.size()))) { logger.warning("rnti={}: UCI allocation on PUCCH Format2 for slot={} skipped. Cause: UL grants reached", rnti, pucch_slot_alloc.slot); @@ -711,26 +683,14 @@ optional pucch_allocator_impl::convert_to_format2_harq(cell_slot_resou pucch_slot_alloc, rnti, ue_cell_cfg.cfg_dedicated().ul_config.value().init_ul_bwp.pucch_cfg.value()); // [Implementation-defined] We only allow a max number of PUCCH + PUSCH grants per slot. - const unsigned max_pucchs_on_this_slot = - std::min(max_pucch_grants_per_slot, - max_ul_grants_per_slot - static_cast(pucch_slot_alloc.result.ul.puschs.size())); - - if (pucch_slot_alloc.result.ul.pucchs.size() >= max_pucchs_on_this_slot) { + if (pucch_slot_alloc.result.ul.pucchs.size() >= + get_max_pucch_grants(static_cast(pucch_slot_alloc.result.ul.puschs.size()))) { logger.info("rnti={}: HARQ-ACK allocation on PUCCH Format2 for slot={} skipped. Cause: UL grants reached", rnti, pucch_slot_alloc.slot); return nullopt; } - // Allocate PUCCH SR grant only. - if (pucch_slot_alloc.result.ul.pucchs.full()) { - logger.warning("rnti={}: UCI could not be allocated on PUCCH Format2 for slot={}. Cause: List still full after " - "removing PUCCH F1 grants", - rnti, - pucch_slot_alloc.slot); - return nullopt; - } - // Allocate PUCCH SR grant only, as HARQ-ACK grant has been allocated earlier. pucch_info& pucch_pdu = pucch_slot_alloc.result.ul.pucchs.emplace_back(); const unsigned csi1_nof_bits_only_harq = 0U; @@ -819,26 +779,14 @@ optional pucch_allocator_impl::change_format2_resource(cell_slot_resou remove_format2_csi_from_grants(pucch_slot_alloc, rnti, ue_cell_cfg); // [Implementation-defined] We only allow a max number of PUCCH + PUSCH grants per slot. - const unsigned max_pucchs_on_this_slot = - std::min(max_pucch_grants_per_slot, - max_ul_grants_per_slot - static_cast(pucch_slot_alloc.result.ul.puschs.size())); - - if (pucch_slot_alloc.result.ul.pucchs.size() >= max_pucchs_on_this_slot) { + if (pucch_slot_alloc.result.ul.pucchs.size() >= + get_max_pucch_grants(static_cast(pucch_slot_alloc.result.ul.puschs.size()))) { logger.info("rnti={}: HARQ-ACK allocation on PUCCH Format2 for slot={} skipped. Cause: UL grants reached", rnti, pucch_slot_alloc.slot); return nullopt; } - if (pucch_slot_alloc.result.ul.pucchs.full()) { - logger.warning( - "rnti={}: HARQ-ACK could not be allocated on PUCCH Format2 for slot={}. Cause: List still full after " - "removing PUCCH F2 CSI grant", - rnti, - pucch_slot_alloc.slot); - return nullopt; - } - pucch_info& pucch_pdu = pucch_slot_alloc.result.ul.pucchs.emplace_back(); fill_pucch_format2_grant(pucch_pdu, rnti, @@ -941,26 +889,14 @@ void pucch_allocator_impl::allocate_new_csi_grant(cell_slot_resource_allocator& srsran_assert(csi_part1_bits != 0, "This function can only be called to allocate a PUCCH F2 resource for CSI"); // [Implementation-defined] We only allow a max number of PUCCH + PUSCH grants per slot. - const unsigned max_pucchs_on_this_slot = - std::min(max_pucch_grants_per_slot, - max_ul_grants_per_slot - static_cast(pucch_slot_alloc.result.ul.puschs.size())); - - if (pucch_slot_alloc.result.ul.pucchs.size() >= max_pucchs_on_this_slot) { + if (pucch_slot_alloc.result.ul.pucchs.size() >= + get_max_pucch_grants(static_cast(pucch_slot_alloc.result.ul.puschs.size()))) { logger.warning("rnti={}: CSI allocation on PUCCH Format2 for slot={} skipped. Cause: UL grants reached", crnti, pucch_slot_alloc.slot); return; } - // Check if there is space for new PUCCH grants in the scheduler. - if (pucch_slot_alloc.result.ul.pucchs.full()) { - logger.warning( - "rnti={}: PUCCH Format 2 grant allocation for slot={} skipped. Cause: scheduler PUCCH grant list is full", - crnti, - pucch_slot_alloc.slot); - return; - } - // Get the F2 resource specific for with CSI. const pucch_resource* csi_f2_res = resource_manager.reserve_csi_resource(pucch_slot_alloc.slot, crnti, ue_cell_cfg); @@ -1201,3 +1137,8 @@ bool pucch_allocator_impl::is_pucch_f1_grant_common(rnti_t rnti, slot_point sl_t pucch_common_alloc_grid[sl_tx.to_uint()].end(), rnti) != pucch_common_alloc_grid[sl_tx.to_uint()].end(); } + +unsigned pucch_allocator_impl::get_max_pucch_grants(unsigned currently_allocated_pucchs) +{ + return std::min(max_pucch_grants_per_slot, max_ul_grants_per_slot - currently_allocated_pucchs); +} diff --git a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.h b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.h index 604c3bf1b2..74c051c543 100644 --- a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.h +++ b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.h @@ -168,6 +168,8 @@ class pucch_allocator_impl final : public pucch_allocator existing_pucch_grants get_existing_pucch_grants(static_vector& pucchs, rnti_t rnti, slot_point sl_ack); + unsigned get_max_pucch_grants(unsigned currently_allocated_pucchs); + using slot_alloc_list = static_vector; // \brief Ring of PUCCH allocations indexed by slot. From 9f13007d8a53f42f376af0f51cdad51a08f59291 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Fri, 5 Jan 2024 16:58:18 +0100 Subject: [PATCH 078/134] gnb: move max_ul_grants to ul_common subcommand Signed-off-by: Carlo Galiotto --- apps/gnb/gnb_appconfig.h | 15 +++-------- apps/gnb/gnb_appconfig_cli11_schema.cpp | 27 +++++++------------ apps/gnb/gnb_appconfig_translators.cpp | 4 +-- apps/gnb/gnb_appconfig_validators.cpp | 15 +++++++++++ .../config/scheduler_expert_config.h | 2 +- .../pucch_scheduling/pucch_allocator_impl.cpp | 4 +-- .../pucch_scheduling/pucch_allocator_impl.h | 2 +- 7 files changed, 35 insertions(+), 34 deletions(-) diff --git a/apps/gnb/gnb_appconfig.h b/apps/gnb/gnb_appconfig.h index 3ec700ab52..e3650f94d6 100644 --- a/apps/gnb/gnb_appconfig.h +++ b/apps/gnb/gnb_appconfig.h @@ -298,9 +298,6 @@ struct pucch_appconfig { /// Maximum number of consecutive undecoded PUCCH Format 2 for CSI before an RLF is reported. unsigned max_consecutive_kos = 100; - - /// Maximum number of PUCCH grants per slot. - unsigned max_pucchs_per_slot = 31U; }; /// Parameters that are used to initialize or build the \c PhysicalCellGroupConfig, TS 38.331. @@ -324,6 +321,10 @@ struct amplitude_control_appconfig { struct ul_common_appconfig { /// Maximum transmit power allowed in this serving cell. Values: {-30,...,33}dBm. optional p_max; + /// Maximum number of PUCCH grants per slot. + unsigned max_pucchs_per_slot = 31U; + /// Maximum number of PUSCH + PUCCH grants per slot. + unsigned max_ul_grants_per_slot = 32U; }; struct ssb_appconfig { @@ -441,12 +442,6 @@ struct mac_cell_group_appconfig { mac_sr_appconfig sr_cfg; }; -/// Scheduler expert configuration. -struct sched_expert_appconfig { - /// Maximum number of PUSCH + PUCCH grants per slot. - unsigned max_ul_grants_per_slot = 32U; -}; - /// Base cell configuration. struct base_cell_appconfig { /// Physical cell identifier. @@ -497,8 +492,6 @@ struct base_cell_appconfig { paging_appconfig paging_cfg; /// CSI configuration. csi_appconfig csi_cfg; - /// Scheduler expert configuration. - sched_expert_appconfig sched_expert; }; /// Cell configuration diff --git a/apps/gnb/gnb_appconfig_cli11_schema.cpp b/apps/gnb/gnb_appconfig_cli11_schema.cpp index 7fad6a1b62..0b23738b64 100644 --- a/apps/gnb/gnb_appconfig_cli11_schema.cpp +++ b/apps/gnb/gnb_appconfig_cli11_schema.cpp @@ -884,11 +884,6 @@ static void configure_cli11_pucch_args(CLI::App& app, pucch_appconfig& pucch_par pucch_params.max_consecutive_kos, "Maximum number of consecutive undecoded PUCCH F2 for CSI before an Radio Link Failure is reported") ->capture_default_str(); - app.add_option("--max_pucchs_per_slot", - pucch_params.max_pucchs_per_slot, - "Maximum number of PUCCH grants that can be allocated per slot.") - ->capture_default_str() - ->check(CLI::Range(1U, static_cast(MAX_PUCCH_PDUS_PER_SLOT))); } static void configure_cli11_ul_common_args(CLI::App& app, ul_common_appconfig& ul_common_params) @@ -896,6 +891,16 @@ static void configure_cli11_ul_common_args(CLI::App& app, ul_common_appconfig& u app.add_option("--p_max", ul_common_params.p_max, "Maximum transmit power allowed in this serving cell") ->capture_default_str() ->check(CLI::Range(-30, 23)); + app.add_option("--max_pucchs_per_slot", + ul_common_params.max_pucchs_per_slot, + "Maximum number of PUCCH grants that can be allocated per slot") + ->capture_default_str() + ->check(CLI::Range(1U, static_cast(MAX_PUCCH_PDUS_PER_SLOT))); + app.add_option("--max_ul_grants_per_slot", + ul_common_params.max_ul_grants_per_slot, + "Maximum number of UL grants that can be allocated per slot") + ->capture_default_str() + ->check(CLI::Range(1U, (unsigned)(MAX_PUSCH_PDUS_PER_SLOT + MAX_PUCCH_PDUS_PER_SLOT))); } static void configure_cli11_ssb_args(CLI::App& app, ssb_appconfig& ssb_params) @@ -1245,14 +1250,6 @@ static void configure_cli11_mac_cell_group_args(CLI::App& app, mac_cell_group_ap configure_cli11_mac_sr_args(*sr_subcmd, mcg_params.sr_cfg); } -static void configure_cli11_sched_expert_args(CLI::App& app, sched_expert_appconfig& sched_exp_params) -{ - app.add_option( - "--max_ul_grants_per_slot", sched_exp_params.max_ul_grants_per_slot, "Maximum number of UL grants per slot") - ->capture_default_str() - ->check(CLI::Range(1U, (unsigned)(MAX_PUSCH_PDUS_PER_SLOT + MAX_PUCCH_PDUS_PER_SLOT))); -} - static void configure_cli11_common_cell_args(CLI::App& app, base_cell_appconfig& cell_params) { app.add_option("--pci", cell_params.pci, "PCI")->capture_default_str()->check(CLI::Range(0, 1007)); @@ -1383,10 +1380,6 @@ static void configure_cli11_common_cell_args(CLI::App& app, base_cell_appconfig& // CSI configuration. CLI::App* csi_subcmd = app.add_subcommand("csi", "CSI-Meas parameters"); configure_cli11_csi_args(*csi_subcmd, cell_params.csi_cfg); - - // Scheduler expert configuration. - CLI::App* sched_expert_subcmd = app.add_subcommand("sched_expert", "Scheduler parameters"); - configure_cli11_sched_expert_args(*sched_expert_subcmd, cell_params.sched_expert); } static void configure_cli11_cells_args(CLI::App& app, cell_appconfig& cell_params) diff --git a/apps/gnb/gnb_appconfig_translators.cpp b/apps/gnb/gnb_appconfig_translators.cpp index 9b6808c908..4b39c6a335 100644 --- a/apps/gnb/gnb_appconfig_translators.cpp +++ b/apps/gnb/gnb_appconfig_translators.cpp @@ -1675,8 +1675,8 @@ scheduler_expert_config srsran::generate_scheduler_expert_config(const gnb_appco out_cfg.ue.olla_max_ul_snr_offset = pusch.olla_max_snr_offset; // PUCCH and scheduler expert parameters. - out_cfg.ue.max_ul_grants_per_slot = cell.sched_expert.max_ul_grants_per_slot; - out_cfg.ue.max_pucchs_per_slot = cell.pucch_cfg.max_pucchs_per_slot; + out_cfg.ue.max_ul_grants_per_slot = cell.ul_common_cfg.max_ul_grants_per_slot; + out_cfg.ue.max_pucchs_per_slot = cell.ul_common_cfg.max_pucchs_per_slot; // RA parameters. const prach_appconfig& prach = cell.prach_cfg; diff --git a/apps/gnb/gnb_appconfig_validators.cpp b/apps/gnb/gnb_appconfig_validators.cpp index 64b7352925..0ef51e1b07 100644 --- a/apps/gnb/gnb_appconfig_validators.cpp +++ b/apps/gnb/gnb_appconfig_validators.cpp @@ -267,6 +267,17 @@ static bool validate_pucch_cell_app_config(const base_cell_appconfig& config, su return true; } +/// Validates the given PUCCH cell application configuration. Returns true on success, otherwise false. +static bool validate_ul_common_app_config(const ul_common_appconfig& config) +{ + if (config.max_ul_grants_per_slot <= config.max_pucchs_per_slot) { + fmt::print("The max number of UL grants per slot should be greater than the maximum number of PUCCH grants.\n"); + return false; + } + + return true; +} + /// Validates the given PRACH cell application configuration. Returns true on success, otherwise false. static bool validate_prach_cell_app_config(const prach_appconfig& config, nr_band band, unsigned nof_rx_atennas) { @@ -493,6 +504,10 @@ static bool validate_base_cell_appconfig(const base_cell_appconfig& config) return false; } + if (!validate_ul_common_app_config(config.ul_common_cfg)) { + return false; + } + if (!validate_pusch_cell_app_config(config.pusch_cfg)) { return false; } diff --git a/include/srsran/scheduler/config/scheduler_expert_config.h b/include/srsran/scheduler/config/scheduler_expert_config.h index da6a4db0ca..0076ee987c 100644 --- a/include/srsran/scheduler/config/scheduler_expert_config.h +++ b/include/srsran/scheduler/config/scheduler_expert_config.h @@ -60,7 +60,7 @@ struct scheduler_ue_expert_config { /// Maximum number of PUSCH grants per slot. unsigned max_puschs_per_slot = MAX_PUSCH_PDUS_PER_SLOT; /// Maximum number of PUCCH grants per slot. - unsigned max_pucchs_per_slot = MAX_PUCCH_PDUS_PER_SLOT; + unsigned max_pucchs_per_slot{31U}; /// Maximum number of PUSCH + PUCCH grants per slot. unsigned max_ul_grants_per_slot{32U}; /// Maximum number of PDCCH grant allocation attempts per slot. Default: Unlimited. diff --git a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp index 3b31ef5fe6..915c5441ad 100644 --- a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp +++ b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp @@ -1138,7 +1138,7 @@ bool pucch_allocator_impl::is_pucch_f1_grant_common(rnti_t rnti, slot_point sl_t rnti) != pucch_common_alloc_grid[sl_tx.to_uint()].end(); } -unsigned pucch_allocator_impl::get_max_pucch_grants(unsigned currently_allocated_pucchs) +unsigned pucch_allocator_impl::get_max_pucch_grants(unsigned currently_allocated_puschs) { - return std::min(max_pucch_grants_per_slot, max_ul_grants_per_slot - currently_allocated_pucchs); + return std::min(max_pucch_grants_per_slot, max_ul_grants_per_slot - currently_allocated_puschs); } diff --git a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.h b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.h index 74c051c543..d7d3377d90 100644 --- a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.h +++ b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.h @@ -168,7 +168,7 @@ class pucch_allocator_impl final : public pucch_allocator existing_pucch_grants get_existing_pucch_grants(static_vector& pucchs, rnti_t rnti, slot_point sl_ack); - unsigned get_max_pucch_grants(unsigned currently_allocated_pucchs); + unsigned get_max_pucch_grants(unsigned currently_allocated_puschs); using slot_alloc_list = static_vector; From b9abff916512a1708423898d565e642674ed3f93 Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Tue, 9 Jan 2024 09:51:42 +0100 Subject: [PATCH 079/134] e1ap: return handling of bearer ctx mod req if UE context was not found. --- lib/e1ap/cu_up/e1ap_cu_up_impl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/e1ap/cu_up/e1ap_cu_up_impl.cpp b/lib/e1ap/cu_up/e1ap_cu_up_impl.cpp index f79380b41b..67480b210d 100644 --- a/lib/e1ap/cu_up/e1ap_cu_up_impl.cpp +++ b/lib/e1ap/cu_up/e1ap_cu_up_impl.cpp @@ -263,6 +263,7 @@ void e1ap_cu_up_impl::handle_bearer_context_modification_request(const asn1::e1a if (!ue_ctxt_list.contains(int_to_gnb_cu_up_ue_e1ap_id(msg->gnb_cu_up_ue_e1ap_id))) { logger.warning("Sending BearerContextModificationFailure. UE context not available"); connection_handler.on_new_message(e1ap_msg); + return; } e1ap_ue_context& ue_ctxt = ue_ctxt_list[int_to_gnb_cu_up_ue_e1ap_id(msg->gnb_cu_up_ue_e1ap_id)]; From 67c063c47d48cdcb0248e1c1fafbaf561ef0d6c5 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 20 Dec 2023 12:19:17 +0000 Subject: [PATCH 080/134] pdcp: refactored pdcp to avoid allocating as much from the pool --- include/srsran/adt/byte_buffer.h | 7 +- include/srsran/security/ciphering.h | 35 +++--- lib/pdcp/pdcp_entity_rx.cpp | 22 ++-- lib/pdcp/pdcp_entity_rx.h | 2 +- lib/pdcp/pdcp_entity_tx.cpp | 118 ++++++++++----------- lib/pdcp/pdcp_entity_tx.h | 4 +- tests/unittests/security/security_test.cpp | 53 ++++++--- 7 files changed, 130 insertions(+), 111 deletions(-) diff --git a/include/srsran/adt/byte_buffer.h b/include/srsran/adt/byte_buffer.h index bd23d8c7d8..13ad6b4952 100644 --- a/include/srsran/adt/byte_buffer.h +++ b/include/srsran/adt/byte_buffer.h @@ -96,6 +96,11 @@ class byte_buffer_view /// Returns a non-owning list of segments that compose the byte_buffer. const_byte_buffer_segment_span_range segments() const { return {it, length()}; } + /// Returns a non-owning list of segments that compose the byte_buffer. + /// The segments are not const, so that the callee can modify the bytes, + /// but not layout of the buffer. + byte_buffer_segment_span_range modifiable_segments() { return {it, length()}; }; + /// \brief Equality comparison between byte buffer view and another range. template friend bool operator==(const byte_buffer_view& lhs, const T& r) @@ -479,7 +484,7 @@ class byte_buffer_slice /// Converts to non-owning byte buffer view. byte_buffer_view view() const { return sliced_view; } - explicit operator byte_buffer_view() const { return sliced_view; } + explicit operator byte_buffer_view() const { return sliced_view; } /// Returns another owning sub-view with dimensions specified in arguments. byte_buffer_slice make_slice(size_t offset, size_t size) const diff --git a/include/srsran/security/ciphering.h b/include/srsran/security/ciphering.h index d341461e13..09fd941c1f 100644 --- a/include/srsran/security/ciphering.h +++ b/include/srsran/security/ciphering.h @@ -28,7 +28,7 @@ inline void security_nea1(const sec_128_key& key, uint32_t count, uint8_t bearer, security_direction direction, - byte_buffer& msg, + byte_buffer_view& msg, uint32_t msg_len) { S3G_STATE state, *state_ptr; @@ -79,7 +79,7 @@ inline void security_nea1(const sec_128_key& key, } // Zero tailing bits - zero_tailing_bits(msg.back(), msg_len); + zero_tailing_bits(msg[offset - 1], msg_len); // Clean up free(ks); @@ -87,8 +87,11 @@ inline void security_nea1(const sec_128_key& key, } } -inline void -security_nea1(const sec_128_key& key, uint32_t count, uint8_t bearer, security_direction direction, byte_buffer& msg) +inline void security_nea1(const sec_128_key& key, + uint32_t count, + uint8_t bearer, + security_direction direction, + byte_buffer_view& msg) { return security_nea1(key, count, bearer, direction, msg, msg.length() * 8); } @@ -97,7 +100,7 @@ inline void security_nea2(const sec_128_key& key, uint32_t count, uint8_t bearer, security_direction direction, - byte_buffer& msg, + byte_buffer_view& msg, uint32_t msg_len) { aes_context ctx; @@ -124,7 +127,7 @@ inline void security_nea2(const sec_128_key& key, nonce_cnt[4] = ((bearer & 0x1f) << 3) | ((to_number(direction) & 0x01) << 2); // Encryption - byte_buffer_segment_span_range segments = msg.segments(); + byte_buffer_segment_span_range segments = msg.modifiable_segments(); for (const auto& segment : segments) { ret = aes_crypt_ctr(&ctx, segment.size(), &nc_off, nonce_cnt, stream_blk, segment.data(), segment.data()); } @@ -132,12 +135,15 @@ inline void security_nea2(const sec_128_key& key, } if (ret == 0) { // Zero tailing bits - zero_tailing_bits(msg.back(), msg_len); + zero_tailing_bits(msg[msg.length() - 1], msg_len); } } -inline void -security_nea2(const sec_128_key& key, uint32_t count, uint8_t bearer, security_direction direction, byte_buffer& msg) +inline void security_nea2(const sec_128_key& key, + uint32_t count, + uint8_t bearer, + security_direction direction, + byte_buffer_view& msg) { return security_nea2(key, count, bearer, direction, msg, msg.length() * 8); } @@ -146,7 +152,7 @@ inline void security_nea3(const sec_128_key& key, uint32_t count, uint8_t bearer, security_direction direction, - byte_buffer& msg, + byte_buffer_view& msg, uint32_t msg_len) { uint8_t iv[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -203,15 +209,18 @@ inline void security_nea3(const sec_128_key& key, offset++; } - zero_tailing_bits(msg.back(), msg_len); + zero_tailing_bits(msg[msg.length() - 1], msg_len); // Clean up free(ks); } } -inline void -security_nea3(const sec_128_key& key, uint32_t count, uint8_t bearer, security_direction direction, byte_buffer& msg) +inline void security_nea3(const sec_128_key& key, + uint32_t count, + uint8_t bearer, + security_direction direction, + byte_buffer_view& msg) { security_nea3(key, count, bearer, direction, msg, msg.length() * 8); } diff --git a/lib/pdcp/pdcp_entity_rx.cpp b/lib/pdcp/pdcp_entity_rx.cpp index 7427fecb2a..43931037b9 100644 --- a/lib/pdcp/pdcp_entity_rx.cpp +++ b/lib/pdcp/pdcp_entity_rx.cpp @@ -189,14 +189,10 @@ void pdcp_entity_rx::handle_data_pdu(byte_buffer pdu) * data part of the PDCP Data PDU except the * SDAP header and the SDAP Control PDU if included in the PDCP SDU. */ - byte_buffer sdu = pdu.deep_copy(); + byte_buffer_view sdu_plus_mac = byte_buffer_view{pdu.begin() + hdr_len_bytes, pdu.end()}; if (ciphering_enabled == security::ciphering_enabled::on && sec_cfg.cipher_algo != security::ciphering_algorithm::nea0) { - sdu.trim_head(hdr_len_bytes); - cipher_decrypt(sdu, rcvd_count); - std::array header_buf; - std::copy(pdu.begin(), pdu.begin() + hdr_len_bytes, header_buf.begin()); - sdu.prepend(span{header_buf.data(), hdr_len_bytes}); + cipher_decrypt(sdu_plus_mac, rcvd_count); } /* @@ -205,7 +201,7 @@ void pdcp_entity_rx::handle_data_pdu(byte_buffer pdu) */ security::sec_mac mac = {}; if (is_srb() || (is_drb() && (integrity_enabled == security::integrity_enabled::on))) { - extract_mac(sdu, mac); + extract_mac(pdu, mac); } /* @@ -215,19 +211,19 @@ void pdcp_entity_rx::handle_data_pdu(byte_buffer pdu) * and the data part of the PDU before ciphering. */ if (integrity_enabled == security::integrity_enabled::on) { - bool is_valid = integrity_verify(sdu, rcvd_count, mac); + bool is_valid = integrity_verify(pdu, rcvd_count, mac); if (!is_valid) { - logger.log_warning(sdu.begin(), sdu.end(), "Integrity failed, dropping PDU."); + logger.log_warning(pdu.begin(), pdu.end(), "Integrity failed, dropping PDU."); metrics_add_integrity_failed_pdus(1); // TODO: Re-enable once the RRC supports notifications from the PDCP // upper_cn.on_integrity_failure(); return; // Invalid packet, drop. } metrics_add_integrity_verified_pdus(1); - logger.log_debug(sdu.begin(), sdu.end(), "Integrity passed."); + logger.log_debug(pdu.begin(), pdu.end(), "Integrity passed."); } // After checking the integrity, we can discard the header. - discard_data_header(sdu); + discard_data_header(pdu); /* * Check valid rcvd_count: @@ -255,7 +251,7 @@ void pdcp_entity_rx::handle_data_pdu(byte_buffer pdu) // Store PDU in Rx window pdcp_rx_sdu_info& sdu_info = rx_window->add_sn(rcvd_count); - sdu_info.sdu = std::move(sdu); + sdu_info.sdu = std::move(pdu); sdu_info.count = rcvd_count; // Update RX_NEXT @@ -470,7 +466,7 @@ bool pdcp_entity_rx::integrity_verify(byte_buffer_view buf, uint32_t count, cons return is_valid; } -byte_buffer pdcp_entity_rx::cipher_decrypt(byte_buffer& msg, uint32_t count) +byte_buffer pdcp_entity_rx::cipher_decrypt(byte_buffer_view& msg, uint32_t count) { logger.log_debug("Cipher decrypt. count={} bearer_id={} dir={}", count, bearer_id, direction); logger.log_debug((uint8_t*)sec_cfg.k_128_enc.data(), sec_cfg.k_128_enc.size(), "Cipher decrypt key."); diff --git a/lib/pdcp/pdcp_entity_rx.h b/lib/pdcp/pdcp_entity_rx.h index bc93651e9e..c8c92afeae 100644 --- a/lib/pdcp/pdcp_entity_rx.h +++ b/lib/pdcp/pdcp_entity_rx.h @@ -182,7 +182,7 @@ class pdcp_entity_rx final : public pdcp_entity_tx_rx_base, void discard_all_sdus(); bool integrity_verify(byte_buffer_view buf, uint32_t count, const security::sec_mac& mac); - byte_buffer cipher_decrypt(byte_buffer& msg, uint32_t count); + byte_buffer cipher_decrypt(byte_buffer_view& msg, uint32_t count); /* * Notifiers and handlers diff --git a/lib/pdcp/pdcp_entity_tx.cpp b/lib/pdcp/pdcp_entity_tx.cpp index b55e27c140..30a17ae4f6 100644 --- a/lib/pdcp/pdcp_entity_tx.cpp +++ b/lib/pdcp/pdcp_entity_tx.cpp @@ -24,7 +24,7 @@ using namespace srsran; /// /// \param sdu Buffer that hold the SDU from higher layers. /// \ref TS 38.323 section 5.2.1: Transmit operation -void pdcp_entity_tx::handle_sdu(byte_buffer sdu) +void pdcp_entity_tx::handle_sdu(byte_buffer buf) { trace_point tx_tp = up_tracer.now(); // Avoid TX'ing if we are close to overload RLC SDU queue @@ -41,8 +41,8 @@ void pdcp_entity_tx::handle_sdu(byte_buffer sdu) return; } - metrics_add_sdus(1, sdu.length()); - logger.log_debug(sdu.begin(), sdu.end(), "TX SDU. sdu_len={}", sdu.length()); + metrics_add_sdus(1, buf.length()); + logger.log_debug(buf.begin(), buf.end(), "TX SDU. sdu_len={}", buf.length()); // The PDCP is not allowed to use the same COUNT value more than once for a given security key, // see TS 38.331, section 5.3.1.2. To avoid this, we notify the RRC once we exceed a "maximum" @@ -64,6 +64,12 @@ void pdcp_entity_tx::handle_sdu(byte_buffer sdu) } } + // 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(); + } + // Perform header compression // TODO @@ -72,16 +78,14 @@ void pdcp_entity_tx::handle_sdu(byte_buffer sdu) hdr.sn = SN(st.tx_next); // Pack header - byte_buffer header_buf = {}; - if (not write_data_pdu_header(header_buf, hdr)) { + if (not write_data_pdu_header(buf, hdr)) { logger.log_error("Could not append PDU header, dropping SDU and notifying RRC. count={}", st.tx_next); upper_cn.on_protocol_failure(); return; } // Apply ciphering and integrity protection - expected exp_buf = - apply_ciphering_and_integrity_protection(std::move(header_buf), sdu.deep_copy(), st.tx_next); + expected exp_buf = apply_ciphering_and_integrity_protection(std::move(buf), st.tx_next); if (exp_buf.is_error()) { logger.log_error("Could not apply ciphering and integrity protection, dropping SDU and notifying RRC. count={}", st.tx_next); @@ -256,60 +260,35 @@ void pdcp_entity_tx::handle_status_report(byte_buffer_chain status) /* * Ciphering and Integrity Protection Helpers */ -expected -pdcp_entity_tx::apply_ciphering_and_integrity_protection(byte_buffer hdr, byte_buffer sdu, uint32_t count) +expected pdcp_entity_tx::apply_ciphering_and_integrity_protection(byte_buffer buf, uint32_t count) { // TS 38.323, section 5.9: Integrity protection // The data unit that is integrity protected is the PDU header // and the data part of the PDU before ciphering. - security::sec_mac mac = {}; + unsigned hdr_size = cfg.sn_size == pdcp_sn_size::size12bits ? 2 : 3; + security::sec_mac mac = {}; + byte_buffer_view sdu_plus_header{buf.begin(), buf.end()}; if (integrity_enabled == security::integrity_enabled::on) { - byte_buffer buf = {}; - if (not buf.append(hdr)) { - return default_error_t{}; - } - if (not buf.append(sdu)) { + integrity_generate(mac, sdu_plus_header, count); + } + // Append MAC-I + if (is_srb() || (is_drb() && (integrity_enabled == security::integrity_enabled::on))) { + if (not buf.append(mac)) { return default_error_t{}; } - integrity_generate(mac, buf, count); } // TS 38.323, section 5.8: Ciphering // The data unit that is ciphered is the MAC-I and the // data part of the PDCP Data PDU except the // SDAP header and the SDAP Control PDU if included in the PDCP SDU. - byte_buffer ct; + byte_buffer_view sdu_plus_mac{buf.begin() + hdr_size, buf.end()}; if (ciphering_enabled == security::ciphering_enabled::on && sec_cfg.cipher_algo != security::ciphering_algorithm::nea0) { - // Append MAC-I - if (is_srb() || (is_drb() && (integrity_enabled == security::integrity_enabled::on))) { - if (not sdu.append(mac)) { - return default_error_t{}; - } - } - cipher_encrypt(sdu, count); - ct = std::move(sdu); - } else { - ct = std::move(sdu); - - // Append MAC-I - if (is_srb() || (is_drb() && (integrity_enabled == security::integrity_enabled::on))) { - if (not ct.append(mac)) { - return default_error_t{}; - } - } + cipher_encrypt(sdu_plus_mac, count); } - // Construct the protected buffer - byte_buffer protected_buf; - if (not protected_buf.append(std::move(hdr))) { - return default_error_t{}; - } - if (not protected_buf.append(std::move(ct))) { - return default_error_t{}; - } - - return protected_buf; + return std::move(buf); } void pdcp_entity_tx::integrity_generate(security::sec_mac& mac, byte_buffer_view buf, uint32_t count) @@ -342,7 +321,7 @@ void pdcp_entity_tx::integrity_generate(security::sec_mac& mac, byte_buffer_view logger.log_debug((uint8_t*)mac.data(), mac.size(), "MAC generated."); } -void pdcp_entity_tx::cipher_encrypt(byte_buffer& buf, uint32_t count) +void pdcp_entity_tx::cipher_encrypt(byte_buffer_view& buf, uint32_t count) { logger.log_debug("Cipher encrypt. count={} bearer_id={} dir={}", count, bearer_id, direction); logger.log_debug((uint8_t*)sec_cfg.k_128_enc.data(), sec_cfg.k_128_enc.size(), "Cipher encrypt key."); @@ -424,8 +403,8 @@ void pdcp_entity_tx::retransmit_all_pdus() hdr.sn = SN(sdu_info.count); // Pack header - byte_buffer header_buf = {}; - if (not write_data_pdu_header(header_buf, hdr)) { + byte_buffer buf = sdu_info.sdu.deep_copy(); + 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); upper_cn.on_protocol_failure(); @@ -436,8 +415,7 @@ void pdcp_entity_tx::retransmit_all_pdus() // (TODO) // Perform integrity protection and ciphering - expected exp_buf = - apply_ciphering_and_integrity_protection(std::move(header_buf), sdu_info.sdu.deep_copy(), sdu_info.count); + expected exp_buf = apply_ciphering_and_integrity_protection(std::move(buf), sdu_info.count); if (exp_buf.is_error()) { logger.log_error("Could not apply ciphering and integrity protection during retransmissions, dropping SDU and " "notifying RRC. count={} {}", @@ -554,37 +532,49 @@ bool pdcp_entity_tx::write_data_pdu_header(byte_buffer& buf, const pdcp_data_pdu srsran_assert( !(is_srb() && cfg.sn_size == pdcp_sn_size::size18bits), "Invalid SN size for SRB. sn_size={}", cfg.sn_size); - byte_buffer_writer hdr_writer = buf; + unsigned hdr_len = cfg.sn_size == pdcp_sn_size::size12bits ? 2 : 3; + auto view = buf.reserve_prepend(cfg.sn_size == pdcp_sn_size::size12bits ? 2 : 3); + if (view.length() != hdr_len) { + logger.log_error("Not enough space to write header. sn_size={}", cfg.sn_size); + return false; + } + + byte_buffer::iterator hdr_writer = buf.begin(); + if (hdr_writer == buf.end()) { + logger.log_error("Not enough space to write header. sn_size={}", cfg.sn_size); + } // Set D/C if required if (is_drb()) { // D/C bit field (1). - if (not hdr_writer.append(0x80)) { - return false; - } + *hdr_writer = 0x80; } else { // No D/C bit field. - if (not hdr_writer.append(0x00)) { - return false; - } + *hdr_writer = 0x00; } // Add SN switch (cfg.sn_size) { case pdcp_sn_size::size12bits: - hdr_writer.back() |= (hdr.sn & 0x00000f00U) >> 8U; - if (not hdr_writer.append((hdr.sn & 0x000000ffU))) { - return false; + *hdr_writer |= (hdr.sn & 0x00000f00U) >> 8U; + hdr_writer++; + if (hdr_writer == buf.end()) { + logger.log_error("Not enough space to write header. sn_size={}", cfg.sn_size); } + *hdr_writer = hdr.sn & 0x000000ffU; break; case pdcp_sn_size::size18bits: - hdr_writer.back() |= (hdr.sn & 0x00030000U) >> 16U; - if (not hdr_writer.append((hdr.sn & 0x0000ff00U) >> 8U)) { - return false; + *hdr_writer |= (hdr.sn & 0x00030000U) >> 16U; + hdr_writer++; + if (hdr_writer == buf.end()) { + logger.log_error("Not enough space to write header. sn_size={}", cfg.sn_size); } - if (not hdr_writer.append((hdr.sn & 0x000000ffU))) { - return false; + *hdr_writer = (hdr.sn & 0x0000ff00U) >> 8U; + hdr_writer++; + if (hdr_writer == buf.end()) { + logger.log_error("Not enough space to write header. sn_size={}", cfg.sn_size); } + *hdr_writer = hdr.sn & 0x000000ffU; break; default: logger.log_error("Invalid sn_size={}", cfg.sn_size); diff --git a/lib/pdcp/pdcp_entity_tx.h b/lib/pdcp/pdcp_entity_tx.h index cf244145f1..d0affe3f6a 100644 --- a/lib/pdcp/pdcp_entity_tx.h +++ b/lib/pdcp/pdcp_entity_tx.h @@ -225,9 +225,9 @@ class pdcp_entity_tx final : public pdcp_entity_tx_rx_base, void write_control_pdu_to_lower_layers(byte_buffer buf); /// Apply ciphering and integrity protection to the payload - expected apply_ciphering_and_integrity_protection(byte_buffer hdr, byte_buffer sdu, uint32_t count); + expected apply_ciphering_and_integrity_protection(byte_buffer sdu_plus_header, uint32_t count); void integrity_generate(security::sec_mac& mac, byte_buffer_view buf, uint32_t count); - void cipher_encrypt(byte_buffer& buf, uint32_t count); + void cipher_encrypt(byte_buffer_view& buf, uint32_t count); uint32_t notification_count_estimation(uint32_t notification_sn); diff --git a/tests/unittests/security/security_test.cpp b/tests/unittests/security/security_test.cpp index 0e37b28861..a6210126f6 100644 --- a/tests/unittests/security/security_test.cpp +++ b/tests/unittests/security/security_test.cpp @@ -69,7 +69,9 @@ TEST(security_nea1_test, testset1) byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr); // Apply ciphering and compare results - security_nea1(key, count, bearer, dir, plaintext, length); + byte_buffer_view plaintext_view{plaintext}; + security_nea1(key, count, bearer, dir, plaintext_view, length); + EXPECT_EQ(ciphertext, plaintext); } @@ -99,7 +101,8 @@ TEST(security_nea1_test, testset2) byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr); // Apply ciphering and compare results - security_nea1(key, count, bearer, dir, plaintext, length); + byte_buffer_view plaintext_view{plaintext}; + security_nea1(key, count, bearer, dir, plaintext_view, length); EXPECT_EQ(ciphertext, plaintext); } @@ -125,7 +128,8 @@ TEST(security_nea1_test, testset3) byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr); // Apply ciphering and compare results - security_nea1(key, count, bearer, dir, plaintext, length); + byte_buffer_view plaintext_view{plaintext}; + security_nea1(key, count, bearer, dir, plaintext_view, length); EXPECT_EQ(ciphertext, plaintext); } @@ -155,7 +159,8 @@ TEST(security_nea1_test, testset4) byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr); // Apply ciphering and compare results - security_nea1(key, count, bearer, dir, plaintext, length); + byte_buffer_view plaintext_view{plaintext}; + security_nea1(key, count, bearer, dir, plaintext_view, length); EXPECT_EQ(ciphertext, plaintext); } @@ -187,7 +192,8 @@ TEST(security_nea1_test, testset5) byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr); // Apply ciphering and compare results - security_nea1(key, count, bearer, dir, plaintext, length); + byte_buffer_view plaintext_view{plaintext}; + security_nea1(key, count, bearer, dir, plaintext_view, length); EXPECT_EQ(ciphertext, plaintext); } @@ -231,7 +237,8 @@ TEST(security_nea1_test, testset6) byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr); // Apply ciphering and compare results - security_nea1(key, count, bearer, dir, plaintext, length); + byte_buffer_view plaintext_view{plaintext}; + security_nea1(key, count, bearer, dir, plaintext_view, length); EXPECT_EQ(ciphertext, plaintext); } @@ -477,7 +484,8 @@ TEST(security_nea2_test, testset1) byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr); // Apply ciphering and compare results - security_nea2(key, count, bearer, dir, plaintext, length); + byte_buffer_view plaintext_view{plaintext}; + security_nea2(key, count, bearer, dir, plaintext_view, length); EXPECT_EQ(ciphertext, plaintext); } @@ -505,7 +513,8 @@ TEST(security_nea2_test, testset2) byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr); // Apply ciphering and compare results - security_nea2(key, count, bearer, dir, plaintext, length); + byte_buffer_view plaintext_view{plaintext}; + security_nea2(key, count, bearer, dir, plaintext_view, length); EXPECT_EQ(ciphertext, plaintext); } @@ -529,7 +538,8 @@ TEST(security_nea2_test, testset3) byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr); // Apply ciphering and compare results - security_nea2(key, count, bearer, dir, plaintext, length); + byte_buffer_view plaintext_view{plaintext}; + security_nea2(key, count, bearer, dir, plaintext_view, length); EXPECT_EQ(ciphertext, plaintext); } @@ -557,7 +567,8 @@ TEST(security_nea2_test, testset4) byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr); // Apply ciphering and compare results - security_nea2(key, count, bearer, dir, plaintext, length); + byte_buffer_view plaintext_view{plaintext}; + security_nea2(key, count, bearer, dir, plaintext_view, length); EXPECT_EQ(ciphertext, plaintext); } @@ -587,7 +598,8 @@ TEST(security_nea2_test, testset5) byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr); // Apply ciphering and compare results - security_nea2(key, count, bearer, dir, plaintext, length); + byte_buffer_view plaintext_view{plaintext}; + security_nea2(key, count, bearer, dir, plaintext_view, length); EXPECT_EQ(ciphertext, plaintext); } @@ -629,7 +641,8 @@ TEST(security_nea2_test, testset6) byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr); // Apply ciphering and compare results - security_nea2(key, count, bearer, dir, plaintext, length); + byte_buffer_view plaintext_view{plaintext}; + security_nea2(key, count, bearer, dir, plaintext_view, length); EXPECT_EQ(ciphertext, plaintext); } @@ -902,7 +915,8 @@ TEST(security_nea3_test, testset1) byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr); // Apply ciphering and compare results - security_nea3(key, count, bearer, dir, plaintext, length); + byte_buffer_view plaintext_view{plaintext}; + security_nea3(key, count, bearer, dir, plaintext_view, length); EXPECT_EQ(ciphertext, plaintext); } @@ -932,7 +946,8 @@ TEST(security_nea3_test, testset2) byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr); // Apply ciphering and compare results - security_nea3(key, count, bearer, dir, plaintext, length); + byte_buffer_view plaintext_view{plaintext}; + security_nea3(key, count, bearer, dir, plaintext_view, length); EXPECT_EQ(ciphertext, plaintext); } @@ -966,7 +981,8 @@ TEST(security_nea3_test, testset3) byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr); // Apply ciphering and compare results - security_nea3(key, count, bearer, dir, plaintext, length); + byte_buffer_view plaintext_view{plaintext}; + security_nea3(key, count, bearer, dir, plaintext_view, length); EXPECT_EQ(ciphertext, plaintext); } @@ -1006,7 +1022,8 @@ TEST(security_nea3_test, testset4) byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr); // Apply ciphering and compare results - security_nea3(key, count, bearer, dir, plaintext, length); + byte_buffer_view plaintext_view{plaintext}; + security_nea3(key, count, bearer, dir, plaintext_view, length); EXPECT_EQ(ciphertext, plaintext); } @@ -1050,7 +1067,8 @@ TEST(security_nea3_test, testset5) byte_buffer ciphertext = make_byte_buffer(ciphertext_cstr); // Apply ciphering and compare results - security_nea3(key, count, bearer, dir, plaintext, length); + byte_buffer_view plaintext_view{plaintext}; + security_nea3(key, count, bearer, dir, plaintext_view, length); EXPECT_EQ(ciphertext, plaintext); } @@ -1382,6 +1400,7 @@ TEST(short_mac, short_mac_valid) int main(int argc, char** argv) { + srslog::init(); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } From 4bd5849e49f14440026dddd78a9a5f7c1d311728 Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Tue, 9 Jan 2024 13:18:16 +0100 Subject: [PATCH 081/134] adt: cosmetic newline --- include/srsran/adt/byte_buffer.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/srsran/adt/byte_buffer.h b/include/srsran/adt/byte_buffer.h index 13ad6b4952..619424fa02 100644 --- a/include/srsran/adt/byte_buffer.h +++ b/include/srsran/adt/byte_buffer.h @@ -484,6 +484,7 @@ class byte_buffer_slice /// Converts to non-owning byte buffer view. byte_buffer_view view() const { return sliced_view; } + explicit operator byte_buffer_view() const { return sliced_view; } /// Returns another owning sub-view with dimensions specified in arguments. From b876c8c92daddd5a2c33d1362ebf6385940e04ef Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 22 Dec 2023 18:01:33 +0100 Subject: [PATCH 082/134] phy: common PUSCH processor dependency pool --- include/srsran/phy/upper/channel_estimation.h | 2 + .../channel_processors/pusch/factories.h | 1 + .../channel_processors/pusch/factories.cpp | 52 ++++--- .../pusch/pusch_decoder_impl.h | 4 +- .../pusch/pusch_processor_impl.cpp | 44 +++--- .../pusch/pusch_processor_impl.h | 147 ++++++++++-------- lib/phy/upper/upper_phy_factories.cpp | 13 +- .../pusch/pusch_processor_benchmark.cpp | 1 + .../pusch/pusch_decoder_buffer_test_doubles.h | 8 +- .../pusch/pusch_decoder_test_doubles.h | 8 +- .../pusch/pusch_processor_unittest.cpp | 2 +- .../pusch/pusch_processor_validator_test.cpp | 1 + .../pusch/pusch_processor_vectortest.cpp | 3 +- 13 files changed, 154 insertions(+), 132 deletions(-) diff --git a/include/srsran/phy/upper/channel_estimation.h b/include/srsran/phy/upper/channel_estimation.h index fbc9954599..a7c8d4cfe9 100644 --- a/include/srsran/phy/upper/channel_estimation.h +++ b/include/srsran/phy/upper/channel_estimation.h @@ -55,6 +55,8 @@ class channel_estimate unsigned nof_tx_layers = 0; }; + channel_estimate(channel_estimate&& other) = default; + /// Default constructor: reserves internal memory. channel_estimate() : max_dims(), nof_subcarriers(0), nof_symbols(0), nof_rx_ports(0), nof_tx_layers(0) { diff --git a/include/srsran/phy/upper/channel_processors/pusch/factories.h b/include/srsran/phy/upper/channel_processors/pusch/factories.h index 524c06e302..01e9f0f134 100644 --- a/include/srsran/phy/upper/channel_processors/pusch/factories.h +++ b/include/srsran/phy/upper/channel_processors/pusch/factories.h @@ -88,6 +88,7 @@ struct pusch_processor_factory_sw_configuration { channel_estimate::channel_estimate_dimensions ch_estimate_dimensions; unsigned dec_nof_iterations = 10; bool dec_enable_early_stop = true; + unsigned max_nof_concurrent_threads; channel_state_information::sinr_type csi_sinr_calc_method = channel_state_information::sinr_type::channel_estimator; }; diff --git a/lib/phy/upper/channel_processors/pusch/factories.cpp b/lib/phy/upper/channel_processors/pusch/factories.cpp index 3169f5ded5..6eea72c42f 100644 --- a/lib/phy/upper/channel_processors/pusch/factories.cpp +++ b/lib/phy/upper/channel_processors/pusch/factories.cpp @@ -160,20 +160,33 @@ class pusch_processor_factory_generic : public pusch_processor_factory srsran_assert(demux_factory, "Invalid demux factory."); srsran_assert(decoder_factory, "Invalid decoder factory."); srsran_assert(uci_dec_factory, "Invalid UCI decoder factory."); + + // Create common dependencies. + std::vector> dependencies( + config.max_nof_concurrent_threads); + std::generate(dependencies.begin(), dependencies.end(), [this]() { + return std::make_unique(estimator_factory->create(), + demodulator_factory->create(), + demux_factory->create(), + uci_dec_factory->create(), + ch_estimate_dimensions); + }); + + // Create common dependencies pool. + dependencies_pool = + std::make_shared(std::move(dependencies)); } std::unique_ptr create() override { - pusch_processor_configuration config; - config.estimator = estimator_factory->create(); - config.demodulator = demodulator_factory->create(); - config.demultiplex = demux_factory->create(); - config.decoder = decoder_factory->create(); - config.uci_dec = uci_dec_factory->create(); - config.ce_dims = ch_estimate_dimensions; - config.dec_nof_iterations = dec_nof_iterations; - config.dec_enable_early_stop = dec_enable_early_stop; - config.csi_sinr_calc_method = csi_sinr_calc_method; + pusch_processor_impl::configuration config; + config.thread_local_dependencies_pool = dependencies_pool; + config.decoder = decoder_factory->create(); + config.uci_dec = uci_dec_factory->create(); + config.ce_dims = ch_estimate_dimensions; + config.dec_nof_iterations = dec_nof_iterations; + config.dec_enable_early_stop = dec_enable_early_stop; + config.csi_sinr_calc_method = csi_sinr_calc_method; return std::make_unique(config); } @@ -183,15 +196,16 @@ class pusch_processor_factory_generic : public pusch_processor_factory } private: - std::shared_ptr estimator_factory; - std::shared_ptr demodulator_factory; - std::shared_ptr demux_factory; - std::shared_ptr decoder_factory; - std::shared_ptr uci_dec_factory; - channel_estimate::channel_estimate_dimensions ch_estimate_dimensions; - unsigned dec_nof_iterations; - bool dec_enable_early_stop; - channel_state_information::sinr_type csi_sinr_calc_method; + std::shared_ptr dependencies_pool; + std::shared_ptr estimator_factory; + std::shared_ptr demodulator_factory; + std::shared_ptr demux_factory; + std::shared_ptr decoder_factory; + std::shared_ptr uci_dec_factory; + channel_estimate::channel_estimate_dimensions ch_estimate_dimensions; + unsigned dec_nof_iterations; + bool dec_enable_early_stop; + channel_state_information::sinr_type csi_sinr_calc_method; }; class pusch_processor_pool_factory : public pusch_processor_factory 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 5b204bda53..04665313be 100644 --- a/lib/phy/upper/channel_processors/pusch/pusch_decoder_impl.h +++ b/lib/phy/upper/channel_processors/pusch/pusch_decoder_impl.h @@ -15,7 +15,7 @@ #include "srsran/phy/upper/channel_processors/pusch/pusch_decoder.h" #include "srsran/phy/upper/channel_processors/pusch/pusch_decoder_buffer.h" #include "srsran/phy/upper/unique_rx_softbuffer.h" -#include "srsran/ran/pdsch/pdsch_constants.h" +#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" @@ -62,7 +62,7 @@ class pusch_decoder_impl : public pusch_decoder, private pusch_decoder_buffer decoder_pool(std::move(decoder_pool_)), crc_set(std::move(crc_set_)), executor(executor_), - softbits_buffer(pdsch_constants::CODEWORD_MAX_SIZE.value()), + softbits_buffer(pusch_constants::CODEWORD_MAX_SIZE.value()), cb_stats(MAX_NOF_SEGMENTS) { srsran_assert(segmenter, "Invalid segmenter."); diff --git a/lib/phy/upper/channel_processors/pusch/pusch_processor_impl.cpp b/lib/phy/upper/channel_processors/pusch/pusch_processor_impl.cpp index bda3294c63..9aec8e4ece 100644 --- a/lib/phy/upper/channel_processors/pusch/pusch_processor_impl.cpp +++ b/lib/phy/upper/channel_processors/pusch/pusch_processor_impl.cpp @@ -170,25 +170,15 @@ bool pusch_processor_validator_impl::is_valid(const pusch_processor::pdu_t& pdu) return true; } -pusch_processor_impl::pusch_processor_impl(pusch_processor_configuration& config) : - estimator(std::move(config.estimator)), - demodulator(std::move(config.demodulator)), - demultiplex(std::move(config.demultiplex)), +pusch_processor_impl::pusch_processor_impl(configuration& config) : + thread_local_dependencies_pool(std::move(config.thread_local_dependencies_pool)), decoder(std::move(config.decoder)), - uci_dec(std::move(config.uci_dec)), - harq_ack_decoder(*uci_dec, pusch_constants::CODEWORD_MAX_SIZE.value()), - csi_part1_decoder(*uci_dec, pusch_constants::CODEWORD_MAX_SIZE.value()), - csi_part2_decoder(*uci_dec, pusch_constants::CODEWORD_MAX_SIZE.value()), - ch_estimate(config.ce_dims), dec_nof_iterations(config.dec_nof_iterations), dec_enable_early_stop(config.dec_enable_early_stop), csi_sinr_calc_method(config.csi_sinr_calc_method) { - srsran_assert(estimator, "Invalid estimator."); - srsran_assert(demodulator, "Invalid demodulator."); - srsran_assert(demultiplex, "Invalid demultiplex."); + srsran_assert(thread_local_dependencies_pool, "Invalid dependency pool."); srsran_assert(decoder, "Invalid decoder."); - srsran_assert(uci_dec, "Invalid UCI decoder."); srsran_assert(dec_nof_iterations != 0, "The decoder number of iterations must be non-zero."); } @@ -200,7 +190,14 @@ void pusch_processor_impl::process(span data, { using namespace units::literals; - assert_pdu(pdu); + // Get thread local dependencies. + concurrent_dependencies& depedencies = thread_local_dependencies_pool->get(); + + // Get channel estimates. + channel_estimate& ch_estimate = depedencies.get_channel_estimate(); + + // Assert PDU. + assert_pdu(pdu, ch_estimate); // Number of RB used by this transmission. unsigned nof_rb = pdu.freq_alloc.get_nof_rb(); @@ -242,7 +239,7 @@ void pusch_processor_impl::process(span data, ch_est_config.nof_symbols = pdu.nof_symbols; ch_est_config.nof_tx_layers = pdu.nof_tx_layers; ch_est_config.rx_ports.assign(pdu.rx_ports.begin(), pdu.rx_ports.end()); - estimator->estimate(ch_estimate, grid, ch_est_config); + depedencies.get_estimator().estimate(ch_estimate, grid, ch_est_config); // Handles the direct current if it is present. if (pdu.dc_position.has_value()) { @@ -290,8 +287,11 @@ void pusch_processor_impl::process(span data, std::reference_wrapper csi_part1_buffer(decoder_buffer_dummy); // Prepare CSI Part 1 feedback. - pusch_processor_csi_part1_feedback_impl csi_part1_feedback( - csi_part2_decoder, *demultiplex, pdu.mcs_descr.modulation, pdu.uci.csi_part2_size, ulsch_config); + pusch_processor_csi_part1_feedback_impl csi_part1_feedback(depedencies.get_csi_part2_decoder(), + depedencies.get_demultiplex(), + pdu.mcs_descr.modulation, + pdu.uci.csi_part2_size, + ulsch_config); // Prepare notifiers. notifier_adaptor.new_transmission(notifier, csi_part1_feedback, csi); @@ -316,19 +316,19 @@ void pusch_processor_impl::process(span data, // Prepares HARQ-ACK notifier and buffer. if (pdu.uci.nof_harq_ack != 0) { - harq_ack_buffer = harq_ack_decoder.new_transmission( + harq_ack_buffer = depedencies.get_harq_ack_decoder().new_transmission( pdu.uci.nof_harq_ack, pdu.mcs_descr.modulation, notifier_adaptor.get_harq_ack_notifier()); } // Prepares CSI Part 1 notifier and buffer. if (pdu.uci.nof_csi_part1 != 0) { - csi_part1_buffer = csi_part1_decoder.new_transmission( + csi_part1_buffer = depedencies.get_csi_part1_decoder().new_transmission( pdu.uci.nof_csi_part1, pdu.mcs_descr.modulation, notifier_adaptor.get_csi_part1_notifier()); } // Demultiplex SCH data, HARQ-ACK and CSI Part 1. pusch_codeword_buffer& demodulator_buffer = - demultiplex->demultiplex(decoder_buffer, harq_ack_buffer, csi_part1_buffer, demux_config); + depedencies.get_demultiplex().demultiplex(decoder_buffer, harq_ack_buffer, csi_part1_buffer, demux_config); // Demodulate. pusch_demodulator::configuration demod_config; @@ -343,11 +343,11 @@ void pusch_processor_impl::process(span data, demod_config.n_id = pdu.n_id; demod_config.nof_tx_layers = pdu.nof_tx_layers; demod_config.rx_ports = pdu.rx_ports; - demodulator->demodulate( + depedencies.get_demodulator().demodulate( demodulator_buffer, notifier_adaptor.get_demodulator_notifier(), grid, ch_estimate, demod_config); } -void pusch_processor_impl::assert_pdu(const pusch_processor::pdu_t& pdu) const +void pusch_processor_impl::assert_pdu(const pusch_processor::pdu_t& pdu, const channel_estimate& ch_estimate) const { // Make sure the configuration is supported. srsran_assert((pdu.bwp_start_rb + pdu.bwp_size_rb) <= ch_estimate.capacity().nof_prb, diff --git a/lib/phy/upper/channel_processors/pusch/pusch_processor_impl.h b/lib/phy/upper/channel_processors/pusch/pusch_processor_impl.h index 56d12b8638..53ef036462 100644 --- a/lib/phy/upper/channel_processors/pusch/pusch_processor_impl.h +++ b/lib/phy/upper/channel_processors/pusch/pusch_processor_impl.h @@ -21,32 +21,11 @@ #include "srsran/phy/upper/signal_processors/dmrs_pusch_estimator.h" #include "srsran/phy/upper/unique_rx_softbuffer.h" #include "srsran/ran/pusch/ulsch_info.h" +#include "srsran/support/memory_pool/concurrent_thread_local_object_pool.h" #include namespace srsran { -/// Describes the necessary parameters for creating a PUSCH processor. -struct pusch_processor_configuration { - /// Channel estimator instance. Ownership is transferred to the processor. - std::unique_ptr estimator; - /// Demodulator instance. Ownership is transferred to the processor. - std::unique_ptr demodulator; - /// Channel demultiplex. Ownership is transferred to the processor. - std::unique_ptr demultiplex; - /// Decoder instance. Ownership is transferred to the processor. - std::unique_ptr decoder; - /// UCI Decoder instance. Ownership is transferred to the processor. - std::unique_ptr uci_dec; - /// Channel estimate dimensions. - channel_estimate::channel_estimate_dimensions ce_dims; - /// Selects the number of LDPC decoder iterations. - unsigned dec_nof_iterations; - /// Enables LDPC decoder early stop if the CRC matches before completing \c ldpc_nof_iterations iterations. - bool dec_enable_early_stop; - /// PUSCH SINR calculation method for CSI reporting. - channel_state_information::sinr_type csi_sinr_calc_method; -}; - /// Implements a parameter validator for \ref pusch_processor_impl. class pusch_processor_validator_impl : public pusch_pdu_validator { @@ -79,9 +58,82 @@ class pusch_processor_validator_impl : public pusch_pdu_validator class pusch_processor_impl : public pusch_processor { public: + /// Groups the PUSCH processor dependencies that can be reused locally by the same processing thread. + class concurrent_dependencies + { + public: + /// Creates the dependencies instance. + concurrent_dependencies(std::unique_ptr estimator_, + std::unique_ptr demodulator_, + std::unique_ptr demultiplex_, + std::unique_ptr uci_dec_, + channel_estimate::channel_estimate_dimensions ce_dims) : + estimator(std::move(estimator_)), + demodulator(std::move(demodulator_)), + demultiplex(std::move(demultiplex_)), + uci_dec(std::move(uci_dec_)), + ch_estimate(ce_dims), + harq_ack_decoder(*uci_dec, pusch_constants::CODEWORD_MAX_SIZE.value()), + csi_part1_decoder(*uci_dec, pusch_constants::CODEWORD_MAX_SIZE.value()), + csi_part2_decoder(*uci_dec, pusch_constants::CODEWORD_MAX_SIZE.value()) + { + srsran_assert(estimator, "Invalid channel estimator."); + srsran_assert(demodulator, "Invalid demodulator."); + srsran_assert(demultiplex, "Invalid demultiplex."); + srsran_assert(uci_dec, "Invalid UCI decoder."); + } + + dmrs_pusch_estimator& get_estimator() { return *estimator; } + pusch_demodulator& get_demodulator() { return *demodulator; } + ulsch_demultiplex& get_demultiplex() { return *demultiplex; } + pusch_uci_decoder_wrapper& get_harq_ack_decoder() { return harq_ack_decoder; } + pusch_uci_decoder_wrapper& get_csi_part1_decoder() { return csi_part1_decoder; } + pusch_uci_decoder_wrapper& get_csi_part2_decoder() { return csi_part2_decoder; } + channel_estimate& get_channel_estimate() { return ch_estimate; } + + private: + /// Channel estimator instance. Ownership is transferred to the processor. + std::unique_ptr estimator; + /// Demodulator instance. Ownership is transferred to the processor. + std::unique_ptr demodulator; + /// Channel demultiplex. Ownership is transferred to the processor. + std::unique_ptr demultiplex; + /// UCI Decoder instance. Ownership is transferred to the processor. + std::unique_ptr uci_dec; + /// Temporal channel estimate. + channel_estimate ch_estimate; + /// HARQ-ACK decoder wrapper. + pusch_uci_decoder_wrapper harq_ack_decoder; + /// CSI Part 1 decoder wrapper. + pusch_uci_decoder_wrapper csi_part1_decoder; + /// CSI Part 2 decoder wrapper. + pusch_uci_decoder_wrapper csi_part2_decoder; + }; + + /// Dependencies pool class. + using concurrent_dependencies_pool_type = concurrent_thread_local_object_pool; + + /// Collects the necessary parameters for creating a PUSCH processor. + struct configuration { + /// Thread local dependencies pool. + std::shared_ptr thread_local_dependencies_pool; + /// Decoder instance. Ownership is transferred to the processor. + std::unique_ptr decoder; + /// UCI decoder. Ownership is transferred to the processor. + std::unique_ptr uci_dec; + /// Channel estimate dimensions. + channel_estimate::channel_estimate_dimensions ce_dims; + /// Selects the number of LDPC decoder iterations. + unsigned dec_nof_iterations; + /// Enables LDPC decoder early stop if the CRC matches before completing \c ldpc_nof_iterations iterations. + bool dec_enable_early_stop; + /// PUSCH SINR calculation method for CSI reporting. + channel_state_information::sinr_type csi_sinr_calc_method; + }; + /// \brief Constructs a generic software PUSCH processor. /// \param[in] config PUSCH processor dependencies and configuration parameters. - pusch_processor_impl(pusch_processor_configuration& config); + pusch_processor_impl(configuration& config); // See interface for documentation. void process(span data, @@ -91,54 +143,13 @@ class pusch_processor_impl : public pusch_processor const pdu_t& pdu) override; private: - /// Maximum UCI scaling \f$\alpha\f$ as per TS38.331 UCI-OnPUSCH. - static constexpr unsigned UCI_ON_PUSCH_MAX_ALPHA = 1; - - /// \brief Maximum number of LLRs for HARQ-ACK in a single transmission. - /// - /// As per TS38.212 Section 6.3.2.4.1.1, \f$Q_{ACK}'\f$ formula. The value of \f$\sum - /// ^{N_{symb,all}^{PUSCH}-1}_{l=l_0}M_{sc}^{UCI}(l)\f$ is bounded above by the maximum number of resource elements in - /// a PUSCH transmission. - static constexpr unsigned MAX_NOF_HARQ_ACK_LLR = - MAX_RB * pusch_constants::MAX_NRE_PER_RB * UCI_ON_PUSCH_MAX_ALPHA * pusch_constants::MAX_MODULATION_ORDER; - - /// \brief Maximum number of LLRs for CSI Part 1 in a single transmission. - /// - /// As per TS38.212 Section 6.3.2.4.1.1 in \f$Q_{CSI-1}'\f$ formula. The value of \f$\sum - /// ^{N_{symb,all}^{PUSCH}-1}_{l=l_0}M_{sc}^{UCI}(l)\f$ is bounded above by the maximum number of resource elements in - /// a PUSCH transmission. - static constexpr unsigned MAX_NOF_CSI_PART1_LLR = - MAX_RB * pusch_constants::MAX_NRE_PER_RB * UCI_ON_PUSCH_MAX_ALPHA * pusch_constants::MAX_MODULATION_ORDER; - - /// \brief Maximum number of LLRs for CSI Part 2 in a single transmission. - /// - /// As per TS38.212 Section 6.3.2.4.1.1 in \f$Q_{CSI-2}'\f$ formula. Ceiling the value of \f$\sum - /// ^{N_{symb,all}^{PUSCH}-1}_{l=l_0}M_{sc}^{UCI}(l)\f$ to the maximum number of resource elements in a PUSCH - /// transmission. - static constexpr unsigned MAX_NOF_CSI_PART2_LLR = - MAX_RB * pusch_constants::MAX_NRE_PER_RB * UCI_ON_PUSCH_MAX_ALPHA * pusch_constants::MAX_MODULATION_ORDER; - /// Asserts the PDU. It triggers an assertion upon an invalid value or combination of values. - void assert_pdu(const pusch_processor::pdu_t& pdu) const; - - /// Channel estimator. - std::unique_ptr estimator; - /// PUSCH demodulator. - std::unique_ptr demodulator; - /// UL-SCH demultiplexer. - std::unique_ptr demultiplex; + void assert_pdu(const pusch_processor::pdu_t& pdu, const channel_estimate& ch_estimate) const; + + /// Thread local dependencies pool. + std::shared_ptr thread_local_dependencies_pool; /// UL-SCH transport block decoder. std::unique_ptr decoder; - /// UCI decoder. - std::unique_ptr uci_dec; - /// HARQ-ACK decoder wrapper. - pusch_uci_decoder_wrapper harq_ack_decoder; - /// CSI Part 1 decoder wrapper. - pusch_uci_decoder_wrapper csi_part1_decoder; - /// CSI Part 2 decoder wrapper. - pusch_uci_decoder_wrapper csi_part2_decoder; - /// Temporal channel estimate. - channel_estimate ch_estimate; /// Selects the number of LDPC decoder iterations. unsigned dec_nof_iterations; /// Enables LDPC decoder early stop if the CRC matches before completing \c ldpc_nof_iterations iterations. diff --git a/lib/phy/upper/upper_phy_factories.cpp b/lib/phy/upper/upper_phy_factories.cpp index 7b056b9120..509aa04b2a 100644 --- a/lib/phy/upper/upper_phy_factories.cpp +++ b/lib/phy/upper/upper_phy_factories.cpp @@ -382,12 +382,13 @@ static std::shared_ptr create_ul_processor_factory(con pusch_config.estimator_factory = create_dmrs_pusch_estimator_factory_sw(prg_factory, ch_estimator_factory); pusch_config.demodulator_factory = create_pusch_demodulator_factory_sw( equalizer_factory, demodulation_factory, prg_factory, enable_evm, enable_eq_sinr); - pusch_config.demux_factory = create_ulsch_demultiplex_factory_sw(); - pusch_config.decoder_factory = create_pusch_decoder_factory_sw(decoder_config); - pusch_config.uci_dec_factory = uci_dec_factory; - pusch_config.dec_nof_iterations = config.ldpc_decoder_iterations; - pusch_config.dec_enable_early_stop = config.ldpc_decoder_early_stop; - pusch_config.csi_sinr_calc_method = config.pusch_sinr_calc_method; + pusch_config.demux_factory = create_ulsch_demultiplex_factory_sw(); + pusch_config.decoder_factory = create_pusch_decoder_factory_sw(decoder_config); + pusch_config.uci_dec_factory = uci_dec_factory; + pusch_config.dec_nof_iterations = config.ldpc_decoder_iterations; + pusch_config.dec_enable_early_stop = config.ldpc_decoder_early_stop; + pusch_config.csi_sinr_calc_method = config.pusch_sinr_calc_method; + pusch_config.max_nof_concurrent_threads = config.max_ul_thread_concurrency; // :TODO: check these values in the future. Extract them to more public config. pusch_config.ch_estimate_dimensions.nof_symbols = 14; 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 810ded300b..4f068033ad 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 @@ -472,6 +472,7 @@ static pusch_processor_factory& get_pusch_processor_factory() pusch_proc_factory_config.ch_estimate_dimensions.nof_tx_layers = nof_tx_layers; pusch_proc_factory_config.dec_nof_iterations = 2; pusch_proc_factory_config.dec_enable_early_stop = true; + pusch_proc_factory_config.max_nof_concurrent_threads = nof_threads; pusch_proc_factory = create_pusch_processor_factory_sw(pusch_proc_factory_config); TESTASSERT(pusch_proc_factory); diff --git a/tests/unittests/phy/upper/channel_processors/pusch/pusch_decoder_buffer_test_doubles.h b/tests/unittests/phy/upper/channel_processors/pusch/pusch_decoder_buffer_test_doubles.h index da28c5da10..6b11cdcb0d 100644 --- a/tests/unittests/phy/upper/channel_processors/pusch/pusch_decoder_buffer_test_doubles.h +++ b/tests/unittests/phy/upper/channel_processors/pusch/pusch_decoder_buffer_test_doubles.h @@ -21,16 +21,10 @@ class pusch_decoder_buffer_spy : public pusch_decoder_buffer pusch_decoder_buffer_spy(unsigned buffer_size) { data.resize(buffer_size); } - void resize(unsigned buffer_size) { data.resize(buffer_size); } - // See interface for documentation. span get_next_block_view(unsigned block_size) override { - srsran_assert(data.size() >= block_size + count, - "Block size (i.e., {}) plus the current number of bits (i.e., {}) exceeds the data size (i.e., {}).", - block_size, - count, - data.size()); + data.resize(block_size + count); return span(data).subspan(count, block_size); } diff --git a/tests/unittests/phy/upper/channel_processors/pusch/pusch_decoder_test_doubles.h b/tests/unittests/phy/upper/channel_processors/pusch/pusch_decoder_test_doubles.h index 64c7bfbcda..e48f255427 100644 --- a/tests/unittests/phy/upper/channel_processors/pusch/pusch_decoder_test_doubles.h +++ b/tests/unittests/phy/upper/channel_processors/pusch/pusch_decoder_test_doubles.h @@ -33,8 +33,6 @@ class pusch_decoder_spy : public pusch_decoder ~pusch_decoder_spy() { srsran_assert(entries.empty(), "Entries must be cleared."); } - void set_codeword_length(unsigned codeword_length_) { codeword_length = codeword_length_; } - pusch_decoder_buffer& new_data(span transport_block, unique_rx_softbuffer softbuffer, pusch_decoder_notifier& notifier, @@ -45,9 +43,8 @@ class pusch_decoder_spy : public pusch_decoder entry.transport_block = transport_block; entry.stats = {}; entry.softbuffer = std::move(softbuffer); - entry.input.resize(codeword_length); - entry.notifier = ¬ifier; - entry.config = cfg; + entry.notifier = ¬ifier; + entry.config = cfg; entry.stats.tb_crc_ok = true; entry.stats.nof_codeblocks_total = 123; @@ -62,7 +59,6 @@ class pusch_decoder_spy : public pusch_decoder void clear() { entries.clear(); } private: - unsigned codeword_length; std::vector entries; }; diff --git a/tests/unittests/phy/upper/channel_processors/pusch/pusch_processor_unittest.cpp b/tests/unittests/phy/upper/channel_processors/pusch/pusch_processor_unittest.cpp index f9565659f3..b0f0a81192 100644 --- a/tests/unittests/phy/upper/channel_processors/pusch/pusch_processor_unittest.cpp +++ b/tests/unittests/phy/upper/channel_processors/pusch/pusch_processor_unittest.cpp @@ -109,6 +109,7 @@ class PuschProcessorFixture : public ::testing::TestWithParam pusch_proc_factory = create_pusch_processor_factory_sw(proc_factory_config); @@ -344,7 +345,6 @@ TEST_P(PuschProcessorFixture, PuschProcessorUnittest) // Calculate the number of LLR. unsigned nof_codeword_llr = nof_re * get_bits_per_symbol(pdu.mcs_descr.modulation) * pdu.nof_tx_layers; demodulator_spy->set_codeword_size(nof_codeword_llr); - decoder_spy->set_codeword_length(ulsch_info.nof_ul_sch_bits.value()); demux_spy->set_ulsch_config(nof_codeword_llr, ulsch_info.nof_ul_sch_bits.value(), ulsch_info.nof_harq_ack_bits.value(), 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 9e53a4353d..54245300fd 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 @@ -242,6 +242,7 @@ class PuschProcessorFixture : public ::testing::TestWithParam pusch_proc_factory_config.ch_estimate_dimensions.nof_symbols = MAX_NSYMB_PER_SLOT; pusch_proc_factory_config.ch_estimate_dimensions.nof_rx_ports = 1; pusch_proc_factory_config.ch_estimate_dimensions.nof_tx_layers = 1; + pusch_proc_factory_config.max_nof_concurrent_threads = 1; std::shared_ptr pusch_proc_factory = create_pusch_processor_factory_sw(pusch_proc_factory_config); ASSERT_NE(pusch_proc_factory, nullptr); 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 e2c4fb7c00..7a4f2b228c 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 @@ -139,7 +139,8 @@ class PuschProcessorFixture : public ::testing::TestWithParam pusch_proc_factory = create_pusch_processor_factory_sw(pusch_proc_factory_config); ASSERT_NE(pusch_proc_factory, nullptr); From 3de9f5c01ea364c510530b4e6f9bb29bc54f67b8 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 9 Jan 2024 10:08:19 +0100 Subject: [PATCH 083/134] phy: review PUSCH processor related --- include/srsran/phy/upper/channel_estimation.h | 2 -- lib/phy/upper/channel_processors/pusch/factories.cpp | 2 -- .../channel_processors/pusch/pusch_processor_impl.h | 12 ++++-------- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/include/srsran/phy/upper/channel_estimation.h b/include/srsran/phy/upper/channel_estimation.h index a7c8d4cfe9..fbc9954599 100644 --- a/include/srsran/phy/upper/channel_estimation.h +++ b/include/srsran/phy/upper/channel_estimation.h @@ -55,8 +55,6 @@ class channel_estimate unsigned nof_tx_layers = 0; }; - channel_estimate(channel_estimate&& other) = default; - /// Default constructor: reserves internal memory. channel_estimate() : max_dims(), nof_subcarriers(0), nof_symbols(0), nof_rx_ports(0), nof_tx_layers(0) { diff --git a/lib/phy/upper/channel_processors/pusch/factories.cpp b/lib/phy/upper/channel_processors/pusch/factories.cpp index 6eea72c42f..a74bbd9fb2 100644 --- a/lib/phy/upper/channel_processors/pusch/factories.cpp +++ b/lib/phy/upper/channel_processors/pusch/factories.cpp @@ -182,8 +182,6 @@ class pusch_processor_factory_generic : public pusch_processor_factory pusch_processor_impl::configuration config; config.thread_local_dependencies_pool = dependencies_pool; config.decoder = decoder_factory->create(); - config.uci_dec = uci_dec_factory->create(); - config.ce_dims = ch_estimate_dimensions; config.dec_nof_iterations = dec_nof_iterations; config.dec_enable_early_stop = dec_enable_early_stop; config.csi_sinr_calc_method = csi_sinr_calc_method; diff --git a/lib/phy/upper/channel_processors/pusch/pusch_processor_impl.h b/lib/phy/upper/channel_processors/pusch/pusch_processor_impl.h index 53ef036462..80328ddeec 100644 --- a/lib/phy/upper/channel_processors/pusch/pusch_processor_impl.h +++ b/lib/phy/upper/channel_processors/pusch/pusch_processor_impl.h @@ -92,13 +92,13 @@ class pusch_processor_impl : public pusch_processor channel_estimate& get_channel_estimate() { return ch_estimate; } private: - /// Channel estimator instance. Ownership is transferred to the processor. + /// Channel estimator instance. std::unique_ptr estimator; - /// Demodulator instance. Ownership is transferred to the processor. + /// Demodulator instance. std::unique_ptr demodulator; - /// Channel demultiplex. Ownership is transferred to the processor. + /// Channel demultiplex. std::unique_ptr demultiplex; - /// UCI Decoder instance. Ownership is transferred to the processor. + /// UCI Decoder instance. std::unique_ptr uci_dec; /// Temporal channel estimate. channel_estimate ch_estimate; @@ -119,10 +119,6 @@ class pusch_processor_impl : public pusch_processor std::shared_ptr thread_local_dependencies_pool; /// Decoder instance. Ownership is transferred to the processor. std::unique_ptr decoder; - /// UCI decoder. Ownership is transferred to the processor. - std::unique_ptr uci_dec; - /// Channel estimate dimensions. - channel_estimate::channel_estimate_dimensions ce_dims; /// Selects the number of LDPC decoder iterations. unsigned dec_nof_iterations; /// Enables LDPC decoder early stop if the CRC matches before completing \c ldpc_nof_iterations iterations. From a247b204469b71017eddea1677206226d633e805 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 9 Jan 2024 11:54:17 +0100 Subject: [PATCH 084/134] support: make lockfree_stack::pop always use memory_order_acquire in the check of the top of the stack --- include/srsran/support/memory_pool/lockfree_object_pool.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/srsran/support/memory_pool/lockfree_object_pool.h b/include/srsran/support/memory_pool/lockfree_object_pool.h index 5587d76e2a..c64b2fd768 100644 --- a/include/srsran/support/memory_pool/lockfree_object_pool.h +++ b/include/srsran/support/memory_pool/lockfree_object_pool.h @@ -44,7 +44,9 @@ class lockfree_index_stack index_type try_pop() { - node old_top{top.load(std::memory_order_relaxed)}; + // We use memory ordering "acquire" to form a "synchronizes-with" relationship with the release of the last push(), + // otherwise the write to next_idx[] during the push() is not visible in this thread. + node old_top{top.load(std::memory_order_acquire)}; if (old_top.index == npos()) { return npos(); } From d599f59da933016933b7e6542ffc40acb30b68bb Mon Sep 17 00:00:00 2001 From: tonigelabertfons Date: Sat, 6 Jan 2024 10:02:43 +0100 Subject: [PATCH 085/134] phy: create step64() --- .../pseudo_random_generator_impl.cpp | 131 +++++++++--------- .../pseudo_random_generator_sequence.h | 9 ++ 2 files changed, 71 insertions(+), 69 deletions(-) diff --git a/lib/phy/upper/sequence_generators/pseudo_random_generator_impl.cpp b/lib/phy/upper/sequence_generators/pseudo_random_generator_impl.cpp index 6d52cb547b..5d9eed0186 100644 --- a/lib/phy/upper/sequence_generators/pseudo_random_generator_impl.cpp +++ b/lib/phy/upper/sequence_generators/pseudo_random_generator_impl.cpp @@ -75,8 +75,7 @@ void pseudo_random_generator_impl::generate(bit_buffer& data) static constexpr unsigned nof_bits_per_byte = 8; // Calculate the maximum number of simultaneous words to process. - static constexpr unsigned max_nof_bytes_step = - pseudo_random_generator_sequence::get_max_step_size() / nof_bits_per_byte; + static constexpr unsigned max_nof_bytes_step = 64 / nof_bits_per_byte; // Calculate the maximum number of simultaneous bits to process. static constexpr unsigned max_nof_bits_step = max_nof_bytes_step * nof_bits_per_byte; @@ -84,49 +83,48 @@ void pseudo_random_generator_impl::generate(bit_buffer& data) // Create sequence with the current x1 and x2 states. pseudo_random_generator_sequence sequence(x1, x2); - // Processes batches of 24 bits in parallel. - for (unsigned i_byte = 0, i_byte_end = (data.size() / max_nof_bits_step) * max_nof_bytes_step; - i_byte != i_byte_end;) { - uint32_t c = sequence.step(max_nof_bits_step); - - // Processes each byte of the batch. - for (unsigned i_byte_batch = 0; i_byte_batch != max_nof_bytes_step; ++i_byte, ++i_byte_batch) { - // Calculate the output byte. - uint8_t output_byte = (static_cast((c >> (max_nof_bits_step - (i_byte_batch * nof_bits_per_byte))) & - mask_lsb_ones(nof_bits_per_byte))); - - // Insert the output byte. - data.set_byte(output_byte, i_byte); - } + // Processes batches of 64 bits in parallel. + for (unsigned i_byte = 0, i_byte_end = (data.size() / max_nof_bits_step) * max_nof_bytes_step; i_byte != i_byte_end; + i_byte += 8) { + uint64_t c = sequence.step64(); + c = __builtin_bswap64(c); + span output_chunk = data.get_buffer().subspan(i_byte, max_nof_bytes_step); + memcpy(output_chunk.data(), &c, max_nof_bytes_step); } // Process spare bits in a batch of the remainder bits. unsigned i_bit = (data.size() / max_nof_bits_step) * max_nof_bits_step; unsigned remainder = data.size() - i_bit; - uint32_t c = sequence.step(remainder); unsigned count = 0; while (remainder != 0) { - // Process per byte basis, ceiling at the remainder. - unsigned word_size = std::min(remainder, nof_bits_per_byte); + unsigned batch_size = std::min(remainder, pseudo_random_generator_sequence::get_max_step_size()); + unsigned reminder_size = batch_size; + uint32_t c = sequence.step(batch_size); - // Mask the LSB of the sequence. - uint32_t mask = mask_lsb_ones(nof_bits_per_byte); + while (batch_size != 0) { + // Process per byte basis, ceiling at the remainder. + unsigned word_size = std::min(batch_size, nof_bits_per_byte); - // Shift to align the reversed sequence LSB with the remainder bits. - unsigned right_shift = nof_bits_per_byte - word_size; + // Mask the LSB of the sequence. + uint32_t mask = mask_lsb_ones(nof_bits_per_byte); - // Calculate the output byte. - uint8_t output_word = ((c >> (max_nof_bits_step - (count * nof_bits_per_byte))) & mask) >> right_shift; + // Shift to align the reversed sequence LSB with the remainder bits. + unsigned right_shift = nof_bits_per_byte - word_size; - // Insert the output byte. - data.insert(output_word, i_bit, word_size); + // Calculate the output byte. + uint8_t output_word = ((c >> (24u - (count * nof_bits_per_byte))) & mask) >> right_shift; + + // Insert the output byte. + data.insert(output_word, i_bit, word_size); - // Advance bit index. - i_bit += word_size; + // Advance bit index. + i_bit += word_size; - // Decrement remainder. - remainder -= word_size; - ++count; + // Decrement remainder. + batch_size -= word_size; + ++count; + } + remainder -= reminder_size; } x1 = sequence.get_x1(); @@ -246,8 +244,7 @@ void pseudo_random_generator_impl::apply_xor(bit_buffer& out, const bit_buffer& static constexpr unsigned nof_bits_per_byte = 8; // Calculate the maximum number of simultaneous words to process. - static constexpr unsigned max_nof_bytes_step = - pseudo_random_generator_sequence::get_max_step_size() / nof_bits_per_byte; + static constexpr unsigned max_nof_bytes_step = 64 / nof_bits_per_byte; // Calculate the maximum number of simultaneous bits to process. static constexpr unsigned max_nof_bits_step = max_nof_bytes_step * nof_bits_per_byte; @@ -256,55 +253,51 @@ void pseudo_random_generator_impl::apply_xor(bit_buffer& out, const bit_buffer& pseudo_random_generator_sequence sequence(x1, x2); // Processes batches of words. - for (unsigned i_byte = 0, i_byte_end = (in.size() / max_nof_bits_step) * max_nof_bytes_step; i_byte != i_byte_end;) { - uint32_t c = sequence.step(); - - // Processes each byte of the batch. - for (unsigned i_byte_batch = 0; i_byte_batch != max_nof_bytes_step; ++i_byte, ++i_byte_batch) { - // Extract input byte. - uint8_t input_byte = in.get_byte(i_byte); - - // Calculate the output byte. - uint8_t output_byte = - input_byte ^ (static_cast((c >> (max_nof_bits_step - (i_byte_batch * nof_bits_per_byte))) & 0xff)); - - // Insert the output byte. - out.set_byte(output_byte, i_byte); - } + for (unsigned i_byte = 0, i_byte_end = (in.size() / max_nof_bits_step) * max_nof_bytes_step; i_byte != i_byte_end; + i_byte += 8) { + uint64_t c = sequence.step64(); + c = __builtin_bswap64(c); + uint64_t temp; + memcpy(&temp, &in.get_buffer()[i_byte], 8); + temp ^= c; + memcpy(&out.get_buffer()[i_byte], &temp, 8); } // Process spare bits in a batch of the remainder bits. unsigned i_bit = (in.size() / max_nof_bits_step) * max_nof_bits_step; unsigned remainder = in.size() - i_bit; unsigned count = 0; - uint32_t c = sequence.step(remainder); - - // Process bits. while (remainder != 0) { - // Process per byte basis, ceiling at the remainder. - unsigned word_size = std::min(remainder, nof_bits_per_byte); + unsigned batch_size = std::min(remainder, pseudo_random_generator_sequence::get_max_step_size()); + unsigned reminder_size = batch_size; + uint32_t c = sequence.step(batch_size); + + // Process bits. + while (batch_size != 0) { + // Process per byte basis, ceiling at the remainder. + unsigned word_size = std::min(batch_size, nof_bits_per_byte); - uint8_t input_word = in.extract(i_bit, word_size); + uint8_t input_word = in.extract(i_bit, word_size); - // Shift to align the reversed sequence LSB with the remainder bits. - unsigned right_shift = nof_bits_per_byte - word_size; + // Shift to align the reversed sequence LSB with the remainder bits. + unsigned right_shift = nof_bits_per_byte - word_size; - // Calculate the output byte. - uint8_t output_word = - input_word ^ - ((static_cast((c >> (max_nof_bits_step - (count * nof_bits_per_byte))) & 0xff)) >> right_shift); + // Calculate the output byte. + uint8_t output_word = + input_word ^ ((static_cast((c >> (24u - (count * nof_bits_per_byte))) & 0xff)) >> right_shift); - // Insert the output byte. - out.insert(output_word, i_bit, word_size); + // Insert the output byte. + out.insert(output_word, i_bit, word_size); - // Advance bit index. - i_bit += word_size; + // Advance bit index. + i_bit += word_size; - // Decrement remainder. - remainder -= word_size; - ++count; + // Decrement remainder. + batch_size -= word_size; + ++count; + } + remainder -= reminder_size; } - // Update x1 and x2 states. x1 = sequence.get_x1(); x2 = sequence.get_x2(); diff --git a/lib/phy/upper/sequence_generators/pseudo_random_generator_sequence.h b/lib/phy/upper/sequence_generators/pseudo_random_generator_sequence.h index 0c13fe3539..524e371ceb 100644 --- a/lib/phy/upper/sequence_generators/pseudo_random_generator_sequence.h +++ b/lib/phy/upper/sequence_generators/pseudo_random_generator_sequence.h @@ -107,6 +107,15 @@ class pseudo_random_generator_sequence return c; } + /// Returns and steps the sequence 64 bits. + uint64_t step64() + { + uint64_t result = static_cast(step()) << 32; + result |= static_cast(step()) << 4; + result |= static_cast(step<8>()) >> 24; + return result; + } + /// Gets the current \f$x_1(n)\f$ state. state_type get_x1() const { return x1; } From 4ae2acb66179aeb2ee4bbe98cdd27f346d995004 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 8 Jan 2024 09:36:35 +0100 Subject: [PATCH 086/134] ofh: fix typo in comment --- lib/ofh/transmitter/helpers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ofh/transmitter/helpers.h b/lib/ofh/transmitter/helpers.h index d41b51df81..3702df1b7c 100644 --- a/lib/ofh/transmitter/helpers.h +++ b/lib/ofh/transmitter/helpers.h @@ -28,7 +28,7 @@ get_biggest_min_tx_parameter_in_symbols(const du_tx_window_timing_parameters& return std::floor(max_value / symbol_duration_ns); } -/// Returns duration of the OFH downkink processing plus the transmission window in symbol units. +/// Returns duration of the OFH downlink processing plus the transmission window in symbol units. inline unsigned calculate_nof_symbols_before_ota(cyclic_prefix cp, subcarrier_spacing scs, std::chrono::microseconds dl_processing_time, From 540e2577c9dd7940ca532e09df3431e7caff3b1f Mon Sep 17 00:00:00 2001 From: Alejandro Leal Date: Tue, 9 Jan 2024 17:51:44 +0100 Subject: [PATCH 087/134] ofh: changed transmission window checker log entry to debug --- lib/ofh/transmitter/ofh_tx_window_checker.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/ofh/transmitter/ofh_tx_window_checker.h b/lib/ofh/transmitter/ofh_tx_window_checker.h index e5b1c2e053..be2c85083d 100644 --- a/lib/ofh/transmitter/ofh_tx_window_checker.h +++ b/lib/ofh/transmitter/ofh_tx_window_checker.h @@ -52,13 +52,13 @@ class tx_window_checker : public ota_symbol_boundary_notifier return false; } - logger.warning("A late upper-PHY downlink request arrived to OFH in slot '{}_{}' with current ota_slot='{}_{}', " - "OFH processing time requires a minimum of '{}' symbols", - slot, - 0, - ota_symbol_point.get_slot(), - ota_symbol_point.get_symbol_index(), - advance_time_in_symbols); + logger.debug("A late upper-PHY downlink request arrived to OFH in slot '{}_{}' with current ota_slot='{}_{}', " + "OFH processing time requires a minimum of '{}' symbols", + slot, + 0, + ota_symbol_point.get_slot(), + ota_symbol_point.get_symbol_index(), + advance_time_in_symbols); return true; } From d756a4f91c10c300fcb494a6be438893372f3168 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 9 Jan 2024 19:45:12 +0100 Subject: [PATCH 088/134] phy: refactor RM buffers phy: remove unused executor --- apps/examples/du/du_example.cpp | 1 - apps/examples/du/fapi_factory.cpp | 2 - apps/examples/du/fapi_factory.h | 1 - apps/examples/du/phy_factory.cpp | 2 +- apps/gnb/gnb_appconfig_translators.cpp | 2 +- .../phy/phy_fapi_adaptor_factory.h | 2 - .../upper/channel_processors/pdsch_encoder.h | 4 +- .../channel_processors/pdsch_processor.h | 4 +- .../channel_processors/pusch/pusch_decoder.h | 8 +- .../pusch/pusch_processor.h | 16 +- include/srsran/phy/upper/downlink_processor.h | 8 +- .../upper/{rx_softbuffer.h => rx_buffer.h} | 6 +- include/srsran/phy/upper/rx_buffer_pool.h | 86 ++++ include/srsran/phy/upper/rx_softbuffer_pool.h | 102 ---- .../srsran/phy/upper/trx_buffer_identifier.h | 90 ++++ include/srsran/phy/upper/tx_buffer.h | 2 +- include/srsran/phy/upper/tx_buffer_pool.h | 29 +- include/srsran/phy/upper/unique_rx_buffer.h | 129 +++++ .../srsran/phy/upper/unique_rx_softbuffer.h | 124 ----- include/srsran/phy/upper/unique_tx_buffer.h | 6 +- include/srsran/phy/upper/uplink_processor.h | 6 +- .../srsran/phy/upper/upper_phy_factories.h | 4 +- lib/du/adapters/fapi_factory.cpp | 2 - lib/du/adapters/fapi_factory.h | 1 - lib/du/du_impl.cpp | 1 - .../phy/fapi_to_phy_translator.cpp | 23 +- lib/fapi_adaptor/phy/fapi_to_phy_translator.h | 6 +- .../phy/phy_fapi_adaptor_factory_impl.cpp | 1 - .../phy/phy_fapi_adaptor_impl.cpp | 1 - lib/fapi_adaptor/phy/phy_fapi_adaptor_impl.h | 2 - lib/phy/upper/CMakeLists.txt | 2 +- .../channel_processor_factories.cpp | 4 +- .../channel_processors/pdsch_encoder_impl.cpp | 15 +- .../channel_processors/pdsch_encoder_impl.h | 2 +- .../pdsch_processor_concurrent_impl.cpp | 26 +- .../pdsch_processor_concurrent_impl.h | 6 +- .../pdsch_processor_impl.cpp | 8 +- .../channel_processors/pdsch_processor_impl.h | 15 +- .../pdsch_processor_lite_impl.cpp | 17 +- .../pdsch_processor_lite_impl.h | 8 +- .../channel_processors/pdsch_processor_pool.h | 8 +- .../pusch/logging_pusch_processor_decorator.h | 6 +- .../pusch/pusch_decoder_hw_impl.cpp | 4 +- .../pusch/pusch_decoder_hw_impl.h | 6 +- .../pusch/pusch_decoder_impl.cpp | 40 +- .../pusch/pusch_decoder_impl.h | 6 +- .../pusch/pusch_processor_impl.cpp | 6 +- .../pusch/pusch_processor_impl.h | 4 +- .../pusch/pusch_processor_logging_decorator.h | 187 ------- .../pusch/pusch_processor_pool.h | 8 +- ...ownlink_processor_single_executor_impl.cpp | 4 +- .../downlink_processor_single_executor_impl.h | 2 +- ...lock_pool.h => rx_buffer_codeblock_pool.h} | 65 ++- lib/phy/upper/rx_buffer_impl.h | 247 ++++++++++ lib/phy/upper/rx_buffer_pool_impl.cpp | 114 +++++ lib/phy/upper/rx_buffer_pool_impl.h | 68 +++ lib/phy/upper/rx_softbuffer_impl.h | 283 ----------- lib/phy/upper/rx_softbuffer_pool_impl.cpp | 112 ----- lib/phy/upper/rx_softbuffer_pool_impl.h | 64 --- lib/phy/upper/tx_buffer_codeblock_pool.h | 14 +- lib/phy/upper/tx_buffer_impl.h | 195 ++++---- lib/phy/upper/tx_buffer_pool_impl.cpp | 180 ++++--- lib/phy/upper/tx_buffer_pool_impl.h | 71 ++- lib/phy/upper/uplink_processor_impl.cpp | 6 +- lib/phy/upper/uplink_processor_impl.h | 2 +- .../upper/uplink_processor_task_dispatcher.h | 6 +- lib/phy/upper/upper_phy_factories.cpp | 6 +- lib/phy/upper/upper_phy_impl.cpp | 2 +- lib/phy/upper/upper_phy_impl.h | 39 +- .../upper_phy_rx_results_notifier_wrapper.h | 2 +- .../upper_phy_rx_symbol_handler_impl.cpp | 38 +- .../upper/upper_phy_rx_symbol_handler_impl.h | 8 +- .../ue_scheduling/ue_scheduler_impl.cpp | 2 +- .../pdsch_processor_benchmark.cpp | 26 +- .../pusch/pusch_decoder_hwacc_benchmark.cpp | 24 +- .../pusch/pusch_processor_benchmark.cpp | 33 +- .../phy/fapi_to_phy_translator_test.cpp | 26 +- tests/unittests/phy/upper/CMakeLists.txt | 6 +- .../channel_processors/pdsch_encoder_test.cpp | 28 +- .../pdsch_encoder_test_doubles.h | 2 +- .../pdsch_processor_test_doubles.h | 2 +- .../pdsch_processor_unittest.cpp | 8 +- .../pdsch_processor_validator_test.cpp | 12 +- .../pdsch_processor_vectortest.cpp | 30 +- .../pusch/pusch_decoder_test_doubles.h | 8 +- .../pusch/pusch_decoder_vectortest.cpp | 23 +- .../pusch/pusch_processor_test_doubles.h | 2 +- .../pusch/pusch_processor_unittest.cpp | 32 +- .../pusch/pusch_processor_validator_test.cpp | 10 +- .../pusch/pusch_processor_vectortest.cpp | 22 +- .../phy/upper/downlink_processor_test.cpp | 36 +- .../upper/downlink_processor_test_doubles.h | 2 +- .../phy/upper/rx_buffer_pool_test.cpp | 461 ++++++++++++++++++ ...est_doubles.h => rx_buffer_test_doubles.h} | 10 +- .../phy/upper/rx_softbuffer_pool_test.cpp | 306 ------------ .../phy/upper/tx_buffer_pool_test_doubles.h | 58 +++ ...est_doubles.h => tx_buffer_test_doubles.h} | 2 +- .../upper/tx_softbuffer_pool_test_doubles.h | 62 --- .../phy/upper/uplink_processor_test.cpp | 2 +- .../phy/upper/uplink_processor_test_doubles.h | 2 +- .../upper_phy_rx_symbol_handler_test.cpp | 6 +- 101 files changed, 1870 insertions(+), 1950 deletions(-) rename include/srsran/phy/upper/{rx_softbuffer.h => rx_buffer.h} (96%) create mode 100644 include/srsran/phy/upper/rx_buffer_pool.h delete mode 100644 include/srsran/phy/upper/rx_softbuffer_pool.h create mode 100644 include/srsran/phy/upper/trx_buffer_identifier.h create mode 100644 include/srsran/phy/upper/unique_rx_buffer.h delete mode 100644 include/srsran/phy/upper/unique_rx_softbuffer.h delete mode 100644 lib/phy/upper/channel_processors/pusch/pusch_processor_logging_decorator.h rename lib/phy/upper/{rx_softbuffer_codeblock_pool.h => rx_buffer_codeblock_pool.h} (59%) create mode 100644 lib/phy/upper/rx_buffer_impl.h create mode 100644 lib/phy/upper/rx_buffer_pool_impl.cpp create mode 100644 lib/phy/upper/rx_buffer_pool_impl.h delete mode 100644 lib/phy/upper/rx_softbuffer_impl.h delete mode 100644 lib/phy/upper/rx_softbuffer_pool_impl.cpp delete mode 100644 lib/phy/upper/rx_softbuffer_pool_impl.h create mode 100644 tests/unittests/phy/upper/rx_buffer_pool_test.cpp rename tests/unittests/phy/upper/{rx_softbuffer_test_doubles.h => rx_buffer_test_doubles.h} (88%) delete mode 100644 tests/unittests/phy/upper/rx_softbuffer_pool_test.cpp create mode 100644 tests/unittests/phy/upper/tx_buffer_pool_test_doubles.h rename tests/unittests/phy/upper/{tx_softbuffer_test_doubles.h => tx_buffer_test_doubles.h} (96%) delete mode 100644 tests/unittests/phy/upper/tx_softbuffer_pool_test_doubles.h diff --git a/apps/examples/du/du_example.cpp b/apps/examples/du/du_example.cpp index d349ca3030..fa057473b1 100644 --- a/apps/examples/du/du_example.cpp +++ b/apps/examples/du/du_example.cpp @@ -718,7 +718,6 @@ int main(int argc, char** argv) generate_carrier_config_tlv(), std::move(std::get>(pm_tools)), std::move(std::get>(uci_part2_tools)), - *dl_executors.front(), upper->get_tx_buffer_pool(), {0}); report_error_if_not(phy_adaptor, "Unable to create PHY adaptor."); diff --git a/apps/examples/du/fapi_factory.cpp b/apps/examples/du/fapi_factory.cpp index 37fc1193e0..a636e8bdc5 100644 --- a/apps/examples/du/fapi_factory.cpp +++ b/apps/examples/du/fapi_factory.cpp @@ -29,7 +29,6 @@ srsran::build_phy_fapi_adaptor(unsigned const fapi::carrier_config& carrier_cfg, std::unique_ptr pm_repo, std::unique_ptr part2_repo, - task_executor& async_executor, tx_buffer_pool& buffer_pool, std::vector prach_ports) { @@ -58,7 +57,6 @@ srsran::build_phy_fapi_adaptor(unsigned phy_fapi_dependencies.ul_pdu_validator = &ul_pdu_validator; phy_fapi_dependencies.pm_repo = std::move(pm_repo); phy_fapi_dependencies.part2_repo = std::move(part2_repo); - phy_fapi_dependencies.async_executor = &async_executor; return adaptor_factory->create(phy_fapi_config, std::move(phy_fapi_dependencies)); } diff --git a/apps/examples/du/fapi_factory.h b/apps/examples/du/fapi_factory.h index 4c0212fc8d..4938ebd03c 100644 --- a/apps/examples/du/fapi_factory.h +++ b/apps/examples/du/fapi_factory.h @@ -33,7 +33,6 @@ build_phy_fapi_adaptor(unsigned const fapi::carrier_config& carrier_cfg, std::unique_ptr pm_repo, std::unique_ptr part2_repo, - task_executor& async_executor, tx_buffer_pool& buffer_pool, std::vector prach_ports); diff --git a/apps/examples/du/phy_factory.cpp b/apps/examples/du/phy_factory.cpp index 8b819326dd..3581dfda02 100644 --- a/apps/examples/du/phy_factory.cpp +++ b/apps/examples/du/phy_factory.cpp @@ -83,7 +83,7 @@ std::unique_ptr srsran::create_upper_phy(const upper_phy_params& upper_config.tx_buffer_config.expire_timeout_slots = 100 * nof_slots_per_subframe; upper_config.tx_buffer_config.external_soft_bits = false; - upper_config.rx_buffer_config.max_softbuffers = upper_config.nof_dl_rg; + upper_config.rx_buffer_config.nof_buffers = upper_config.nof_dl_rg; upper_config.rx_buffer_config.max_nof_codeblocks = 128; upper_config.rx_buffer_config.max_codeblock_size = ldpc::MAX_CODEBLOCK_SIZE; upper_config.rx_buffer_config.expire_timeout_slots = 100 * nof_slots_per_subframe; diff --git a/apps/gnb/gnb_appconfig_translators.cpp b/apps/gnb/gnb_appconfig_translators.cpp index 4b39c6a335..f409497fb6 100644 --- a/apps/gnb/gnb_appconfig_translators.cpp +++ b/apps/gnb/gnb_appconfig_translators.cpp @@ -1615,7 +1615,7 @@ std::vector srsran::generate_du_low_config(const gnb_appconfig cfg.tx_buffer_config.expire_timeout_slots = expire_pdsch_harq_timeout_slots; cfg.tx_buffer_config.external_soft_bits = false; - cfg.rx_buffer_config.max_softbuffers = nof_buffers; + cfg.rx_buffer_config.nof_buffers = nof_buffers; cfg.rx_buffer_config.max_nof_codeblocks = max_rx_nof_codeblocks; cfg.rx_buffer_config.max_codeblock_size = ldpc::MAX_CODEBLOCK_SIZE; cfg.rx_buffer_config.expire_timeout_slots = expire_pusch_harq_timeout_slots; diff --git a/include/srsran/fapi_adaptor/phy/phy_fapi_adaptor_factory.h b/include/srsran/fapi_adaptor/phy/phy_fapi_adaptor_factory.h index 1a04895583..7e73d335b9 100644 --- a/include/srsran/fapi_adaptor/phy/phy_fapi_adaptor_factory.h +++ b/include/srsran/fapi_adaptor/phy/phy_fapi_adaptor_factory.h @@ -72,8 +72,6 @@ struct phy_fapi_adaptor_factory_dependencies { std::unique_ptr pm_repo; /// UCI Part2 correspondence repository. std::unique_ptr part2_repo; - /// Task executor for asynchronous tasks. - task_executor* async_executor; }; /// Factory to create \c phy_fapi_adaptor objects. diff --git a/include/srsran/phy/upper/channel_processors/pdsch_encoder.h b/include/srsran/phy/upper/channel_processors/pdsch_encoder.h index f8d3a4cd00..29a99a8d77 100644 --- a/include/srsran/phy/upper/channel_processors/pdsch_encoder.h +++ b/include/srsran/phy/upper/channel_processors/pdsch_encoder.h @@ -58,11 +58,11 @@ class pdsch_encoder /// block segmentation (see TS38.212 Section 7.2.3), codeblock encoding (see TS38.212 Section 7.2.4) and rate matching /// (see TS38.212 Section 7.2.5), and codeblock concatenation (see TS38.212 Section 7.2.6) into the PDSCH codeword. /// \param[out] codeword Final PDSCH codeword. - /// \param[in,out] softbuffer Rate matching softbuffer. + /// \param[in,out] rm_buffer Rate matching buffer. /// \param[in] transport_block Transport block to be transmitted. /// \param[in] cfg PDSCH configuration parameters. virtual void encode(span codeword, - tx_buffer& softbuffer, + tx_buffer& rm_buffer, span transport_block, const configuration& cfg) = 0; }; diff --git a/include/srsran/phy/upper/channel_processors/pdsch_processor.h b/include/srsran/phy/upper/channel_processors/pdsch_processor.h index 097a5dc48a..9a3c62175e 100644 --- a/include/srsran/phy/upper/channel_processors/pdsch_processor.h +++ b/include/srsran/phy/upper/channel_processors/pdsch_processor.h @@ -149,14 +149,14 @@ class pdsch_processor /// \brief Processes a PDSCH transmission. /// \param[out] mapper Resource grid mapper interface. - /// \param[in] softbuffer Data transmission rate match buffer. + /// \param[in] rm_buffer Rate match buffer. /// \param[out] notifier PDSCH processor notifier. /// \param[in] data The codewords to transmit. /// \param[in] pdu Necessary parameters to process the PDSCH transmission. /// \remark The number of transport blocks must be equal to the number of codewords in \c pdu. /// \remark The size of each transport block is determined by data[TB index].size() virtual void process(resource_grid_mapper& mapper, - unique_tx_buffer softbuffer, + unique_tx_buffer rm_buffer, pdsch_processor_notifier& notifier, static_vector, MAX_NOF_TRANSPORT_BLOCKS> data, const pdu_t& pdu) = 0; diff --git a/include/srsran/phy/upper/channel_processors/pusch/pusch_decoder.h b/include/srsran/phy/upper/channel_processors/pusch/pusch_decoder.h index bcfcc47c4e..a83bb8f6ab 100644 --- a/include/srsran/phy/upper/channel_processors/pusch/pusch_decoder.h +++ b/include/srsran/phy/upper/channel_processors/pusch/pusch_decoder.h @@ -22,8 +22,8 @@ namespace srsran { class pusch_decoder_buffer; class pusch_decoder_notifier; -class rx_softbuffer; -class unique_rx_softbuffer; +class rx_buffer; +class unique_rx_buffer; struct pusch_decoder_result; /// \brief PUSCH decoder interface. @@ -68,12 +68,12 @@ class pusch_decoder /// \brief Decodes a PUSCH codeword. /// \param[out] transport_block The decoded transport block, with packed (8 bits per entry) representation. - /// \param[in,out] soft_codeword A soft-buffer for combining log-likelihood ratios from different retransmissions. + /// \param[in,out] rm_buffer A buffer for combining log-likelihood ratios from different retransmissions. /// \param[in] notifier Interface for notifying the completion of the TB processing. /// \param[in] cfg Decoder configuration parameters. /// \return A \ref pusch_decoder_buffer, used to write softbits into the decoder. virtual pusch_decoder_buffer& new_data(span transport_block, - unique_rx_softbuffer softbuffer, + unique_rx_buffer rm_buffer, pusch_decoder_notifier& notifier, const configuration& cfg) = 0; }; diff --git a/include/srsran/phy/upper/channel_processors/pusch/pusch_processor.h b/include/srsran/phy/upper/channel_processors/pusch/pusch_processor.h index 69f04127c0..3f2069da5d 100644 --- a/include/srsran/phy/upper/channel_processors/pusch/pusch_processor.h +++ b/include/srsran/phy/upper/channel_processors/pusch/pusch_processor.h @@ -15,7 +15,7 @@ #include "srsran/phy/upper/channel_coding/ldpc/ldpc.h" #include "srsran/phy/upper/dmrs_mapping.h" #include "srsran/phy/upper/rb_allocation.h" -#include "srsran/phy/upper/rx_softbuffer.h" +#include "srsran/phy/upper/rx_buffer.h" #include "srsran/ran/pusch/pusch_context.h" #include "srsran/ran/sch_mcs.h" #include "srsran/ran/slot_point.h" @@ -26,7 +26,7 @@ namespace srsran { class pusch_processor_result_notifier; class resource_grid_reader; -class unique_rx_softbuffer; +class unique_rx_buffer; /// \brief Describes the PUSCH processor interface. /// @@ -146,13 +146,13 @@ class pusch_processor /// /// The size of each transport block is determined by data[TB index].size() . /// - /// \param[out] data Received transport block.. - /// \param[in,out] softbuffer Data reception softbuffer. - /// \param[in] notifier Result notification interface. - /// \param[in] grid Source resource grid. - /// \param[in] pdu Necessary parameters to process the PUSCH transmission. + /// \param[out] data Received transport block.. + /// \param[in,out] rm_buffer Rate matcher buffer. + /// \param[in] notifier Result notification interface. + /// \param[in] grid Source resource grid. + /// \param[in] pdu Necessary parameters to process the PUSCH transmission. virtual void process(span data, - unique_rx_softbuffer softbuffer, + unique_rx_buffer rm_buffer, pusch_processor_result_notifier& notifier, const resource_grid_reader& grid, const pdu_t& pdu) = 0; diff --git a/include/srsran/phy/upper/downlink_processor.h b/include/srsran/phy/upper/downlink_processor.h index 018ae9df2b..f11a662ed3 100644 --- a/include/srsran/phy/upper/downlink_processor.h +++ b/include/srsran/phy/upper/downlink_processor.h @@ -44,10 +44,10 @@ class downlink_processor /// \brief Process the given PDSCH PDU and its related data, which it is given in data parameter. /// - /// \param[in,out] softbuffer Transmit buffer. - /// \param[in] data Contains the PDSCH transport blocks. - /// \param[in] pdu PDSCH PDU to process. - virtual void process_pdsch(unique_tx_buffer buffer, + /// \param[in,out] rm_buffer Rate matcher buffer. + /// \param[in] data Contains the PDSCH transport blocks. + /// \param[in] pdu PDSCH PDU to process. + virtual void process_pdsch(unique_tx_buffer rm_buffer, const static_vector, pdsch_processor::MAX_NOF_TRANSPORT_BLOCKS>& data, const pdsch_processor::pdu_t& pdu) = 0; diff --git a/include/srsran/phy/upper/rx_softbuffer.h b/include/srsran/phy/upper/rx_buffer.h similarity index 96% rename from include/srsran/phy/upper/rx_softbuffer.h rename to include/srsran/phy/upper/rx_buffer.h index 0cd61cfa05..c9403ebed1 100644 --- a/include/srsran/phy/upper/rx_softbuffer.h +++ b/include/srsran/phy/upper/rx_buffer.h @@ -17,7 +17,7 @@ namespace srsran { class bit_buffer; -/// \brief Describes a receiver softbuffer. +/// \brief Describes a PUSCH rate matcher buffer. /// /// The aim is to provide the physical layer shared channel FEC with a persistent storage of CRC and soft bits buffer /// among transmissions for a given user and HARQ process. @@ -27,11 +27,11 @@ class bit_buffer; /// /// It is the responsibility of the shared channel receiver to reset CRCs and set to zero the soft bits when new data is /// indicated. -class rx_softbuffer +class rx_buffer { public: /// Default destructor. - virtual ~rx_softbuffer() = default; + virtual ~rx_buffer() = default; /// Gets the number of codeblocks. virtual unsigned get_nof_codeblocks() const = 0; diff --git a/include/srsran/phy/upper/rx_buffer_pool.h b/include/srsran/phy/upper/rx_buffer_pool.h new file mode 100644 index 0000000000..e305f913ce --- /dev/null +++ b/include/srsran/phy/upper/rx_buffer_pool.h @@ -0,0 +1,86 @@ +/* + * + * 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/upper/trx_buffer_identifier.h" +#include "srsran/ran/rnti.h" +#include "srsran/ran/slot_point.h" +#include +#include + +namespace srsran { + +class unique_rx_buffer; + +/// \brief Describes a receive buffer pool. +/// +/// The aim of this interface is to provide the physical layer shared channel decoder with receiver buffers. +/// +/// The receiver buffers are selected from a pool of resources for a given trx_buffer_identifier and kept persistent +/// until the buffer is released or expires. +/// +/// The pool is designed for being unique in a sector. In other words, every sector must create its own pool. +/// +/// The implementation might not be thread safe: reserve(), and run_slot() can not be called simultaneously. +/// +/// \remark An assertion is triggered if the slot numerology used for reserve() and run_slot() are different. +class rx_buffer_pool +{ +public: + /// Default destructor. + virtual ~rx_buffer_pool() = default; + + /// \brief Reserves and gets a buffer for a given identifier and number of codeblocks. + /// + /// It reserves a buffer for the given identifier. It guarantees that reserved buffers keep the CRC and data values. + /// + /// The buffers are reserved until: + /// - the buffer is freed using unique_rx_buffer::release(), + /// - a buffer reservation is performed with the same identifier but different number of codeblocks, or + /// - buffer reservation expires (by means run_slot()). + /// + /// The buffer CRC are reset if one of the conditions above is satisfied. + /// + /// The pool does not initialize or modify the codeblock contents of the buffers. The modules that use the buffers are + /// responsible for initializing and modifying their contents upon new transmissions. + /// + /// It is expected that the pool logs in \c PHY channel the context and the reason of a failed reservation. + /// + /// \param[in] slot Indicates the slot context in which the reservation occurs. + /// \param[in] id Identifies the buffer. + /// \param[in] nof_codeblocks Indicates the number of codeblocks to reserve. + /// \return A valid unique buffer if the reservation was successful. Otherwise, an invalid unique buffer. + virtual unique_rx_buffer reserve(const slot_point& slot, trx_buffer_identifier id, unsigned nof_codeblocks) = 0; + + /// \brief Runs pool housekeeping tasks. + /// \param[in] slot Indicates the current slot. + virtual void run_slot(const slot_point& slot) = 0; +}; + +/// buffer pool configuration. +struct rx_buffer_pool_config { + /// \brief Maximum codeblock size. + /// + /// Set to \c ldpc::MAX_CODEBLOCK_SIZE by default. + unsigned max_codeblock_size; + /// Number of buffers available in the pool. + unsigned nof_buffers; + /// Number of codeblocks available in the pool for all the buffers. + unsigned max_nof_codeblocks; + /// buffer lifetime as a number of slots. + unsigned expire_timeout_slots; + /// Set to true to indicate that soft bits are not stored in the buffer. + bool external_soft_bits; +}; + +std::unique_ptr create_rx_buffer_pool(const rx_buffer_pool_config& config); + +} // namespace srsran diff --git a/include/srsran/phy/upper/rx_softbuffer_pool.h b/include/srsran/phy/upper/rx_softbuffer_pool.h deleted file mode 100644 index 9bb767cd48..0000000000 --- a/include/srsran/phy/upper/rx_softbuffer_pool.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * - * 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/ran/slot_point.h" -#include - -namespace srsran { - -class unique_rx_softbuffer; - -/// Identifies a receive softbuffer. -struct rx_softbuffer_identifier { - /// Indicates the UE identifier. - uint16_t rnti; - /// Indicates the HARQ process identifier. - uint8_t harq_ack_id; - - /// Equal comparison to other identifier. - bool operator==(const rx_softbuffer_identifier& other) const - { - return (rnti == other.rnti) && (harq_ack_id == other.harq_ack_id); - } - - /// Not equal comparison with another identifier. - bool operator!=(const rx_softbuffer_identifier& other) const { return !(*this == other); } - - /// Get unknown buffer identifier. - static constexpr rx_softbuffer_identifier unknown() { return {0, 16}; } -}; - -/// \brief Describes a receive softbuffer pool. -/// -/// The aim of this interface is to provide the physical layer shared channel decoder with receiver softbuffers. -/// -/// The receiver softbuffers are selected from a pool of resources for a given rx_softbuffer_identifier and kept -/// persistent until the identifier is freed or expires. -/// -/// The pool is designed for being unique in a sector. In other words, every sector must create its own pool. -/// -/// The implementation must be thread safe: reserve_buffer(), free_softbuffer() and run_slot() can potentially be -/// called from different threads. -class rx_softbuffer_pool -{ -public: - /// Default destructor. - virtual ~rx_softbuffer_pool() = default; - - /// \brief Reserves and gets a softbuffer for a given identifier and number of codeblocks. - /// - /// Reserves a softbuffer for the given identifier. It guarantees that reserved softbuffers keep the CRC and data - /// values. - /// - /// The softbuffers are reserved until: - /// - the softbuffer identifier is freed using free_softbuffer(), - /// - a softbuffer reservation is performed with the same identifier but different number of codeblocks, or - /// - softbuffer reservation expires (by means run_slot()). - /// - /// The pool does not initialize or modify the contents of the softbuffers. The modules that use the softbuffers are - /// responsible for initializing and modifying their contents upon new transmissions. - /// - /// It is expected that the pool logs in \c PHY channel the reason of a failed reservation. - /// - /// \param[in] slot Indicates the slot context in which the reservation occurs. - /// \param[in] id Identifies the softbuffer. - /// \param[in] nof_codeblocks Indicates the number of codeblocks to reserve. - /// \return A valid unique softbuffer if the reservation was successful. Otherwise, an invalid unique softbuffer. - virtual unique_rx_softbuffer - reserve_softbuffer(const slot_point& slot, const rx_softbuffer_identifier& id, unsigned nof_codeblocks) = 0; - - /// \brief Runs internal state machines and releases expired softbuffers. - /// \param[in] slot Indicates the current slot. - virtual void run_slot(const slot_point& slot) = 0; -}; - -/// Softbuffer pool configuration. -struct rx_softbuffer_pool_config { - /// \brief Maximum codeblock size. - /// - /// Set to \c ldpc::MAX_CODEBLOCK_SIZE by default. - unsigned max_codeblock_size; - /// Number of softbuffers available in the pool. - unsigned max_softbuffers; - /// Number of codeblocks available in the pool for all the softbuffers. - unsigned max_nof_codeblocks; - /// Softbuffer lifetime as a number of slots. - unsigned expire_timeout_slots; - /// Set to true to indicate that soft bits are not stored in the buffer. - bool external_soft_bits; -}; - -std::unique_ptr create_rx_softbuffer_pool(const rx_softbuffer_pool_config& config); - -} // namespace srsran diff --git a/include/srsran/phy/upper/trx_buffer_identifier.h b/include/srsran/phy/upper/trx_buffer_identifier.h new file mode 100644 index 0000000000..62a5bd5c1a --- /dev/null +++ b/include/srsran/phy/upper/trx_buffer_identifier.h @@ -0,0 +1,90 @@ +/* + * + * 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 +#include +#include + +namespace srsran { + +/// Identifies transmit and receive buffers. +class trx_buffer_identifier +{ + /// Internal identifier type. + using id_type = uint32_t; + + /// Invalid identifier. + static constexpr id_type invalid_id = std::numeric_limits::max(); + /// Unknown identifier. + static constexpr id_type unknown_id = invalid_id - 1; + + /// Converts RNTI and HARQ identifiers to the internal identifier. + static constexpr uint32_t to_id(uint16_t rnti, uint8_t harq) + { + return (static_cast(rnti) << 8U) | static_cast(harq); + } + + /// Create from an internal identifier. + constexpr trx_buffer_identifier(uint32_t id_) : id(id_) {} + +public: + /// Get an invalid buffer identifier. + static constexpr trx_buffer_identifier invalid() { return invalid_id; } + + /// Get unknown buffer identifier. + static constexpr trx_buffer_identifier unknown() { return unknown_id; } + + /// Default constructor - creates an invalid identifier. + explicit trx_buffer_identifier() noexcept : id(invalid_id) {} + + /// Constructor from RNTI and HARQ process identifier. + explicit constexpr trx_buffer_identifier(uint16_t rnti, uint8_t harq) noexcept : id(to_id(rnti, harq)) {} + + /// Equal comparison to other identifier. + constexpr bool operator==(const trx_buffer_identifier& other) const { return other.id == id; } + + /// Not equal comparison with another identifier. + constexpr bool operator!=(const trx_buffer_identifier& other) const { return !(*this == other); } + + /// Gets the RNTI. + uint16_t get_rnti() const { return static_cast(id >> 8); } + + /// Gets the HARQ process identifier. + uint8_t get_harq() const { return static_cast(id & 0xff); } + +private: + /// Internal identifier. + id_type id; +}; + +} // namespace srsran + +namespace fmt { + +/// Default formatter for trx_buffer_identifier. +template <> +struct formatter { + template + auto parse(ParseContext& ctx) -> decltype(ctx.begin()) + { + return ctx.begin(); + } + + template + auto format(const srsran::trx_buffer_identifier& value, FormatContext& ctx) + -> decltype(std::declval().out()) + { + return format_to(ctx.out(), "rnti={:#x} h_id={}", value.get_rnti(), value.get_harq()); + } +}; + +} // namespace fmt \ No newline at end of file diff --git a/include/srsran/phy/upper/tx_buffer.h b/include/srsran/phy/upper/tx_buffer.h index f920407e83..42cd9165ad 100644 --- a/include/srsran/phy/upper/tx_buffer.h +++ b/include/srsran/phy/upper/tx_buffer.h @@ -15,7 +15,7 @@ namespace srsran { -/// \brief Describes a transmitter buffer. +/// \brief Describes a PDSCH rate matcher buffer. /// /// The aim is to provide the physical layer shared channel FEC with a persistent storage of the rate matcher buffer /// among transmissions for a given user and HARQ process. diff --git a/include/srsran/phy/upper/tx_buffer_pool.h b/include/srsran/phy/upper/tx_buffer_pool.h index fa2a739721..33e73a49b3 100644 --- a/include/srsran/phy/upper/tx_buffer_pool.h +++ b/include/srsran/phy/upper/tx_buffer_pool.h @@ -10,6 +10,7 @@ #pragma once +#include "srsran/phy/upper/trx_buffer_identifier.h" #include "srsran/ran/slot_point.h" #include @@ -17,35 +18,18 @@ namespace srsran { class unique_tx_buffer; -/// Identifies a transmit buffer. -struct tx_buffer_identifier { - /// The UE temporal identifier. - uint16_t rnti; - /// The HARQ process identifier. - uint8_t harq_ack_id; - - /// Equal comparison to other identifier. - bool operator==(const tx_buffer_identifier& other) const - { - return (rnti == other.rnti) && (harq_ack_id == other.harq_ack_id); - } - - /// Get unknown buffer identifier. - static constexpr tx_buffer_identifier unknown() { return {0, 16}; } -}; - /// \brief Describes a transmitter buffer pool interface. /// /// The purpose of this interface is to provide the physical layer shared channel encoder with transmitter rate match /// buffers. /// -/// Transmitter buffers are selected from a pool of resources using a given tx_buffer_identifier and remain +/// Transmitter buffers are selected from a pool of resources using a given trx_buffer_identifier and remain /// persistent until the identifier is reused or expires. /// /// Each sector is expected to create its unique pool for the purpose of resource management. /// -/// The implementation of this interface must be thread-safe, as both reserve_buffer() and run_slot() may be called -/// from different threads. +/// The implementation of this interface might not thread-safe, reserve() and run_slot() must be called from the same +/// thread. class tx_buffer_pool { public: @@ -69,8 +53,7 @@ class tx_buffer_pool /// \param[in] nof_codeblocks Number of codeblocks to reserve. /// \return A valid unique transmit buffer if the reservation was successful; otherwise, an invalid unique transmit /// buffer. - virtual unique_tx_buffer - reserve_buffer(const slot_point& slot, const tx_buffer_identifier& id, unsigned nof_codeblocks) = 0; + virtual unique_tx_buffer reserve(const slot_point& slot, trx_buffer_identifier id, unsigned nof_codeblocks) = 0; /// \brief Reserves and retrieves a transmit buffer without an identifier. /// @@ -83,7 +66,7 @@ class tx_buffer_pool /// \param[in] slot Slot context. /// \param[in] nof_codeblocks Number of codeblocks to reserve. /// \return A valid unique transmit buffer if the reservation was successful; otherwise, an invalid unique buffer. - virtual unique_tx_buffer reserve_buffer(const slot_point& slot, unsigned nof_codeblocks) = 0; + virtual unique_tx_buffer reserve(const slot_point& slot, unsigned nof_codeblocks) = 0; /// \brief Runs internal state machines and releases expired buffers. /// \param[in] slot Current slot. diff --git a/include/srsran/phy/upper/unique_rx_buffer.h b/include/srsran/phy/upper/unique_rx_buffer.h new file mode 100644 index 0000000000..c78cd283df --- /dev/null +++ b/include/srsran/phy/upper/unique_rx_buffer.h @@ -0,0 +1,129 @@ +/* + * + * 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/upper/rx_buffer.h" +#include "srsran/support/srsran_assert.h" + +namespace srsran { + +/// \brief Wraps a receive buffer instance and locks it inside a scope. +/// +/// The locking mechanism prevents the pool from reserving and freeing a buffer as long as it is being used inside a +/// block scope. +class unique_rx_buffer +{ +public: + /// \brief Public interface required for locking and unlocking the internal buffer. + /// + /// The implementation must be thread safe. In other words, lock(), unlock() and release() might be called from + /// different threads. + class callback : public rx_buffer + { + public: + /// Locks the buffer. + virtual void lock() = 0; + + /// Unlocks the buffer. + virtual void unlock() = 0; + + /// Releases (after unlocking) the buffer resources. + virtual void release() = 0; + }; + + /// Builds an invalid buffer. + explicit unique_rx_buffer() = default; + + /// Builds a unique buffer from a buffer reference. It locks the internal buffer. + explicit unique_rx_buffer(callback& instance_) : ptr(&instance_) + { + if (ptr != nullptr) { + ptr->lock(); + } + } + + /// Destructor - it unlocks the buffer. + ~unique_rx_buffer() + { + if (ptr != nullptr) { + ptr->unlock(); + ptr = nullptr; + } + } + + /// Copy constructor is deleted to prevent the unique buffer from being shared across multiple scopes. + unique_rx_buffer(unique_rx_buffer& /**/) = delete; + + /// Move constructor is the only way to move the buffer to a different scope. + unique_rx_buffer(unique_rx_buffer&& other) noexcept + { + ptr = other.ptr; + other.ptr = nullptr; + }; + + /// Move assigment operator. + unique_rx_buffer& operator=(unique_rx_buffer&& other) noexcept + { + // Unlock current soft buffer if it is actually not unlocked. + if (ptr != nullptr) { + ptr->unlock(); + } + + // Move the other soft buffer ownership to the current soft buffer. + ptr = other.ptr; + other.ptr = nullptr; + + return *this; + } + + /// Gets the buffer. + rx_buffer& get() + { + srsran_assert(is_valid(), "Invalid buffer."); + return *ptr; + } + + /// Gets a read-only buffer. + const rx_buffer& get() const + { + srsran_assert(is_valid(), "Invalid buffer."); + return *ptr; + } + + rx_buffer& operator*() { return get(); } + rx_buffer* operator->() { return &get(); } + const rx_buffer& operator*() const { return get(); } + const rx_buffer* operator->() const { return &get(); } + + /// Returns true if the unique buffer contains a valid buffer. + bool is_valid() const { return ptr != nullptr; } + + /// Unlock and releases the buffer resources. + void release() + { + srsran_assert(ptr != nullptr, "Invalid buffer for releasing."); + ptr->release(); + ptr = nullptr; + } + + /// Unlocks the buffer resources. + void unlock() + { + srsran_assert(ptr != nullptr, "Invalid buffer for unlocking."); + ptr->unlock(); + ptr = nullptr; + } + +private: + /// Underlying pointer to the buffer. Set to nullptr for an invalid buffer. + callback* ptr = nullptr; +}; + +} // namespace srsran diff --git a/include/srsran/phy/upper/unique_rx_softbuffer.h b/include/srsran/phy/upper/unique_rx_softbuffer.h deleted file mode 100644 index 824a3f95e8..0000000000 --- a/include/srsran/phy/upper/unique_rx_softbuffer.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * - * 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/upper/rx_softbuffer.h" - -namespace srsran { - -/// \brief Wraps a softbuffer instance and locks it inside a block scope. -/// -/// The locking mechanism prevents the pool from reserving and freeing a softbuffer as long as it is being used inside a -/// block scope. -class unique_rx_softbuffer -{ -public: - /// Public interface required for locking and unlocking the internal softbuffer. - class softbuffer : public rx_softbuffer - { - public: - /// Locks the softbuffer. - virtual void lock() = 0; - - /// Unlocks the softbuffer. - virtual void unlock() = 0; - - /// Releases (after unlocking) the softbuffer resources. - virtual void release() = 0; - }; - - /// Builds an invalid softbuffer. - unique_rx_softbuffer() = default; - - /// Builds a unique softbuffer from a softbuffer reference. It locks the internal buffer. - explicit unique_rx_softbuffer(softbuffer& softbuffer_) : ptr(&softbuffer_) - { - if (ptr != nullptr) { - ptr->lock(); - } - } - - /// Destructor - it releases the softbuffer. - ~unique_rx_softbuffer() - { - if (ptr != nullptr) { - ptr->unlock(); - ptr = nullptr; - } - } - - /// Copy constructor is deleted to prevent the unique softbuffer from being shared across multiple scopes. - unique_rx_softbuffer(unique_rx_softbuffer& /**/) = delete; - - /// Move constructor is the only way to move the softbuffer to a different scope. - unique_rx_softbuffer(unique_rx_softbuffer&& other) noexcept - { - ptr = other.ptr; - other.ptr = nullptr; - }; - - /// Move assigment operator. - unique_rx_softbuffer& operator=(unique_rx_softbuffer&& other) noexcept - { - // Unlock current soft buffer if it is actually not unlocked. - if (ptr != nullptr) { - ptr->unlock(); - } - - // Move the other soft buffer ownership to the current soft buffer. - ptr = other.ptr; - other.ptr = nullptr; - - return *this; - } - - /// Gets the softbuffer. - rx_softbuffer& get() - { - srsran_assert(is_valid(), "Invalid softbuffer."); - return *ptr; - } - - const rx_softbuffer& get() const - { - srsran_assert(is_valid(), "Invalid softbuffer."); - return *ptr; - } - - rx_softbuffer& operator*() { return get(); } - rx_softbuffer* operator->() { return &get(); } - const rx_softbuffer& operator*() const { return get(); } - const rx_softbuffer* operator->() const { return &get(); } - - /// Returns true if the unique softbuffer contains a valid softbuffer. - bool is_valid() const { return ptr != nullptr; } - - /// Unlock and releases the softbuffer resources. - void release() - { - srsran_assert(ptr != nullptr, "Invalid softbuffer for releasing."); - ptr->release(); - ptr = nullptr; - } - - /// Unlocks the softbuffer resources. - void unlock() - { - srsran_assert(ptr != nullptr, "Invalid softbuffer for unlocking."); - ptr->unlock(); - ptr = nullptr; - } - -private: - /// Underlying pointer to the softbuffer. Set to nullptr for an invalid softbuffer. - softbuffer* ptr = nullptr; -}; - -} // namespace srsran diff --git a/include/srsran/phy/upper/unique_tx_buffer.h b/include/srsran/phy/upper/unique_tx_buffer.h index 620c21cae4..d6358d9d61 100644 --- a/include/srsran/phy/upper/unique_tx_buffer.h +++ b/include/srsran/phy/upper/unique_tx_buffer.h @@ -20,7 +20,7 @@ class unique_tx_buffer { public: /// Public interface required for locking and unlocking the internal buffer. - class lockable_buffer : public tx_buffer + class callback : public tx_buffer { public: /// Locks the buffer. @@ -34,7 +34,7 @@ class unique_tx_buffer unique_tx_buffer() = default; /// Builds a unique transmit buffer from a reference. It locks the internal buffer. - explicit unique_tx_buffer(lockable_buffer& buffer_) : ptr(&buffer_) + explicit unique_tx_buffer(callback& buffer_) : ptr(&buffer_) { if (ptr != nullptr) { ptr->lock(); @@ -89,7 +89,7 @@ class unique_tx_buffer private: /// Underlying pointer to the actual buffer. Set to nullptr for an invalid buffer. - lockable_buffer* ptr = nullptr; + callback* ptr = nullptr; }; } // namespace srsran diff --git a/include/srsran/phy/upper/uplink_processor.h b/include/srsran/phy/upper/uplink_processor.h index 48b6645083..2dd722b0c2 100644 --- a/include/srsran/phy/upper/uplink_processor.h +++ b/include/srsran/phy/upper/uplink_processor.h @@ -16,7 +16,7 @@ #include "srsran/phy/upper/channel_processors/prach_detector.h" #include "srsran/phy/upper/channel_processors/pucch_processor.h" #include "srsran/phy/upper/channel_processors/pusch/pusch_processor.h" -#include "srsran/phy/upper/unique_rx_softbuffer.h" +#include "srsran/phy/upper/unique_rx_buffer.h" #include "srsran/phy/upper/uplink_processor_context.h" namespace srsran { @@ -85,12 +85,12 @@ class uplink_processor /// upper_phy_rx_results_notifier::on_new_pusch_results "on_new_pusch_results". /// /// \param[out] data Received transport block. - /// \param[in,out] softbuffer Data reception softbuffer. + /// \param[in,out] rm_buffer Rate matcher buffer. /// \param[in] notifier Event notification interface. /// \param[in] grid Grid the capture data is stored in. /// \param[in] pdu PUSCH transmission parameters. virtual void process_pusch(span data, - unique_rx_softbuffer softbuffer, + unique_rx_buffer rm_buffer, upper_phy_rx_results_notifier& notifier, const resource_grid_reader& grid, const uplink_processor::pusch_pdu& pdu) = 0; diff --git a/include/srsran/phy/upper/upper_phy_factories.h b/include/srsran/phy/upper/upper_phy_factories.h index f222818f98..cb8af982ef 100644 --- a/include/srsran/phy/upper/upper_phy_factories.h +++ b/include/srsran/phy/upper/upper_phy_factories.h @@ -15,7 +15,7 @@ #include "srsran/phy/upper/channel_coding/channel_coding_factories.h" #include "srsran/phy/upper/channel_processors/channel_processor_factories.h" #include "srsran/phy/upper/downlink_processor.h" -#include "srsran/phy/upper/rx_softbuffer_pool.h" +#include "srsran/phy/upper/rx_buffer_pool.h" #include "srsran/phy/upper/uplink_processor.h" #include "srsran/phy/upper/upper_phy.h" #include @@ -292,7 +292,7 @@ struct upper_phy_config { /// Transmit buffer pool configuration. tx_buffer_pool_config tx_buffer_config; /// Receive buffer pool configuration. - rx_softbuffer_pool_config rx_buffer_config; + rx_buffer_pool_config rx_buffer_config; /// Upper PHY resource grid gateway. upper_phy_rg_gateway* rg_gateway; /// Downlink task executors. diff --git a/lib/du/adapters/fapi_factory.cpp b/lib/du/adapters/fapi_factory.cpp index 4f61df8f17..abad756aa7 100644 --- a/lib/du/adapters/fapi_factory.cpp +++ b/lib/du/adapters/fapi_factory.cpp @@ -32,7 +32,6 @@ srsran::build_phy_fapi_adaptor(unsigned sect const fapi::carrier_config& carrier_cfg, std::unique_ptr pm_repo, std::unique_ptr part2_repo, - task_executor& async_executor, tx_buffer_pool& buffer_pool, std::vector prach_ports) { @@ -60,7 +59,6 @@ srsran::build_phy_fapi_adaptor(unsigned sect phy_fapi_dependencies.ul_pdu_validator = &ul_pdu_validator; phy_fapi_dependencies.pm_repo = std::move(pm_repo); phy_fapi_dependencies.part2_repo = std::move(part2_repo); - phy_fapi_dependencies.async_executor = &async_executor; return adaptor_factory->create(phy_fapi_config, std::move(phy_fapi_dependencies)); } diff --git a/lib/du/adapters/fapi_factory.h b/lib/du/adapters/fapi_factory.h index 7d00f15736..e3a5fa69c8 100644 --- a/lib/du/adapters/fapi_factory.h +++ b/lib/du/adapters/fapi_factory.h @@ -36,7 +36,6 @@ build_phy_fapi_adaptor(unsigned const fapi::carrier_config& carrier_cfg, std::unique_ptr pm_repo, std::unique_ptr part2_repo, - task_executor& async_executor, tx_buffer_pool& buffer_pool, std::vector prach_ports); diff --git a/lib/du/du_impl.cpp b/lib/du/du_impl.cpp index 61d1b6ae26..538819bee0 100644 --- a/lib/du/du_impl.cpp +++ b/lib/du/du_impl.cpp @@ -127,7 +127,6 @@ du_impl::du_impl(const du_config& du_cfg) : generate_carrier_config_tlv(du_cell), std::move(std::get>(pm_tools)), std::move(std::get>(uci_part2_tools)), - *upper_phy_cfg.dl_executors.front(), du_lo->get_tx_buffer_pool(), du_cfg.fapi.prach_ports); diff --git a/lib/fapi_adaptor/phy/fapi_to_phy_translator.cpp b/lib/fapi_adaptor/phy/fapi_to_phy_translator.cpp index 29c02d9b75..63f212804e 100644 --- a/lib/fapi_adaptor/phy/fapi_to_phy_translator.cpp +++ b/lib/fapi_adaptor/phy/fapi_to_phy_translator.cpp @@ -37,7 +37,7 @@ class downlink_processor_dummy : public downlink_processor { srslog::fetch_basic_logger("FAPI").warning("Could not enqueue PDCCH PDU in the downlink processor"); } - void process_pdsch(unique_tx_buffer softbuffer, + void process_pdsch(unique_tx_buffer rm_buffer, const static_vector, pdsch_processor::MAX_NOF_TRANSPORT_BLOCKS>& data, const pdsch_processor::pdu_t& pdu) override { @@ -82,7 +82,6 @@ fapi_to_phy_translator::fapi_to_phy_translator(const fapi_to_phy_translator_conf ul_rg_pool(*dependencies.ul_rg_pool), ul_pdu_validator(*dependencies.ul_pdu_validator), ul_pdu_repository(*dependencies.ul_pdu_repository), - asynchronous_executor(*dependencies.async_executor), slot_controller_mngr(*dependencies.dl_processor_pool, *dependencies.dl_rg_pool, sector_id, @@ -620,18 +619,16 @@ void fapi_to_phy_translator::tx_data_request(const fapi::tx_data_request_message unsigned nof_cb = ldpc::compute_nof_codeblocks(pdu.tlv_custom.length.to_bits(), pdsch_config.ldpc_base_graph); // Prepare buffer identifier. - tx_buffer_identifier id; - id.rnti = pdsch_config.rnti; - id.harq_ack_id = (pdsch_config.context.has_value()) ? pdsch_config.context->get_h_id() : 0; + trx_buffer_identifier id(pdsch_config.rnti, + (pdsch_config.context.has_value()) ? pdsch_config.context->get_h_id() : 0); // Get transmit buffer. - unique_tx_buffer buffer = (pdsch_config.context.has_value()) - ? buffer_pool.reserve_buffer(pdsch_config.slot, id, nof_cb) - : buffer_pool.reserve_buffer(pdsch_config.slot, nof_cb); + unique_tx_buffer buffer = (pdsch_config.context.has_value()) ? buffer_pool.reserve(pdsch_config.slot, id, nof_cb) + : buffer_pool.reserve(pdsch_config.slot, nof_cb); // Check the soft buffer is valid. if (!buffer.is_valid()) { - logger.warning("No PDSCH softbuffer available for rnti=0x{:04x}.", id.rnti); + logger.warning("No PDSCH buffer available for {}.", id); return; } @@ -644,6 +641,9 @@ void fapi_to_phy_translator::tx_data_request(const fapi::tx_data_request_message // All the PDSCH PDUs have been processed. Clear the repository. pdsch_repository.clear(); + // Run PDSCH buffer housekeeping. + buffer_pool.run_slot(slot); + l1_tracer << trace_event("tx_data_request", tp); } @@ -653,11 +653,6 @@ void fapi_to_phy_translator::handle_new_slot(slot_point slot) update_current_slot(slot); - // Enqueue soft buffer run slot. - if (!asynchronous_executor.execute([this, slot]() { buffer_pool.run_slot(slot); })) { - logger.warning("Failed to execute transmit softbuffer pool slot."); - } - // Update the logger context. logger.set_context(slot.sfn(), slot.slot_index()); diff --git a/lib/fapi_adaptor/phy/fapi_to_phy_translator.h b/lib/fapi_adaptor/phy/fapi_to_phy_translator.h index 9eb2e3e9b5..6f8875ea92 100644 --- a/lib/fapi_adaptor/phy/fapi_to_phy_translator.h +++ b/lib/fapi_adaptor/phy/fapi_to_phy_translator.h @@ -74,8 +74,6 @@ struct fapi_to_phy_translator_dependencies { std::unique_ptr pm_repo; /// UCI Part2 correspondence repository. std::unique_ptr part2_repo; - /// Task executor for asynchronous tasks. - task_executor* async_executor; }; /// \brief FAPI-to-PHY message translator. @@ -250,7 +248,7 @@ class fapi_to_phy_translator : public fapi::slot_message_gateway srslog::basic_logger& logger; /// Downlink PDU validator. const downlink_pdu_validator& dl_pdu_validator; - /// PDSCH Softbuffer pool. + /// PDSCH buffer pool. tx_buffer_pool& buffer_pool; /// Uplink request processor. uplink_request_processor& ul_request_processor; @@ -260,8 +258,6 @@ class fapi_to_phy_translator : public fapi::slot_message_gateway const uplink_pdu_validator& ul_pdu_validator; /// Uplink slot PDU repository. uplink_slot_pdu_repository& ul_pdu_repository; - /// Asynchronous task executor. - task_executor& asynchronous_executor; /// Current slot count value. std::atomic current_slot_count_val; /// Slot controller manager. diff --git a/lib/fapi_adaptor/phy/phy_fapi_adaptor_factory_impl.cpp b/lib/fapi_adaptor/phy/phy_fapi_adaptor_factory_impl.cpp index 089682d966..dfc6f1b4dc 100644 --- a/lib/fapi_adaptor/phy/phy_fapi_adaptor_factory_impl.cpp +++ b/lib/fapi_adaptor/phy/phy_fapi_adaptor_factory_impl.cpp @@ -39,7 +39,6 @@ phy_fapi_adaptor_factory_impl::create(const phy_fapi_adaptor_factory_config& co adaptor_dependencies.ul_pdu_validator = dependencies.ul_pdu_validator; adaptor_dependencies.pm_repo = std::move(dependencies.pm_repo); adaptor_dependencies.part2_repo = std::move(dependencies.part2_repo); - adaptor_dependencies.async_executor = dependencies.async_executor; return std::make_unique(adaptor_config, std::move(adaptor_dependencies)); } diff --git a/lib/fapi_adaptor/phy/phy_fapi_adaptor_impl.cpp b/lib/fapi_adaptor/phy/phy_fapi_adaptor_impl.cpp index 85901ffc44..2a6c768739 100644 --- a/lib/fapi_adaptor/phy/phy_fapi_adaptor_impl.cpp +++ b/lib/fapi_adaptor/phy/phy_fapi_adaptor_impl.cpp @@ -46,7 +46,6 @@ generate_fapi_to_phy_translator_dependencies(phy_fapi_adaptor_impl_dependencies& fapi_dependencies.ul_pdu_validator = dependencies.ul_pdu_validator; fapi_dependencies.pm_repo = std::move(dependencies.pm_repo); fapi_dependencies.part2_repo = std::move(dependencies.part2_repo); - fapi_dependencies.async_executor = dependencies.async_executor; return fapi_dependencies; } diff --git a/lib/fapi_adaptor/phy/phy_fapi_adaptor_impl.h b/lib/fapi_adaptor/phy/phy_fapi_adaptor_impl.h index 098c0712ae..fb2c8b292e 100644 --- a/lib/fapi_adaptor/phy/phy_fapi_adaptor_impl.h +++ b/lib/fapi_adaptor/phy/phy_fapi_adaptor_impl.h @@ -67,8 +67,6 @@ struct phy_fapi_adaptor_impl_dependencies { std::unique_ptr pm_repo; /// UCI Part2 correspondence repository. std::unique_ptr part2_repo; - /// Asynchronous task executor. - task_executor* async_executor; }; /// \brief PHY–FAPI bidirectional adaptor implementation. diff --git a/lib/phy/upper/CMakeLists.txt b/lib/phy/upper/CMakeLists.txt index 6e11202519..301de5101a 100644 --- a/lib/phy/upper/CMakeLists.txt +++ b/lib/phy/upper/CMakeLists.txt @@ -39,7 +39,7 @@ add_library(log_likelihood_ratio log_likelihood_ratio.cpp) add_library(srsran_upper_phy_support rb_allocation.cpp - rx_softbuffer_pool_impl.cpp + rx_buffer_pool_impl.cpp tx_buffer_pool_impl.cpp vrb_to_prb_mapper.cpp ) diff --git a/lib/phy/upper/channel_processors/channel_processor_factories.cpp b/lib/phy/upper/channel_processors/channel_processor_factories.cpp index d1ef7f46eb..ec479c42d8 100644 --- a/lib/phy/upper/channel_processors/channel_processor_factories.cpp +++ b/lib/phy/upper/channel_processors/channel_processor_factories.cpp @@ -1058,7 +1058,7 @@ class logging_pdsch_processor_decorator : public pdsch_processor, private pdsch_ } void process(resource_grid_mapper& mapper, - unique_tx_buffer softbuffer, + unique_tx_buffer rm_buffer, pdsch_processor_notifier& notifier_, static_vector, MAX_NOF_TRANSPORT_BLOCKS> data_, const pdu_t& pdu_) override @@ -1068,7 +1068,7 @@ class logging_pdsch_processor_decorator : public pdsch_processor, private pdsch_ pdu = pdu_; start = std::chrono::steady_clock::now(); - processor->process(mapper, std::move(softbuffer), *this, data_, pdu); + processor->process(mapper, std::move(rm_buffer), *this, data_, pdu); } private: diff --git a/lib/phy/upper/channel_processors/pdsch_encoder_impl.cpp b/lib/phy/upper/channel_processors/pdsch_encoder_impl.cpp index 5524cd3e77..44fde15804 100644 --- a/lib/phy/upper/channel_processors/pdsch_encoder_impl.cpp +++ b/lib/phy/upper/channel_processors/pdsch_encoder_impl.cpp @@ -15,7 +15,7 @@ using namespace srsran; void pdsch_encoder_impl::encode(span codeword, - tx_buffer& softbuffer, + tx_buffer& buffer, span transport_block, const configuration& config) { @@ -34,19 +34,18 @@ void pdsch_encoder_impl::encode(span codeword, segmenter->segment(d_segments, transport_block, segmenter_cfg); // Make sure the number of codeblocks match the number of segments. - srsran_assert( - softbuffer.get_nof_codeblocks() == d_segments.size(), - "The number of codeblocks in the softbuffer (i.e., {}) are not eqwual to the number of segments (i.e., {}).", - softbuffer.get_nof_codeblocks(), - d_segments.size()); + srsran_assert(buffer.get_nof_codeblocks() == d_segments.size(), + "The number of codeblocks in the buffer (i.e., {}) are not equal to the number of segments (i.e., {}).", + buffer.get_nof_codeblocks(), + d_segments.size()); unsigned offset = 0; for (unsigned i_cb = 0, i_cb_end = d_segments.size(); i_cb != i_cb_end; ++i_cb) { // Select segment description. const described_segment& descr_seg = d_segments[i_cb]; - // Get rate matching buffer from the softbuffer. - bit_buffer rm_buffer = softbuffer.get_codeblock(i_cb, descr_seg.get_metadata().cb_specific.full_length); + // Get rate matching buffer from the buffer. + bit_buffer rm_buffer = buffer.get_codeblock(i_cb, descr_seg.get_metadata().cb_specific.full_length); if (config.new_data) { // Encode the segment into a codeblock. diff --git a/lib/phy/upper/channel_processors/pdsch_encoder_impl.h b/lib/phy/upper/channel_processors/pdsch_encoder_impl.h index a3bd8de079..3001bd74dd 100644 --- a/lib/phy/upper/channel_processors/pdsch_encoder_impl.h +++ b/lib/phy/upper/channel_processors/pdsch_encoder_impl.h @@ -42,7 +42,7 @@ class pdsch_encoder_impl : public pdsch_encoder // See interface for the documentation. void encode(span codeword, - tx_buffer& softbuffer, + tx_buffer& rm_buffer, span transport_block, const configuration& config) override; diff --git a/lib/phy/upper/channel_processors/pdsch_processor_concurrent_impl.cpp b/lib/phy/upper/channel_processors/pdsch_processor_concurrent_impl.cpp index a7ccd01294..227f8f1bcd 100644 --- a/lib/phy/upper/channel_processors/pdsch_processor_concurrent_impl.cpp +++ b/lib/phy/upper/channel_processors/pdsch_processor_concurrent_impl.cpp @@ -19,13 +19,13 @@ using namespace srsran; void pdsch_processor_concurrent_impl::process(resource_grid_mapper& mapper_, - unique_tx_buffer softbuffer_, + unique_tx_buffer rm_buffer_, pdsch_processor_notifier& notifier_, static_vector, MAX_NOF_TRANSPORT_BLOCKS> data_, const pdsch_processor::pdu_t& pdu_) { // Saves inputs. - save_inputs(mapper_, std::move(softbuffer_), notifier_, data_, pdu_); + save_inputs(mapper_, std::move(rm_buffer_), notifier_, data_, pdu_); // Makes sure the PDU is valid. pdsch_processor_validator_impl::assert_pdu(config); @@ -44,7 +44,7 @@ void pdsch_processor_concurrent_impl::process(resource_grid_mapper& } void pdsch_processor_concurrent_impl::save_inputs(resource_grid_mapper& mapper_, - unique_tx_buffer softbuffer_, + unique_tx_buffer rm_buffer_, pdsch_processor_notifier& notifier_, static_vector, MAX_NOF_TRANSPORT_BLOCKS> data_, const pdsch_processor::pdu_t& pdu) @@ -52,14 +52,14 @@ void pdsch_processor_concurrent_impl::save_inputs(resource_grid_mapper& mapp using namespace units::literals; // Save process parameter inputs. - mapper = &mapper_; - notifier = ¬ifier_; - data = data_.front(); - config = pdu; - softbuffer = std::move(softbuffer_); + mapper = &mapper_; + notifier = ¬ifier_; + data = data_.front(); + config = pdu; + unique_rm_buffer = std::move(rm_buffer_); - // verify softbuffer is valid. - srsran_assert(softbuffer.is_valid(), "Invalid softbuffer."); + // verify buffer is valid. + srsran_assert(unique_rm_buffer.is_valid(), "Invalid buffer."); // Codeword index is fix. static constexpr unsigned i_cw = 0; @@ -288,7 +288,7 @@ void pdsch_processor_concurrent_impl::fork_cb_batches() // Get rate matching buffer. bit_buffer rm_buffer = - softbuffer.get().get_codeblock(absolute_i_cb, cb_config.metadata.cb_specific.full_length); + unique_rm_buffer.get().get_codeblock(absolute_i_cb, cb_config.metadata.cb_specific.full_length); // Process codeblock. pdsch_codeblock_processor::result result = cb_processor.process(rm_buffer, data, cb_config); @@ -305,8 +305,8 @@ void pdsch_processor_concurrent_impl::fork_cb_batches() // Decrement code block batch counter. if (cb_batch_counter.fetch_sub(1) == 1) { - // Unlock softbuffer. - softbuffer = unique_tx_buffer(); + // Unlock buffer. + unique_rm_buffer = unique_tx_buffer(); // Decrement asynchronous task counter. if (async_task_counter.fetch_sub(1) == 1) { diff --git a/lib/phy/upper/channel_processors/pdsch_processor_concurrent_impl.h b/lib/phy/upper/channel_processors/pdsch_processor_concurrent_impl.h index 47df37ba5f..88876690a6 100644 --- a/lib/phy/upper/channel_processors/pdsch_processor_concurrent_impl.h +++ b/lib/phy/upper/channel_processors/pdsch_processor_concurrent_impl.h @@ -53,7 +53,7 @@ class pdsch_processor_concurrent_impl : public pdsch_processor // See interface for documentation. void process(resource_grid_mapper& mapper, - unique_tx_buffer softbuffer, + unique_tx_buffer rm_buffer, pdsch_processor_notifier& notifier, static_vector, MAX_NOF_TRANSPORT_BLOCKS> data, const pdu_t& pdu) override; @@ -69,7 +69,7 @@ class pdsch_processor_concurrent_impl : public pdsch_processor /// Saves process() parameters for future uses during an asynchronous execution. void save_inputs(resource_grid_mapper& mapper, - unique_tx_buffer softbuffer, + unique_tx_buffer rm_buffer, pdsch_processor_notifier& notifier, static_vector, MAX_NOF_TRANSPORT_BLOCKS> data, const pdu_t& pdu); @@ -93,7 +93,7 @@ class pdsch_processor_concurrent_impl : public pdsch_processor pdsch_processor_notifier* notifier; span data; pdsch_processor::pdu_t config; - unique_tx_buffer softbuffer; + unique_tx_buffer unique_rm_buffer; /// Transport block size of the current transmission. units::bits tbs; diff --git a/lib/phy/upper/channel_processors/pdsch_processor_impl.cpp b/lib/phy/upper/channel_processors/pdsch_processor_impl.cpp index 7f1678a9cc..61fef2b8ff 100644 --- a/lib/phy/upper/channel_processors/pdsch_processor_impl.cpp +++ b/lib/phy/upper/channel_processors/pdsch_processor_impl.cpp @@ -17,7 +17,7 @@ using namespace srsran; void pdsch_processor_impl::process(resource_grid_mapper& mapper, - unique_tx_buffer softbuffer, + unique_tx_buffer rm_buffer, pdsch_processor_notifier& notifier, static_vector, MAX_NOF_TRANSPORT_BLOCKS> data, const pdsch_processor::pdu_t& pdu) @@ -47,7 +47,7 @@ void pdsch_processor_impl::process(resource_grid_mapper& // Encode each codeword. for (unsigned codeword_id = 0; codeword_id != nof_codewords; ++codeword_id) { unsigned nof_layers_cw = (codeword_id == 0) ? nof_layers_cw0 : nof_layers_cw1; - const bit_buffer& codeword = encode(*softbuffer, data[codeword_id], codeword_id, nof_layers_cw, nof_re_pdsch, pdu); + const bit_buffer& codeword = encode(*rm_buffer, data[codeword_id], codeword_id, nof_layers_cw, nof_re_pdsch, pdu); codewords.emplace_back(codeword); } @@ -86,7 +86,7 @@ unsigned pdsch_processor_impl::compute_nof_data_re(const pdu_t& pdu) return nof_grid_re - nof_reserved_re; } -const bit_buffer& pdsch_processor_impl::encode(tx_buffer& softbuffer, +const bit_buffer& pdsch_processor_impl::encode(tx_buffer& rm_buffer, span data, unsigned codeword_id, unsigned nof_layers, @@ -112,7 +112,7 @@ const bit_buffer& pdsch_processor_impl::encode(tx_buffer& softbuffer, span codeword = tmp_codeword.first(Nre * nof_layers * get_bits_per_symbol(modulation)); // Encode codeword. - encoder->encode(codeword, softbuffer, data, encoder_config); + encoder->encode(codeword, rm_buffer, data, encoder_config); // Pack encoded bits. temp_packed_codewords[codeword_id].resize(codeword.size()); diff --git a/lib/phy/upper/channel_processors/pdsch_processor_impl.h b/lib/phy/upper/channel_processors/pdsch_processor_impl.h index 73fa0bcada..bec450d355 100644 --- a/lib/phy/upper/channel_processors/pdsch_processor_impl.h +++ b/lib/phy/upper/channel_processors/pdsch_processor_impl.h @@ -35,7 +35,7 @@ class pdsch_processor_impl : public pdsch_processor // See interface for documentation. void process(resource_grid_mapper& mapper, - unique_tx_buffer softbuffer, + unique_tx_buffer rm_buffer, pdsch_processor_notifier& notifier, static_vector, MAX_NOF_TRANSPORT_BLOCKS> data, const pdu_t& pdu) override; @@ -51,13 +51,14 @@ class pdsch_processor_impl : public pdsch_processor /// \brief Encodes a codeword as per TS 38.212 section 7.2. /// - /// \param[in] data Provides the data to transmit as packed bits. - /// \param[in] codeword_id Indicates the codeword identifier. - /// \param[in] nof_layers Indicates the number of layers the codeword is mapped on to. - /// \param[in] Nre Indicates the number of resource elements used for PDSCH mapping. - /// \param[in] pdu Provides the PDSCH processor PDU. + /// \param[in,out] rm_buffer Rate matcher buffer. + /// \param[in] data Provides the data to transmit as packed bits. + /// \param[in] codeword_id Indicates the codeword identifier. + /// \param[in] nof_layers Indicates the number of layers the codeword is mapped on to. + /// \param[in] Nre Indicates the number of resource elements used for PDSCH mapping. + /// \param[in] pdu Provides the PDSCH processor PDU. /// \return A view of the encoded codeword. - const bit_buffer& encode(tx_buffer& softbuffer, + const bit_buffer& encode(tx_buffer& rm_buffer, span data, unsigned codeword_id, unsigned nof_layers, diff --git a/lib/phy/upper/channel_processors/pdsch_processor_lite_impl.cpp b/lib/phy/upper/channel_processors/pdsch_processor_lite_impl.cpp index af6d03bc3a..aee4b3f5f6 100644 --- a/lib/phy/upper/channel_processors/pdsch_processor_lite_impl.cpp +++ b/lib/phy/upper/channel_processors/pdsch_processor_lite_impl.cpp @@ -47,13 +47,13 @@ static unsigned compute_nof_data_re(const pdsch_processor::pdu_t& pdu) return nof_grid_re - nof_reserved_re; } -void pdsch_block_processor::configure_new_transmission(unique_tx_buffer softbuffer_, +void pdsch_block_processor::configure_new_transmission(unique_tx_buffer rm_buffer_, span data, unsigned i_cw, const pdsch_processor::pdu_t& pdu) { - new_data = pdu.codewords.front().new_data; - softbuffer = std::move(softbuffer_); + new_data = pdu.codewords.front().new_data; + unique_rm_buffer = std::move(rm_buffer_); // The number of layers is equal to the number of ports. unsigned nof_layers = pdu.precoding.get_nof_layers(); @@ -104,7 +104,8 @@ void pdsch_block_processor::new_codeblock() unsigned nof_symbols = rm_length / get_bits_per_symbol(modulation); // Resize internal buffer to match data from the encoder to the rate matcher (all segments have the same length). - bit_buffer rm_buffer = softbuffer.get().get_codeblock(next_i_cb, descr_seg.get_metadata().cb_specific.full_length); + bit_buffer rm_buffer = + unique_rm_buffer.get().get_codeblock(next_i_cb, descr_seg.get_metadata().cb_specific.full_length); // Encode only if it is a new transmission. if (new_data) { @@ -126,9 +127,9 @@ void pdsch_block_processor::new_codeblock() // Increment codeblock counter. ++next_i_cb; - // Unlock softbuffer if all the codeblocks have been processed. + // Unlock buffer if all the codeblocks have been processed. if (next_i_cb == d_segments.size()) { - softbuffer = unique_tx_buffer(); + unique_rm_buffer = unique_tx_buffer(); } } @@ -174,7 +175,7 @@ bool pdsch_block_processor::empty() const } void pdsch_processor_lite_impl::process(resource_grid_mapper& mapper, - unique_tx_buffer softbuffer, + unique_tx_buffer rm_buffer, pdsch_processor_notifier& notifier, static_vector, MAX_NOF_TRANSPORT_BLOCKS> data, const pdu_t& pdu) @@ -182,7 +183,7 @@ void pdsch_processor_lite_impl::process(resource_grid_mapper& pdsch_processor_validator_impl::assert_pdu(pdu); // Configure new transmission. - subprocessor.configure_new_transmission(std::move(softbuffer), data[0], 0, pdu); + subprocessor.configure_new_transmission(std::move(rm_buffer), data[0], 0, pdu); // Get the PRB allocation mask. const bounded_bitset prb_allocation_mask = pdu.freq_alloc.get_prb_mask(pdu.bwp_start_rb, pdu.bwp_size_rb); diff --git a/lib/phy/upper/channel_processors/pdsch_processor_lite_impl.h b/lib/phy/upper/channel_processors/pdsch_processor_lite_impl.h index 3ff3c5b8a3..b76dab8d98 100644 --- a/lib/phy/upper/channel_processors/pdsch_processor_lite_impl.h +++ b/lib/phy/upper/channel_processors/pdsch_processor_lite_impl.h @@ -38,11 +38,11 @@ class pdsch_block_processor : public resource_grid_mapper::symbol_buffer } /// \brief Configures a new transmission. - /// \param[in,out] softbuffer Rate matcher soft buffer. + /// \param[in,out] rm_buffer Rate matcher buffer. /// \param[in] data Transport block data. /// \param[in] i_cw Codeword index. /// \param[in] pdu PDSCH transmission parameters. - void configure_new_transmission(unique_tx_buffer softbuffer, + void configure_new_transmission(unique_tx_buffer rm_buffer, span data, unsigned i_cw, const pdsch_processor::pdu_t& pdu); @@ -85,7 +85,7 @@ class pdsch_block_processor : public resource_grid_mapper::symbol_buffer /// Temporary storage of codeblock symbols. std::array temp_codeblock_symbols; /// Rate matching soft buffer. - unique_tx_buffer softbuffer; + unique_tx_buffer unique_rm_buffer; /// Current view of the codeblock modulated symbols. span codeblock_symbols; @@ -119,7 +119,7 @@ class pdsch_processor_lite_impl : public pdsch_processor // See interface for documentation. void process(resource_grid_mapper& mapper, - unique_tx_buffer softbuffer, + unique_tx_buffer rm_buffer, pdsch_processor_notifier& notifier, static_vector, MAX_NOF_TRANSPORT_BLOCKS> data, const pdu_t& pdu) override; diff --git a/lib/phy/upper/channel_processors/pdsch_processor_pool.h b/lib/phy/upper/channel_processors/pdsch_processor_pool.h index bdce5bac45..f3fa06c5dd 100644 --- a/lib/phy/upper/channel_processors/pdsch_processor_pool.h +++ b/lib/phy/upper/channel_processors/pdsch_processor_pool.h @@ -45,7 +45,7 @@ class pdsch_processor_wrapper : private pdsch_processor, private pdsch_processor // See pdsch_processor interface for documentation. void process(resource_grid_mapper& mapper, - unique_tx_buffer softbuffer, + unique_tx_buffer rm_buffer, pdsch_processor_notifier& notifier_, static_vector, pdsch_processor::MAX_NOF_TRANSPORT_BLOCKS> data, const pdsch_processor::pdu_t& pdu) override @@ -54,7 +54,7 @@ class pdsch_processor_wrapper : private pdsch_processor, private pdsch_processor notifier = ¬ifier_; // Process. - processor->process(mapper, std::move(softbuffer), *this, data, pdu); + processor->process(mapper, std::move(rm_buffer), *this, data, pdu); } private: @@ -99,7 +99,7 @@ class pdsch_processor_pool : public pdsch_processor } void process(resource_grid_mapper& mapper, - unique_tx_buffer softbuffer, + unique_tx_buffer rm_buffer, pdsch_processor_notifier& notifier, static_vector, MAX_NOF_TRANSPORT_BLOCKS> data, const pdu_t& pdu) override @@ -115,7 +115,7 @@ class pdsch_processor_pool : public pdsch_processor } // Process PDSCH. - processors[index.value()].process(mapper, std::move(softbuffer), notifier, data, pdu); + processors[index.value()].process(mapper, std::move(rm_buffer), notifier, data, pdu); } private: diff --git a/lib/phy/upper/channel_processors/pusch/logging_pusch_processor_decorator.h b/lib/phy/upper/channel_processors/pusch/logging_pusch_processor_decorator.h index f1f3dad682..62fecbf7ae 100644 --- a/lib/phy/upper/channel_processors/pusch/logging_pusch_processor_decorator.h +++ b/lib/phy/upper/channel_processors/pusch/logging_pusch_processor_decorator.h @@ -12,7 +12,7 @@ #include "srsran/phy/support/support_formatters.h" #include "srsran/phy/upper/channel_processors/pusch/formatters.h" -#include "srsran/phy/upper/unique_rx_softbuffer.h" +#include "srsran/phy/upper/unique_rx_buffer.h" namespace fmt { @@ -74,7 +74,7 @@ class logging_pusch_processor_decorator : public pusch_processor, private pusch_ } void process(span data_, - unique_rx_softbuffer softbuffer, + unique_rx_buffer rm_buffer, pusch_processor_result_notifier& notifier_, const resource_grid_reader& grid, const pdu_t& pdu_) override @@ -90,7 +90,7 @@ class logging_pusch_processor_decorator : public pusch_processor, private pusch_ results.sch.reset(); results.uci.reset(); - processor->process(data, std::move(softbuffer), *this, grid, pdu); + processor->process(data, std::move(rm_buffer), *this, grid, pdu); time_return = std::chrono::steady_clock::now(); } diff --git a/lib/phy/upper/channel_processors/pusch/pusch_decoder_hw_impl.cpp b/lib/phy/upper/channel_processors/pusch/pusch_decoder_hw_impl.cpp index ad8be30b3c..0e176cdf9c 100644 --- a/lib/phy/upper/channel_processors/pusch/pusch_decoder_hw_impl.cpp +++ b/lib/phy/upper/channel_processors/pusch/pusch_decoder_hw_impl.cpp @@ -11,7 +11,7 @@ #include "pusch_decoder_hw_impl.h" #include "srsran/phy/upper/channel_processors/pusch/pusch_decoder_notifier.h" #include "srsran/phy/upper/channel_processors/pusch/pusch_decoder_result.h" -#include "srsran/phy/upper/rx_softbuffer.h" +#include "srsran/phy/upper/rx_buffer.h" #include "srsran/srsvec/bit.h" #include "srsran/srsvec/copy.h" #include "srsran/srsvec/zero.h" @@ -80,7 +80,7 @@ static std::tuple set_crc_type(unsigned nof_c } pusch_decoder_buffer& pusch_decoder_hw_impl::new_data(span transport_block_, - unique_rx_softbuffer softbuffer_, + unique_rx_buffer softbuffer_, pusch_decoder_notifier& notifier, const pusch_decoder::configuration& cfg) { diff --git a/lib/phy/upper/channel_processors/pusch/pusch_decoder_hw_impl.h b/lib/phy/upper/channel_processors/pusch/pusch_decoder_hw_impl.h index 1a71911fb1..b83eff6fb1 100644 --- a/lib/phy/upper/channel_processors/pusch/pusch_decoder_hw_impl.h +++ b/lib/phy/upper/channel_processors/pusch/pusch_decoder_hw_impl.h @@ -20,7 +20,7 @@ #include "srsran/phy/upper/channel_processors/pusch/pusch_decoder.h" #include "srsran/phy/upper/channel_processors/pusch/pusch_decoder_buffer.h" #include "srsran/phy/upper/codeblock_metadata.h" -#include "srsran/phy/upper/unique_rx_softbuffer.h" +#include "srsran/phy/upper/unique_rx_buffer.h" #include "srsran/ran/pdsch/pdsch_constants.h" namespace srsran { @@ -77,7 +77,7 @@ class pusch_decoder_hw_impl : public pusch_decoder, private pusch_decoder_buffer // See interface for the documentation. pusch_decoder_buffer& new_data(span transport_block, - unique_rx_softbuffer softbuffer, + unique_rx_buffer softbuffer, pusch_decoder_notifier& notifier, const configuration& cfg) override; @@ -98,7 +98,7 @@ class pusch_decoder_hw_impl : public pusch_decoder, private pusch_decoder_buffer /// Current transport block. span transport_block; /// Current soft bits buffer. - unique_rx_softbuffer softbuffer; + unique_rx_buffer softbuffer; /// Current notifier. pusch_decoder_notifier* result_notifier = nullptr; /// Current PUSCH decoder configuration. 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 11a4d4b026..62f4687263 100644 --- a/lib/phy/upper/channel_processors/pusch/pusch_decoder_impl.cpp +++ b/lib/phy/upper/channel_processors/pusch/pusch_decoder_impl.cpp @@ -12,7 +12,7 @@ #include "srsran/instrumentation/traces/du_traces.h" #include "srsran/phy/upper/channel_processors/pusch/pusch_decoder_notifier.h" #include "srsran/phy/upper/channel_processors/pusch/pusch_decoder_result.h" -#include "srsran/phy/upper/rx_softbuffer.h" +#include "srsran/phy/upper/rx_buffer.h" #include "srsran/srsvec/bit.h" #include "srsran/srsvec/copy.h" #include "srsran/srsvec/zero.h" @@ -56,15 +56,15 @@ static std::tuple get_cblk_bit_breakdown(const cod } pusch_decoder_buffer& pusch_decoder_impl::new_data(span transport_block_, - unique_rx_softbuffer softbuffer_, + unique_rx_buffer unique_rm_buffer_, pusch_decoder_notifier& notifier, const pusch_decoder::configuration& cfg) { - transport_block = transport_block_; - softbuffer = std::move(softbuffer_); - result_notifier = ¬ifier; - current_config = cfg; - softbits_count = 0; + transport_block = transport_block_; + unique_rm_buffer = std::move(unique_rm_buffer_); + result_notifier = ¬ifier; + current_config = cfg; + softbits_count = 0; return *this; } @@ -118,16 +118,16 @@ void pusch_decoder_impl::on_end_softbits() segmenter->segment(codeblock_llrs, llrs, tb_size, segmentation_config); unsigned nof_cbs = codeblock_llrs.size(); - srsran_assert(nof_cbs == softbuffer->get_nof_codeblocks(), + srsran_assert(nof_cbs == unique_rm_buffer->get_nof_codeblocks(), "Wrong number of codeblocks {} (expected {}).", - softbuffer->get_nof_codeblocks(), + unique_rm_buffer->get_nof_codeblocks(), nof_cbs); // Select CRC calculator for inner codeblock checks. crc_calculator* block_crc = select_crc(crc_set, tb_size, nof_cbs); // Reset CRCs if new data is flagged. - span cb_crcs = softbuffer->get_codeblocks_crc(); + span cb_crcs = unique_rm_buffer->get_codeblocks_crc(); if (current_config.new_data) { srsvec::zero(cb_crcs); } @@ -147,12 +147,12 @@ void pusch_decoder_impl::on_end_softbits() std::tie(cb_length, msg_length, nof_data_bits) = get_cblk_bit_breakdown(cb_meta); // Get data bits from previous transmissions, if any. - // Messages are written on a dedicated buffer associated to the softbuffer. By doing this, we keep the decoded - // message in memory and we don't need to compute it again if there is a retransmission. - bit_buffer message = softbuffer->get_codeblock_data_bits(cb_id, msg_length); + // Messages are written on a dedicated buffer associated to the buffer. By doing this, we keep the decoded message + // in memory and we don't need to compute it again if there is a retransmission. + bit_buffer message = unique_rm_buffer->get_codeblock_data_bits(cb_id, msg_length); // Get the LLRs from previous transmissions, if any, or a clean buffer. - span rm_buffer = softbuffer->get_codeblock_soft_bits(cb_id, cb_length); + span rm_buffer = unique_rm_buffer->get_codeblock_soft_bits(cb_id, cb_length); // Code block processing task. auto cb_process_task = [this, cb_meta, rm_buffer, cb_llrs, &cb_crc = cb_crcs[cb_id], block_crc, message]() { @@ -212,7 +212,7 @@ void pusch_decoder_impl::on_end_softbits() void pusch_decoder_impl::join_and_notify() { unsigned nof_cbs = codeblock_llrs.size(); - span cb_crcs = softbuffer->get_codeblocks_crc(); + span cb_crcs = unique_rm_buffer->get_codeblocks_crc(); // Initialize decoder status. pusch_decoder_result stats; @@ -233,7 +233,7 @@ void pusch_decoder_impl::join_and_notify() // Copy the code block only nif the CRC is OK. if (stats.tb_crc_ok) { - const bit_buffer cb_data = softbuffer->get_codeblock_data_bits(0, transport_block.size() * BITS_PER_BYTE); + const bit_buffer cb_data = unique_rm_buffer->get_codeblock_data_bits(0, transport_block.size() * BITS_PER_BYTE); srsvec::copy(transport_block, cb_data.get_buffer()); } } else if (std::all_of(cb_crcs.begin(), cb_crcs.end(), [](bool a) { return a; })) { @@ -246,15 +246,15 @@ void pusch_decoder_impl::join_and_notify() stats.tb_crc_ok = true; } else { // If the checksum is wrong, then at least one of the codeblocks is a false negative. Reset all of them. - softbuffer->reset_codeblocks_crc(); + unique_rm_buffer->reset_codeblocks_crc(); } } // Release soft buffer if the CRC is OK, otherwise unlock. if (stats.tb_crc_ok) { - softbuffer.release(); + unique_rm_buffer.release(); } else { - softbuffer.unlock(); + unique_rm_buffer.unlock(); } // In case there are multiple codeblocks and at least one has a corrupted codeblock CRC, nothing to do. @@ -289,7 +289,7 @@ unsigned pusch_decoder_impl::concatenate_codeblocks() unsigned nof_new_bits = std::min(free_tb_bits, nof_data_bits); // Get code block data from the buffer. - bit_buffer cb_data = softbuffer->get_codeblock_data_bits(cb_id, nof_data_bits); + bit_buffer cb_data = unique_rm_buffer->get_codeblock_data_bits(cb_id, nof_data_bits); // Copy the decoded code block into the transport block buffer. srsvec::copy_offset(tb_data, tb_offset, cb_data, 0, nof_new_bits); 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 04665313be..269808299d 100644 --- a/lib/phy/upper/channel_processors/pusch/pusch_decoder_impl.h +++ b/lib/phy/upper/channel_processors/pusch/pusch_decoder_impl.h @@ -14,7 +14,7 @@ #include "srsran/adt/concurrent_queue.h" #include "srsran/phy/upper/channel_processors/pusch/pusch_decoder.h" #include "srsran/phy/upper/channel_processors/pusch/pusch_decoder_buffer.h" -#include "srsran/phy/upper/unique_rx_softbuffer.h" +#include "srsran/phy/upper/unique_rx_buffer.h" #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" @@ -82,7 +82,7 @@ class pusch_decoder_impl : public pusch_decoder, private pusch_decoder_buffer // See interface for the documentation. pusch_decoder_buffer& new_data(span transport_block, - unique_rx_softbuffer softbuffer, + unique_rx_buffer rm_buffer, pusch_decoder_notifier& notifier, const configuration& cfg) override; @@ -106,7 +106,7 @@ class pusch_decoder_impl : public pusch_decoder, private pusch_decoder_buffer /// Current transport block. span transport_block; /// Current soft bits buffer. - unique_rx_softbuffer softbuffer; + unique_rx_buffer unique_rm_buffer; /// Current notifier. pusch_decoder_notifier* result_notifier = nullptr; /// Current PUSCH decoder configuration. diff --git a/lib/phy/upper/channel_processors/pusch/pusch_processor_impl.cpp b/lib/phy/upper/channel_processors/pusch/pusch_processor_impl.cpp index 9aec8e4ece..bcbf2ef3b3 100644 --- a/lib/phy/upper/channel_processors/pusch/pusch_processor_impl.cpp +++ b/lib/phy/upper/channel_processors/pusch/pusch_processor_impl.cpp @@ -13,7 +13,7 @@ #include "pusch_processor_notifier_adaptor.h" #include "srsran/phy/upper/channel_processors/pusch/pusch_codeword_buffer.h" #include "srsran/phy/upper/channel_processors/pusch/pusch_decoder_buffer.h" -#include "srsran/phy/upper/unique_rx_softbuffer.h" +#include "srsran/phy/upper/unique_rx_buffer.h" #include "srsran/ran/pusch/ulsch_info.h" #include "srsran/ran/sch_dmrs_power.h" #include "srsran/ran/uci/uci_formatters.h" @@ -183,7 +183,7 @@ pusch_processor_impl::pusch_processor_impl(configuration& config) : } void pusch_processor_impl::process(span data, - unique_rx_softbuffer softbuffer, + unique_rx_buffer rm_buffer, pusch_processor_result_notifier& notifier, const resource_grid_reader& grid, const pusch_processor::pdu_t& pdu) @@ -311,7 +311,7 @@ void pusch_processor_impl::process(span data, // Setup decoder. decoder_buffer = - decoder->new_data(data, std::move(softbuffer), notifier_adaptor.get_sch_data_notifier(), decoder_config); + decoder->new_data(data, std::move(rm_buffer), notifier_adaptor.get_sch_data_notifier(), decoder_config); } // Prepares HARQ-ACK notifier and buffer. diff --git a/lib/phy/upper/channel_processors/pusch/pusch_processor_impl.h b/lib/phy/upper/channel_processors/pusch/pusch_processor_impl.h index 80328ddeec..a746da17ec 100644 --- a/lib/phy/upper/channel_processors/pusch/pusch_processor_impl.h +++ b/lib/phy/upper/channel_processors/pusch/pusch_processor_impl.h @@ -19,7 +19,7 @@ #include "srsran/phy/upper/channel_processors/pusch/ulsch_demultiplex.h" #include "srsran/phy/upper/channel_processors/uci/uci_decoder.h" #include "srsran/phy/upper/signal_processors/dmrs_pusch_estimator.h" -#include "srsran/phy/upper/unique_rx_softbuffer.h" +#include "srsran/phy/upper/unique_rx_buffer.h" #include "srsran/ran/pusch/ulsch_info.h" #include "srsran/support/memory_pool/concurrent_thread_local_object_pool.h" #include @@ -133,7 +133,7 @@ class pusch_processor_impl : public pusch_processor // See interface for documentation. void process(span data, - unique_rx_softbuffer softbuffer, + unique_rx_buffer rm_buffer, pusch_processor_result_notifier& notifier, const resource_grid_reader& grid, const pdu_t& pdu) override; diff --git a/lib/phy/upper/channel_processors/pusch/pusch_processor_logging_decorator.h b/lib/phy/upper/channel_processors/pusch/pusch_processor_logging_decorator.h deleted file mode 100644 index 8de0a16c37..0000000000 --- a/lib/phy/upper/channel_processors/pusch/pusch_processor_logging_decorator.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * - * 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 "pusch_codeblock_decoder.h" -#include "pusch_decoder_impl.h" -#include "pusch_demodulator_impl.h" -#include "pusch_processor_impl.h" -#include "pusch_processor_logging_decorator.h" -#include "pusch_processor_pool.h" -#include "ulsch_demultiplex_impl.h" -#include "srsran/phy/support/support_formatters.h" -#include "srsran/phy/upper/channel_processors/channel_processor_formatters.h" -#include "srsran/phy/upper/channel_processors/pusch/formatters.h" -#include "srsran/phy/upper/channel_processors/pusch/pusch_processor_result_notifier.h" -#include "srsran/support/format_utils.h" - -namespace fmt { - -struct pusch_results_wrapper { - srsran::optional uci; - srsran::optional sch; -}; - -/// \brief Custom formatter for \c pusch_results_wrapper. -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 pusch_results_wrapper& result, FormatContext& ctx) -> decltype(std::declval().out()) - { - // Format SCH message. - if (result.sch.has_value()) { - helper.format_always(ctx, result.sch.value()); - } - - // Format UCI message. - if (result.uci.has_value()) { - helper.format_always(ctx, result.uci.value()); - } - - // Format channel state information. - if (result.sch.has_value()) { - helper.format_always(ctx, result.sch.value().csi); - } else if (result.uci.has_value()) { - helper.format_always(ctx, result.uci.value().csi); - } - - return ctx.out(); - } -}; - -} // namespace fmt - -namespace srsran { - -class pusch_processor_logging_decorator : public pusch_processor, private pusch_processor_result_notifier -{ -public: - pusch_processor_logging_decorator(srslog::basic_logger& logger_, std::unique_ptr processor_) : - logger(logger_), processor(std::move(processor_)) - { - srsran_assert(processor, "Invalid processor."); - } - - void process(span data_, - unique_rx_softbuffer softbuffer, - pusch_processor_result_notifier& notifier_, - const resource_grid_reader& grid, - const pdu_t& pdu_) override - { - notifier = ¬ifier_; - data = data_; - pdu = pdu_; - time_start = std::chrono::steady_clock::now(); - time_uci = std::chrono::time_point(); - time_return = std::chrono::time_point(); - results = {}; - - processor->process(data, std::move(softbuffer), *this, grid, pdu); - time_return = std::chrono::steady_clock::now(); - } - -private: - void on_uci(const pusch_processor_result_control& uci) override - { - srsran_assert(notifier, "Invalid notifier"); - time_uci = std::chrono::steady_clock::now(); - results.uci = uci; - notifier->on_uci(uci); - } - - void on_sch(const pusch_processor_result_data& sch) override - { - srsran_assert(notifier, "Invalid notifier"); - - // Data size in bytes for printing hex dump only if SCH is present and CRC is passed. - unsigned data_size = 0; - if (results.sch.has_value() && results.sch->data.tb_crc_ok) { - data_size = data.size(); - } - - // Save SCH results. - results.sch = sch; - - std::chrono::time_point time_end = std::chrono::steady_clock::now(); - - // Calculate the UCI report latency if available. - std::chrono::nanoseconds time_uci_ns = {}; - if (time_uci != std::chrono::time_point()) { - time_uci_ns = time_uci - time_start; - } - - // Calculate the return latency if available. - std::chrono::nanoseconds time_return_ns = {}; - if (time_return != std::chrono::time_point()) { - time_return_ns = time_return - time_start; - } - - // Calculate the final time. - std::chrono::nanoseconds time_ns = time_end - time_start; - - if (logger.debug.enabled()) { - // Detailed log information, including a list of all PDU fields. - logger.debug(data.data(), - data_size, - "PUSCH: {:s} tbs={} {:s} {} uci_{} ret_{}\n {:n}\n {:n}", - pdu, - data.size(), - results, - time_ns, - time_uci_ns, - time_return_ns, - pdu, - results); - } else { - // Single line log entry. - logger.info(data.data(), - data_size, - "PUSCH: {:s} tbs={} {:s} {} uci_{} ret_{}", - pdu, - data.size(), - results, - time_ns, - time_uci_ns, - time_return_ns); - } - - // Exchanges the notifier before notifying the reception of SCH. - pusch_processor_result_notifier* notifier_ = nullptr; - std::exchange(notifier_, notifier); - - // Notify the SCH reception. - notifier_->on_sch(sch); - } - - srslog::basic_logger& logger; - std::unique_ptr processor; - span data; - pdu_t pdu; - pusch_processor_result_notifier* notifier; - std::chrono::time_point time_start; - std::chrono::time_point time_uci; - std::chrono::time_point time_return; - fmt::pusch_results_wrapper results; -}; - -} // namespace srsran 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 2c9360bf45..e7048978bb 100644 --- a/lib/phy/upper/channel_processors/pusch/pusch_processor_pool.h +++ b/lib/phy/upper/channel_processors/pusch/pusch_processor_pool.h @@ -45,7 +45,7 @@ class pusch_processor_wrapper : public pusch_processor, private pusch_processor_ // See pusch_processor interface for documentation. void process(span data, - unique_rx_softbuffer softbuffer, + unique_rx_buffer rm_buffer, pusch_processor_result_notifier& notifier_, const resource_grid_reader& grid, const pdu_t& pdu) override @@ -54,7 +54,7 @@ class pusch_processor_wrapper : public pusch_processor, private pusch_processor_ notifier = ¬ifier_; // Process. - processor->process(data, std::move(softbuffer), *this, grid, pdu); + processor->process(data, std::move(rm_buffer), *this, grid, pdu); } private: @@ -108,7 +108,7 @@ class pusch_processor_pool : public pusch_processor // See interface for documentation. void process(span data, - unique_rx_softbuffer softbuffer, + unique_rx_buffer rm_buffer, pusch_processor_result_notifier& notifier, const resource_grid_reader& grid, const pdu_t& pdu) override @@ -123,7 +123,7 @@ class pusch_processor_pool : public pusch_processor } // Process pusch. - processors[index.value()].process(data, std::move(softbuffer), notifier, grid, pdu); + processors[index.value()].process(data, std::move(rm_buffer), notifier, grid, pdu); } private: diff --git a/lib/phy/upper/downlink_processor_single_executor_impl.cpp b/lib/phy/upper/downlink_processor_single_executor_impl.cpp index 9e72e36145..3f87d5bcdd 100644 --- a/lib/phy/upper/downlink_processor_single_executor_impl.cpp +++ b/lib/phy/upper/downlink_processor_single_executor_impl.cpp @@ -85,7 +85,7 @@ void downlink_processor_single_executor_impl::process_pdcch(const pdcch_processo } void downlink_processor_single_executor_impl::process_pdsch( - unique_tx_buffer softbuffer, + unique_tx_buffer rm_buffer, const static_vector, pdsch_processor::MAX_NOF_TRANSPORT_BLOCKS>& data, const pdsch_processor::pdu_t& pdu) { @@ -104,7 +104,7 @@ void downlink_processor_single_executor_impl::process_pdsch( } // Try to enqueue the PDU processing task. - bool enqueued = executor.execute([this, sb = std::move(softbuffer), data, pdu]() mutable { + bool enqueued = executor.execute([this, sb = std::move(rm_buffer), data, pdu]() mutable { trace_point process_pdsch_tp = l1_tracer.now(); // Do not execute if the grid is not available. diff --git a/lib/phy/upper/downlink_processor_single_executor_impl.h b/lib/phy/upper/downlink_processor_single_executor_impl.h index f49de24b6b..a0d6f6c45f 100644 --- a/lib/phy/upper/downlink_processor_single_executor_impl.h +++ b/lib/phy/upper/downlink_processor_single_executor_impl.h @@ -75,7 +75,7 @@ class downlink_processor_single_executor_impl : public downlink_processor, priva void process_pdcch(const pdcch_processor::pdu_t& pdu) override; // See interface for documentation. - void process_pdsch(unique_tx_buffer softbuffer, + void process_pdsch(unique_tx_buffer rm_buffer, const static_vector, pdsch_processor::MAX_NOF_TRANSPORT_BLOCKS>& data, const pdsch_processor::pdu_t& pdu) override; diff --git a/lib/phy/upper/rx_softbuffer_codeblock_pool.h b/lib/phy/upper/rx_buffer_codeblock_pool.h similarity index 59% rename from lib/phy/upper/rx_softbuffer_codeblock_pool.h rename to lib/phy/upper/rx_buffer_codeblock_pool.h index 3af9cb32da..1e29b8ddcd 100644 --- a/lib/phy/upper/rx_softbuffer_codeblock_pool.h +++ b/lib/phy/upper/rx_buffer_codeblock_pool.h @@ -9,24 +9,29 @@ */ #pragma once -#include "rx_softbuffer_impl.h" -#include "srsran/adt/static_vector.h" -#include "srsran/phy/upper/codeblock_metadata.h" -#include "srsran/phy/upper/rx_softbuffer_pool.h" -#include "srsran/phy/upper/unique_rx_softbuffer.h" -#include "srsran/support/error_handling.h" + +#include "srsran/adt/bit_buffer.h" +#include "srsran/adt/concurrent_queue.h" +#include "srsran/adt/optional.h" +#include "srsran/adt/span.h" +#include "srsran/phy/upper/log_likelihood_ratio.h" #include "srsran/support/math_utils.h" +#include "srsran/support/srsran_assert.h" +#include +#include namespace srsran { /// Manages a codeblock buffer pool. -class rx_softbuffer_codeblock_pool +class rx_buffer_codeblock_pool { private: + /// Codeblock identifier list type. + using codeblock_identifier_list = + concurrent_queue; + /// Describes a codeblock buffer entry. struct entry { - /// Indicates if the entry is reserved. - bool reserved; /// Contains the codeblock soft bits. std::vector soft_bits; /// Contains the codeblock data bits. @@ -35,53 +40,45 @@ class rx_softbuffer_codeblock_pool /// Stores all codeblock entries. std::vector entries; + /// List containing the free codeblocks identifiers. + codeblock_identifier_list free_list; public: - /// Default CB identifier for unreserved codeblocks. - static constexpr unsigned UNRESERVED_CB_ID = UINT32_MAX; - /// \brief Creates a receive buffer codeblock pool. /// \param[in] nof_codeblocks Indicates the maximum number of codeblocks. /// \param[in] max_codeblock_size Indicates the maximum codeblock size. /// \param[in] external_soft_bits Set to true to indicate that soft bits are not stored in the buffer. - rx_softbuffer_codeblock_pool(unsigned nof_codeblocks, unsigned max_codeblock_size, bool external_soft_bits) + rx_buffer_codeblock_pool(unsigned nof_codeblocks, unsigned max_codeblock_size, bool external_soft_bits) : + free_list(nof_codeblocks) { entries.resize(nof_codeblocks); + unsigned cb_id = 0; for (entry& e : entries) { - e.reserved = false; e.soft_bits.resize(external_soft_bits ? 0 : max_codeblock_size); // The maximum number of data bits is // max_codeblock_size * max(BG coding rate) = max_codeblock_size * (1/3) e.data_bits.resize(divide_ceil(max_codeblock_size, 3)); + // Push codeblock identifier into the free list. + while (!free_list.try_push(cb_id++)) { + } } } - /// \brief Reserves a codeblock softbuffer. - /// \return The codeblock identifier in the pool if it is reserved successfully. Otherwise, \c UNRESERVED_CB_ID - unsigned reserve() + /// \brief Reserves a codeblock buffer. + /// \return The codeblock identifier in the pool if it is reserved successfully. Otherwise, \c nullopt + optional reserve() { - // Find the first available codeblock. - for (unsigned cb_id = 0; cb_id != entries.size(); ++cb_id) { - if (!entries[cb_id].reserved) { - entries[cb_id].reserved = true; - return cb_id; - } - } - return UNRESERVED_CB_ID; + // Try to get an available codeblock. + return free_list.try_pop(); } - /// \brief Frees a codeblock softbuffer. + /// \brief Frees a codeblock buffer. /// \param[in] cb_id Indicates the codeblock identifier in the pool. void free(unsigned cb_id) { - // Skip if the codeblock identifier is equal to the unreserved identifier. - if (cb_id == UNRESERVED_CB_ID) { - return; + // Push codeblock identifier back in the pool. + while (!free_list.try_push(cb_id)) { } - - srsran_assert(cb_id < entries.size(), "Codeblock index ({}) is out of range ({}).", cb_id, entries.size()); - srsran_assert(entries[cb_id].reserved, "Codeblock index ({}) is not reserved.", cb_id); - entries[cb_id].reserved = false; } /// \brief Gets a codeblock soft-bit buffer. @@ -90,7 +87,6 @@ class rx_softbuffer_codeblock_pool span get_soft_bits(unsigned cb_id) { srsran_assert(cb_id < entries.size(), "Codeblock index ({}) is out of range ({}).", cb_id, entries.size()); - srsran_assert(entries[cb_id].reserved, "Codeblock index ({}) is not reserved.", cb_id); return entries[cb_id].soft_bits; } @@ -100,7 +96,6 @@ class rx_softbuffer_codeblock_pool bit_buffer& get_data_bits(unsigned cb_id) { srsran_assert(cb_id < entries.size(), "Codeblock index ({}) is out of range ({}).", cb_id, entries.size()); - srsran_assert(entries[cb_id].reserved, "Codeblock index ({}) is not reserved.", cb_id); return entries[cb_id].data_bits; } }; diff --git a/lib/phy/upper/rx_buffer_impl.h b/lib/phy/upper/rx_buffer_impl.h new file mode 100644 index 0000000000..35fe61ce27 --- /dev/null +++ b/lib/phy/upper/rx_buffer_impl.h @@ -0,0 +1,247 @@ +/* + * + * 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 "rx_buffer_codeblock_pool.h" +#include "srsran/adt/bit_buffer.h" +#include "srsran/adt/optional.h" +#include "srsran/adt/span.h" +#include "srsran/adt/static_vector.h" +#include "srsran/phy/upper/log_likelihood_ratio.h" +#include "srsran/phy/upper/rx_buffer_pool.h" +#include "srsran/phy/upper/unique_rx_buffer.h" +#include "srsran/ran/sch/sch_constants.h" +#include "srsran/support/srsran_assert.h" +#include +#include + +namespace srsran { + +enum class rx_buffer_status : uint8_t { successful = 0, already_in_use, insufficient_cb }; + +/// Implements a receiver buffer interface. +class rx_buffer_impl : public unique_rx_buffer::callback +{ +private: + /// Internal buffer states. + enum class state : uint8_t { + /// \brief The buffer has not been configured with any codeblock. + /// + /// It is available for being reserved. + available, + /// \brief The buffer is reserved with a number of codeblocks. + /// + /// It allows: + /// -\c expire: called when the buffer context has expired, it transitions to \c available. + /// -\c reserve: makes a new reservation. + reserved, + /// \brief The buffer is reserved and locked in a context. It does not accept new reservations or retransmissions, + /// and prevents the buffer from expiring. + /// + /// It allows: + /// - \c unlock: a transmission did not match the CRC, it transitions to \c reserved; and + /// - \c release: a transmission matched the CRC and the buffer releases all its resources, it transitions to \c + /// available. + locked + }; + + /// Current buffer state. + std::atomic current_state = {state::available}; + /// Reference to the codeblock pool. + rx_buffer_codeblock_pool& codeblock_pool; + /// Stores codeblocks CRCs. + static_vector crc; + /// Stores codeblock identifiers. + static_vector codeblock_ids; + + /// Frees reserved codeblocks. The codeblocks are returned to the pool. + void free() + { + // Free all codeblocks. + for (unsigned cb_id : codeblock_ids) { + codeblock_pool.free(cb_id); + } + + // Indicate the buffer is available by clearing the codeblocks identifiers. + codeblock_ids.clear(); + } + +public: + /// \brief Creates a receive buffer. + /// \param pool Codeblock buffer pool. + explicit rx_buffer_impl(rx_buffer_codeblock_pool& pool) : codeblock_pool(pool) + { + // Do nothing. + } + + /// Copy constructor - creates another buffer with the same codeblock pool. + rx_buffer_impl(const rx_buffer_impl& other) noexcept : codeblock_pool(other.codeblock_pool) {} + + /// Move constructor - creates another buffer with the same codeblock pool. + rx_buffer_impl(rx_buffer_impl&& other) noexcept : codeblock_pool(other.codeblock_pool) {} + + /// \brief Reserves a number of codeblocks from the pool. + /// + /// It optionally resets the CRCs. + /// + /// \param nof_codeblocks Number of codeblocks to reserve. + /// \param reset_crc Set to true for reset the codeblock CRCs. + /// \return The reservation status. + rx_buffer_status reserve(unsigned nof_codeblocks, bool reset_crc) + { + // It cannot reserve resources if it is locked. + if (current_state.load() == state::locked) { + return rx_buffer_status::already_in_use; + } + + // If the current number of codeblocks is larger than required, free the excess of codeblocks. + while (codeblock_ids.size() > nof_codeblocks) { + // Get the codeblock identifier at the back and remove from the list. + unsigned cb_id = codeblock_ids.back(); + codeblock_ids.pop_back(); + + // Free the codeblock. + codeblock_pool.free(cb_id); + } + + // If the current number of codeblocks is less than required, reserve the remaining codeblocks. + while (codeblock_ids.size() < nof_codeblocks) { + // Reserve codeblock. + optional cb_id = codeblock_pool.reserve(); + + // Free the entire buffer if one codeblock cannot be reserved. + if (!cb_id.has_value()) { + free(); + current_state = state::available; + return rx_buffer_status::insufficient_cb; + } + + // Append the codeblock identifier to the list. + codeblock_ids.push_back(cb_id.value()); + } + + // Resize CRCs. + crc.resize(nof_codeblocks); + + // Reset CRCs if necessary. + if (reset_crc) { + reset_codeblocks_crc(); + } + current_state = state::reserved; + + return rx_buffer_status::successful; + } + + // See interface for documentation. + unsigned get_nof_codeblocks() const override { return crc.size(); } + + // See interface for documentation. + void reset_codeblocks_crc() override + { + // Set all codeblock CRC to false. + for (bool& cb_crc : crc) { + cb_crc = false; + } + } + + // See interface for documentation. + span get_codeblocks_crc() override { return crc; } + + // See interface for documentation. + unsigned get_absolute_codeblock_id(unsigned codeblock_id) const override + { + srsran_assert(codeblock_id < codeblock_ids.size(), + "Codeblock index ({}) is out of range ({}).", + codeblock_id, + codeblock_ids.size()); + return codeblock_ids[codeblock_id]; + } + + // See interface for documentation. + span get_codeblock_soft_bits(unsigned codeblock_id, unsigned codeblock_size) override + { + srsran_assert(codeblock_id < codeblock_ids.size(), + "Codeblock index ({}) is out of range ({}).", + codeblock_id, + codeblock_ids.size()); + unsigned cb_id = codeblock_ids[codeblock_id]; + unsigned cb_max_size = codeblock_pool.get_soft_bits(cb_id).size(); + srsran_assert( + codeblock_size <= cb_max_size, "Codeblock size {} exceeds maximum size {}.", codeblock_size, cb_max_size); + return codeblock_pool.get_soft_bits(cb_id).first(codeblock_size); + } + + // See interface for documentation. + bit_buffer get_codeblock_data_bits(unsigned codeblock_id, unsigned data_size) override + { + srsran_assert(codeblock_id < codeblock_ids.size(), + "Codeblock index ({}) is out of range ({}).", + codeblock_id, + codeblock_ids.size()); + unsigned cb_id = codeblock_ids[codeblock_id]; + unsigned data_max_size = codeblock_pool.get_data_bits(cb_id).size(); + srsran_assert( + data_size <= data_max_size, "Codeblock data size {} exceeds maximum size {}.", data_size, data_max_size); + return codeblock_pool.get_data_bits(cb_id).first(data_size); + } + + // See interface for documentation. + void lock() override + { + state previous_state = current_state.exchange(state::locked); + srsran_assert(previous_state == state::reserved, "Failed to lock. Invalid state."); + } + + // See interface for documentation. + void unlock() override + { + state previous_state = current_state.exchange(state::reserved); + srsran_assert(previous_state == state::locked, "Failed to unlock. Invalid state."); + } + + // See interface for documentation. + void release() override + { + // Release all reserved codeblocks. + free(); + + // The buffer can now be reused again. + state previous_state = current_state.exchange(state::available); + srsran_assert(previous_state == state::locked, "Failed to release. Invalid state."); + } + + /// Returns true if the buffer is free. + bool is_free() const { return current_state == state::available; } + + /// \brief Expires the buffer. + /// + /// The buffer pool shall use this method when the buffer expires. The buffer frees the reserved codeblocks if it is + /// not blocked. + /// + /// \return \c true if the buffer is not locked. + bool expire() + { + state expected_state = state::reserved; + bool from_reserved = current_state.compare_exchange_weak(expected_state, state::available); + + // The buffer cannot be freed if it is locked. + if (!from_reserved) { + return false; + } + + // Release resources. + free(); + + return true; + } +}; + +} // namespace srsran diff --git a/lib/phy/upper/rx_buffer_pool_impl.cpp b/lib/phy/upper/rx_buffer_pool_impl.cpp new file mode 100644 index 0000000000..f74b5d619e --- /dev/null +++ b/lib/phy/upper/rx_buffer_pool_impl.cpp @@ -0,0 +1,114 @@ +/* + * + * 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 "rx_buffer_pool_impl.h" +#include "rx_buffer_impl.h" +#include "srsran/phy/upper/rx_buffer_pool.h" +#include "srsran/phy/upper/unique_rx_buffer.h" +#include "srsran/ran/slot_point.h" +#include +#include + +using namespace srsran; + +unique_rx_buffer rx_buffer_pool_impl::reserve(const slot_point& slot, trx_buffer_identifier id, unsigned nof_codeblocks) +{ + // Try to find the HARQ identifier. + auto id_found = std::find(identifiers.begin(), identifiers.end(), id); + + // Find an available buffer if no buffer was found with the same identifier. + if (id_found == identifiers.end()) { + id_found = std::find(identifiers.begin(), identifiers.end(), trx_buffer_identifier::invalid()); + } + + // Report warning and return invalid buffer if no available buffer has been found. + if (id_found == identifiers.end()) { + logger.warning( + slot.sfn(), slot.slot_index(), "UL HARQ {}: failed to reserve, insufficient buffers in the pool.", id); + return unique_rx_buffer(); + } + + // Get buffer index within the pool. + unsigned i_buffer = id_found - identifiers.begin(); + + // Get reference to the buffer. + rx_buffer_impl& buffer = buffers[i_buffer]; + + // Reset CRCs if one of the following conditions holds: + // - The reservation identifier changed; + // - The buffer is available; or + // - The number of codeblocks changed. + bool reset_crc = (identifiers[i_buffer] != id) || buffer.is_free() || (buffer.get_nof_codeblocks() != nof_codeblocks); + + // Reserve codeblocks. + rx_buffer_status status = buffer.reserve(nof_codeblocks, reset_crc); + + // Report warning and return invalid buffer if the reservation is not successful. + if (status != rx_buffer_status::successful) { + logger.warning(slot.sfn(), + slot.slot_index(), + "UL HARQ {}: failed to reserve, {}.", + id, + (status == rx_buffer_status::already_in_use) ? "HARQ already in use" : "insufficient CBs"); + return unique_rx_buffer(); + } + + // Update identifier and expiration. + identifiers[i_buffer] = id; + expirations[i_buffer] = slot + expire_timeout_slots; + + // Create buffer. + return unique_rx_buffer(buffer); +} + +void rx_buffer_pool_impl::run_slot(const slot_point& slot) +{ + // Predicate for finding available buffers. + auto pred = [](trx_buffer_identifier id) { return id != trx_buffer_identifier::invalid(); }; + + // Iterate over all the buffers that are currently reserved. + for (auto it = std::find_if(identifiers.begin(), identifiers.end(), pred); it != identifiers.end(); + it = std::find_if(++it, identifiers.end(), pred)) { + // Calculate buffer index. + unsigned i_buffer = it - identifiers.begin(); + + // Get reference to the buffer. + rx_buffer_impl& buffer = buffers[i_buffer]; + + // Determines whether the buffer is free. + bool is_free = false; + + // A buffer is expired if the expiration slot is lower than or equal to the current slot. + if ((expirations[i_buffer] != null_expiration) && (expirations[i_buffer] <= slot)) { + // Try to expire the buffer. + is_free = buffer.expire(); + + // If the buffer is not available, increase the expiration time and continue to the next buffer. + if (!is_free) { + expirations[i_buffer] = slot + expire_timeout_slots; + continue; + } + } else { + // Check if the buffer is free before expiring. + is_free = buffer.is_free(); + } + + // Clear identifier and expiration. + if (is_free) { + identifiers[i_buffer] = trx_buffer_identifier::invalid(); + expirations[i_buffer] = null_expiration; + } + } +} + +std::unique_ptr srsran::create_rx_buffer_pool(const rx_buffer_pool_config& config) +{ + return std::make_unique(config); +} diff --git a/lib/phy/upper/rx_buffer_pool_impl.h b/lib/phy/upper/rx_buffer_pool_impl.h new file mode 100644 index 0000000000..206ba3fd3b --- /dev/null +++ b/lib/phy/upper/rx_buffer_pool_impl.h @@ -0,0 +1,68 @@ +/* + * + * 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 "rx_buffer_codeblock_pool.h" +#include "rx_buffer_impl.h" +#include "srsran/phy/upper/rx_buffer_pool.h" +#include "srsran/phy/upper/unique_rx_buffer.h" +#include "srsran/ran/slot_point.h" +#include "srsran/srslog/logger.h" +#include "srsran/srslog/srslog.h" +#include + +namespace srsran { + +/// Implements a PUSCH rate matcher buffer pool. +class rx_buffer_pool_impl : public rx_buffer_pool +{ +private: + /// No expiration time value. + slot_point null_expiration = slot_point(); + + /// Codeblock buffer pool. + rx_buffer_codeblock_pool codeblock_pool; + /// Actual buffer pool. + std::vector buffers; + /// \brief List of buffer identifiers. + /// + /// Maps buffer identifiers to buffers. Each position indicates the buffer identifier assign to each of the buffers. + /// Buffers with \c trx_buffer_identifier::invalid() identifier are not reserved. + std::vector identifiers; + /// Tracks expiration times. + std::vector expirations; + + /// Indicates the lifetime of a buffer reservation as a number of slots. + unsigned expire_timeout_slots; + /// Logger. + srslog::basic_logger& logger; + +public: + /// \brief Creates a generic receiver buffer pool. + /// \param[in] config Provides the pool required parameters. + rx_buffer_pool_impl(const rx_buffer_pool_config& config) : + codeblock_pool(config.max_nof_codeblocks, config.max_codeblock_size, config.external_soft_bits), + buffers(config.nof_buffers, rx_buffer_impl(codeblock_pool)), + identifiers(config.nof_buffers, trx_buffer_identifier::invalid()), + expirations(config.nof_buffers, null_expiration), + expire_timeout_slots(config.expire_timeout_slots), + logger(srslog::fetch_basic_logger("PHY", true)) + { + } + + // See interface for documentation. + unique_rx_buffer reserve(const slot_point& slot, trx_buffer_identifier id, unsigned nof_codeblocks) override; + + // See interface for documentation. + void run_slot(const slot_point& slot) override; +}; + +} // namespace srsran diff --git a/lib/phy/upper/rx_softbuffer_impl.h b/lib/phy/upper/rx_softbuffer_impl.h deleted file mode 100644 index 6b854d4b26..0000000000 --- a/lib/phy/upper/rx_softbuffer_impl.h +++ /dev/null @@ -1,283 +0,0 @@ -/* - * - * 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 "rx_softbuffer_codeblock_pool.h" -#include "srsran/adt/static_vector.h" -#include "srsran/phy/upper/codeblock_metadata.h" -#include "srsran/phy/upper/rx_softbuffer_pool.h" -#include "srsran/phy/upper/unique_rx_softbuffer.h" -#include "srsran/support/error_handling.h" -#include - -namespace srsran { - -enum class rx_softbuffer_status { successful = 0, already_in_use, insufficient_cb }; - -constexpr const char* to_string(rx_softbuffer_status status) -{ - switch (status) { - default: - case rx_softbuffer_status::successful: - return "successful"; - case rx_softbuffer_status::already_in_use: - return "HARQ already in use"; - case rx_softbuffer_status::insufficient_cb: - return "insufficient CBs"; - } -} - -/// Implements a receiver softbuffer interface. -class rx_softbuffer_impl : public unique_rx_softbuffer::softbuffer -{ -private: - /// Protects the finite state machine from concurrent access. - mutable std::mutex fsm_mutex; - /// Finite state machine states. - enum class state { - /// \brief The softbuffer has not been configured with any codeblock. - /// - /// It is available for being reserved. - available = 0, - ///\brief The softbuffer is reserved with a number of codeblocks for an RNTI and HARQ process. - /// - /// It allows new reservations. - reserved, - /// \brief The softbuffer is reserved and locked in a context. It does not accept new reservations or - /// retransmissions. - /// - /// It allows: - /// - \c unlock: a transmission did not match the CRC, it transitions to \c reserved; and - /// - \c release: a transmission matched the CRC and the softbuffer releases all its resources, it transitions to \c - /// released. - locked, - /// \brief The softbuffer has been released and the resources have not been released. - /// - /// It allows: - /// - \c run_slot: releases its resources and transitions to \c available; and - /// - \c reserve: reserves or reuses its resources for a new transmission. - released - }; - /// Current softbuffer state. - state current_state = state::available; - /// Reservation identifier. - rx_softbuffer_identifier reservation_id = rx_softbuffer_identifier::unknown(); - /// Indicates the slot the softbuffer will expire at. - slot_point reservation_expire_slot; - /// Reference to the codeblock pool. - rx_softbuffer_codeblock_pool& codeblock_pool; - /// Stores codeblocks CRCs. - static_vector crc; - /// Stores codeblock identifiers. - static_vector codeblock_ids; - - /// \brief Releases the reserved softbuffer to the pool. - /// \remark An assertion is triggered if the softbuffer is locked. - void free() - { - // Free codeblocks. - for (unsigned cb_id : codeblock_ids) { - codeblock_pool.free(cb_id); - } - - // Indicate the buffer is available by clearing the codeblocks identifiers. - codeblock_ids.clear(); - - // Transition to available. - current_state = state::available; - } - -public: - /// \brief Creates a receive softbuffer. - /// \param[in] pool Provides the codeblock softbuffer pool. - rx_softbuffer_impl(rx_softbuffer_codeblock_pool& pool) : reservation_id(), codeblock_pool(pool) - { - // Do nothing. - } - - /// \brief Reserves the softbuffer. - /// - /// The reservation is unsuccessful if: - /// - the softbuffer is already in use in an another scope, or - /// - the pool is out of resources. - /// - /// \param[in] id Reservation identifier. - /// \param[in] expire_slot Slot at which the reservation expires. - /// \param[in] nof_codeblocks Number of codeblocks to reserve. - /// \return True if the reservation is successful, false otherwise. - rx_softbuffer_status - reserve(const rx_softbuffer_identifier& id, const slot_point& expire_slot, unsigned nof_codeblocks) - { - std::unique_lock lock(fsm_mutex); - - // It cannot be reserved if it is locked. - if (current_state == state::locked) { - return rx_softbuffer_status::already_in_use; - } - - // Reset CRCs if one of the following conditions holds: - // - The reservation identifier changed; - // - The buffer is available; or - // - The number of codeblocks changed. - bool reset_crc = (reservation_id != id) || (current_state == state::available) || (crc.size() != nof_codeblocks); - - // Update reservation information. - reservation_id = id; - reservation_expire_slot = expire_slot; - - // If the current number of codeblocks is larger than required, free the excess of codeblocks. - while (codeblock_ids.size() > nof_codeblocks) { - // Get the codeblock identifier at the back and remove from the list. - unsigned cb_id = codeblock_ids.back(); - codeblock_ids.pop_back(); - - // Free the codeblock. - codeblock_pool.free(cb_id); - } - - // If the current number of codeblocks is less than required, reserve the remaining codeblocks. - while (codeblock_ids.size() < nof_codeblocks) { - // Reserve codeblock. - unsigned cb_id = codeblock_pool.reserve(); - - // Make sure the CB identifier is valid. - if (cb_id == rx_softbuffer_codeblock_pool::UNRESERVED_CB_ID) { - // Free the rest of the buffer. - free(); - return rx_softbuffer_status::insufficient_cb; - } - - // Append the codeblock identifier to the list. - codeblock_ids.push_back(cb_id); - } - - // Resize CRCs. - crc.resize(nof_codeblocks); - - // Reset CRCs if necessary. - if (reset_crc) { - reset_codeblocks_crc(); - } - - // Transition to reserved. - current_state = state::reserved; - return rx_softbuffer_status::successful; - } - - /// \brief Runs softbuffer housekeeping as per slot basis. - /// - /// Releases the resources if the softbuffer is \c released or the softbuffer reservation time expired while it - /// is \c reserved. - /// - /// \param[in] slot Indicates the current slot. - /// \return \c true if the softbuffer is available, otherwise \c false. - bool run_slot(const slot_point& slot) - { - std::unique_lock lock(fsm_mutex); - - // Check if it is released. - bool is_released = current_state == state::released; - - // Check if it is expired. - bool is_expired = (current_state == state::reserved) && (reservation_expire_slot <= slot); - - // Check the expiration of the buffer reservation. - if (is_released || is_expired) { - // Free codeblocks and transition to available. - free(); - } - - return current_state == state::available; - } - - /// Returns true if the buffer matches the given identifier, false otherwise. It does not require state protection. - bool match_id(const rx_softbuffer_identifier& identifier) const { return reservation_id == identifier; } - - // See interface for documentation. - unsigned get_nof_codeblocks() const override { return crc.size(); } - - // See interface for documentation. - void reset_codeblocks_crc() override - { - // Set all codeblock CRC to false. - for (bool& cb_crc : crc) { - cb_crc = false; - } - } - - // See interface for documentation. - span get_codeblocks_crc() override { return crc; } - - // See interface for documentation. - unsigned get_absolute_codeblock_id(unsigned codeblock_id) const override - { - srsran_assert(codeblock_id < codeblock_ids.size(), - "Codeblock index ({}) is out of range ({}).", - codeblock_id, - codeblock_ids.size()); - return codeblock_ids[codeblock_id]; - } - - // See interface for documentation. - span get_codeblock_soft_bits(unsigned codeblock_id, unsigned codeblock_size) override - { - srsran_assert(codeblock_id < codeblock_ids.size(), - "Codeblock index ({}) is out of range ({}).", - codeblock_id, - codeblock_ids.size()); - unsigned cb_id = codeblock_ids[codeblock_id]; - unsigned cb_max_size = codeblock_pool.get_soft_bits(cb_id).size(); - srsran_assert( - codeblock_size <= cb_max_size, "Codeblock size {} exceeds maximum size {}.", codeblock_size, cb_max_size); - return codeblock_pool.get_soft_bits(cb_id).first(codeblock_size); - } - - // See interface for documentation. - bit_buffer get_codeblock_data_bits(unsigned codeblock_id, unsigned data_size) override - { - srsran_assert(codeblock_id < codeblock_ids.size(), - "Codeblock index ({}) is out of range ({}).", - codeblock_id, - codeblock_ids.size()); - unsigned cb_id = codeblock_ids[codeblock_id]; - unsigned data_max_size = codeblock_pool.get_data_bits(cb_id).size(); - srsran_assert( - data_size <= data_max_size, "Codeblock data size {} exceeds maximum size {}.", data_size, data_max_size); - return codeblock_pool.get_data_bits(cb_id).first(data_size); - } - - // See interface for documentation. - void lock() override - { - std::unique_lock lock(fsm_mutex); - srsran_assert(current_state == state::reserved, "It is only possible to reserve in reserved state."); - current_state = state::locked; - } - - // See interface for documentation. - void unlock() override - { - std::unique_lock lock(fsm_mutex); - if (current_state == state::locked) { - current_state = state::reserved; - } - } - - // See interface for documentation. - void release() override - { - std::unique_lock lock(fsm_mutex); - srsran_assert((current_state == state::reserved) || (current_state == state::locked), - "It is only possible to reserve in reserved state."); - current_state = state::released; - } -}; - -} // namespace srsran diff --git a/lib/phy/upper/rx_softbuffer_pool_impl.cpp b/lib/phy/upper/rx_softbuffer_pool_impl.cpp deleted file mode 100644 index 5f428bdf02..0000000000 --- a/lib/phy/upper/rx_softbuffer_pool_impl.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - * - * 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 "rx_softbuffer_pool_impl.h" - -using namespace srsran; - -namespace fmt { - -/// Default formatter for rx_softbuffer_identifier. -template <> -struct formatter { - template - auto parse(ParseContext& ctx) -> decltype(ctx.begin()) - { - return ctx.begin(); - } - - template - auto format(const srsran::rx_softbuffer_identifier& value, FormatContext& ctx) - -> decltype(std::declval().out()) - { - return format_to(ctx.out(), "rnti={} h_id={}", value.rnti, value.harq_ack_id); - } -}; - -} // namespace fmt - -unique_rx_softbuffer rx_softbuffer_pool_impl::reserve_softbuffer(const slot_point& slot, - const rx_softbuffer_identifier& id, - unsigned nof_codeblocks) -{ - std::unique_lock lock(mutex); - slot_point expire_slot = slot + expire_timeout_slots; - - // Look for the same identifier within the reserved buffers. - for (auto& buffer : reserved_buffers) { - if (buffer->match_id(id)) { - rx_softbuffer_status status = buffer->reserve(id, expire_slot, nof_codeblocks); - - // Reserve buffer. - if (status != rx_softbuffer_status::successful) { - logger.warning(slot.sfn(), slot.slot_index(), "UL HARQ {}: failed to reserve, {}.", id, to_string(status)); - - // If the reservation failed, return an invalid buffer. - return unique_rx_softbuffer(); - } - - return unique_rx_softbuffer(*buffer); - } - } - - // If no available buffer is found, return an invalid buffer. - if (available_buffers.empty()) { - logger.warning( - slot.sfn(), slot.slot_index(), "UL HARQ {}: failed to reserve, insufficient buffers in the pool.", id); - return unique_rx_softbuffer(); - } - - // Select an available buffer. - std::unique_ptr& buffer = available_buffers.top(); - - // Try to reserve codeblocks. - rx_softbuffer_status status = buffer->reserve(id, expire_slot, nof_codeblocks); - - // Move the buffer to reserved list and remove from available if the reservation was successful. - if (status == rx_softbuffer_status::successful) { - unique_rx_softbuffer unique_buffer(*buffer); - reserved_buffers.push(std::move(buffer)); - available_buffers.pop(); - return unique_buffer; - } - - // If the reservation failed, return an invalid buffer. - logger.warning(slot.sfn(), slot.slot_index(), "UL HARQ {}: failed to reserve, {}.", id, to_string(status)); - return unique_rx_softbuffer(); -} - -void rx_softbuffer_pool_impl::run_slot(const slot_point& slot) -{ - std::unique_lock lock(mutex); - - // Run TTI for each reserved buffer. - unsigned count = reserved_buffers.size(); - for (unsigned i = 0; i != count; ++i) { - // Pop top reserved buffer. - std::unique_ptr buffer = std::move(reserved_buffers.top()); - reserved_buffers.pop(); - - // Run buffer slot. - bool available = buffer->run_slot(slot); - - // Return buffer to queue. - if (available) { - available_buffers.push(std::move(buffer)); - } else { - reserved_buffers.push(std::move(buffer)); - } - } -} - -std::unique_ptr srsran::create_rx_softbuffer_pool(const rx_softbuffer_pool_config& config) -{ - return std::make_unique(config); -} diff --git a/lib/phy/upper/rx_softbuffer_pool_impl.h b/lib/phy/upper/rx_softbuffer_pool_impl.h deleted file mode 100644 index 6a03ebc475..0000000000 --- a/lib/phy/upper/rx_softbuffer_pool_impl.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * - * 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 "rx_softbuffer_impl.h" -#include "srsran/adt/ring_buffer.h" -#include "srsran/adt/static_vector.h" -#include "srsran/phy/upper/codeblock_metadata.h" -#include "srsran/phy/upper/rx_softbuffer_pool.h" -#include "srsran/phy/upper/unique_rx_softbuffer.h" -#include "srsran/support/error_handling.h" -#include "srsran/support/math_utils.h" -#include - -namespace srsran { - -/// Describes a receiver softbuffer pool. -class rx_softbuffer_pool_impl : public rx_softbuffer_pool -{ -private: - /// Codeblock softbuffer pool. - rx_softbuffer_codeblock_pool codeblock_pool; - /// Storage of softbuffers. - ring_buffer> available_buffers; - ring_buffer> reserved_buffers; - /// Indicates the lifetime of a softbuffer reservation as a number of slots. - unsigned expire_timeout_slots; - /// Protects methods from concurrent calls. - std::mutex mutex; - /// Logger. - srslog::basic_logger& logger; - -public: - /// \brief Creates a generic receiver softbuffer pool. - /// \param[in] config Provides the pool required parameters. - rx_softbuffer_pool_impl(const rx_softbuffer_pool_config& config) : - codeblock_pool(config.max_nof_codeblocks, config.max_codeblock_size, config.external_soft_bits), - available_buffers(config.max_softbuffers), - reserved_buffers(config.max_softbuffers), - expire_timeout_slots(config.expire_timeout_slots), - logger(srslog::fetch_basic_logger("PHY", true)) - { - for (unsigned i = 0, i_end = config.max_softbuffers; i != i_end; ++i) { - available_buffers.push(std::make_unique(codeblock_pool)); - } - } - - // See interface for documentation. - unique_rx_softbuffer - reserve_softbuffer(const slot_point& slot, const rx_softbuffer_identifier& id, unsigned nof_codeblocks) override; - - // See interface for documentation. - void run_slot(const slot_point& slot) override; -}; - -} // namespace srsran diff --git a/lib/phy/upper/tx_buffer_codeblock_pool.h b/lib/phy/upper/tx_buffer_codeblock_pool.h index ff167419b6..1331c5fea3 100644 --- a/lib/phy/upper/tx_buffer_codeblock_pool.h +++ b/lib/phy/upper/tx_buffer_codeblock_pool.h @@ -9,14 +9,13 @@ */ #pragma once -#include "tx_buffer_impl.h" + +#include "srsran/adt/bit_buffer.h" #include "srsran/adt/concurrent_queue.h" -#include "srsran/adt/static_vector.h" -#include "srsran/phy/upper/codeblock_metadata.h" -#include "srsran/phy/upper/tx_buffer_pool.h" -#include "srsran/phy/upper/unique_tx_buffer.h" -#include "srsran/support/error_handling.h" -#include "srsran/support/math_utils.h" +#include "srsran/adt/optional.h" +#include "srsran/support/srsran_assert.h" +#include +#include namespace srsran { @@ -24,6 +23,7 @@ namespace srsran { class tx_buffer_codeblock_pool { private: + /// Codeblock identifier list type. using codeblock_identifier_list = concurrent_queue; diff --git a/lib/phy/upper/tx_buffer_impl.h b/lib/phy/upper/tx_buffer_impl.h index 7593fa3f61..aafcda39a7 100644 --- a/lib/phy/upper/tx_buffer_impl.h +++ b/lib/phy/upper/tx_buffer_impl.h @@ -9,111 +9,95 @@ */ #pragma once + #include "tx_buffer_codeblock_pool.h" +#include "srsran/adt/bit_buffer.h" +#include "srsran/adt/optional.h" +#include "srsran/adt/span.h" #include "srsran/adt/static_vector.h" +#include "srsran/phy/upper/log_likelihood_ratio.h" +#include "srsran/phy/upper/tx_buffer_pool.h" #include "srsran/phy/upper/unique_tx_buffer.h" -#include +#include "srsran/ran/sch/sch_constants.h" +#include "srsran/support/srsran_assert.h" +#include +#include namespace srsran { -/// Transmit buffer reservation status. -enum class tx_buffer_status { successful = 0, already_in_use, insufficient_cb }; +enum class tx_buffer_status : uint8_t { successful = 0, already_in_use, insufficient_cb }; -/// Converts the buffer reservation status to a string. -constexpr const char* to_string(tx_buffer_status status) -{ - switch (status) { - default: - case tx_buffer_status::successful: - return "successful"; - case tx_buffer_status::already_in_use: - return "HARQ already in use"; - case tx_buffer_status::insufficient_cb: - return "insufficient CBs"; - } -} - -/// Implements a transmitter buffer interface. -class tx_buffer_impl : public unique_tx_buffer::lockable_buffer +/// Implements a transmiter buffer interface. +class tx_buffer_impl : public unique_tx_buffer::callback { private: - /// Protects the finite state machine from concurrent access. - mutable std::mutex fsm_mutex; - /// Finite state machine states. - enum class state { + /// Internal buffer states. + enum class state : uint8_t { /// \brief The buffer has not been configured with any codeblock. /// /// It is available for being reserved. - available = 0, - ///\brief The buffer is reserved with a number of codeblocks for an RNTI and HARQ process. + available, + /// \brief The buffer is reserved with a number of codeblocks. /// - /// It allows new reservations. + /// It allows: + /// -\c expire: called when the buffer context has expired, it transitions to \c available. + /// -\c reserve: makes a new reservation. reserved, - /// \brief The buffer is reserved and locked in a context. It does not accept new reservations or retransmissions. + /// \brief The buffer is reserved and locked in a context. It does not accept new reservations or retransmissions, + /// and prevents the buffer from expiring. /// - /// The buffer is active in a scope, the buffer shall transition to \c reserved when unlock() is called. - locked, + /// It allows: + /// - \c unlock: a transmission did not match the CRC, it transitions to \c reserved; and + /// - \c release: a transmission matched the CRC and the buffer releases all its resources, it transitions to \c + /// available. + locked }; + /// Current buffer state. - state current_state = state::available; - /// Reservation identifier. - tx_buffer_identifier reservation_id = tx_buffer_identifier::unknown(); - /// Indicates the slot the buffer will expire at. - slot_point reservation_expire_slot; + std::atomic current_state = {state::available}; /// Reference to the codeblock pool. tx_buffer_codeblock_pool& codeblock_pool; + /// Stores codeblocks CRCs. + static_vector crc; /// Stores codeblock identifiers. static_vector codeblock_ids; - /// \brief Releases the reserved buffer to the pool. - /// \remark An assertion is triggered if the buffer is locked. + /// Frees reserved codeblocks. The codeblocks are returned to the pool. void free() { - srsran_assert(current_state != state::locked, "The buffer is locked."); - // Free all codeblocks. - while (!codeblock_ids.empty()) { - unsigned cb_id = codeblock_ids.back(); - codeblock_ids.pop_back(); - + for (unsigned cb_id : codeblock_ids) { codeblock_pool.free(cb_id); } - // Transition to available. - current_state = state::available; + // Indicate the buffer is available by clearing the codeblocks identifiers. + codeblock_ids.clear(); } public: - /// \brief Creates a transmit buffer. - /// \param[in] pool Codeblock buffer pool. - tx_buffer_impl(tx_buffer_codeblock_pool& pool) : reservation_id(), codeblock_pool(pool) + /// \brief Creates a receive buffer. + /// \param pool Codeblock buffer pool. + explicit tx_buffer_impl(tx_buffer_codeblock_pool& pool) : codeblock_pool(pool) { // Do nothing. } - /// \brief Reserves a transmit buffer. - /// - /// The reservation is unsuccessful if: - /// - the buffer is already in use in an another scope, or - /// - the pool is out of resources. - /// - /// \param[in] id Reservation identifier. - /// \param[in] expire_slot Slot at which the reservation expires. - /// \param[in] nof_codeblocks Number of codeblocks to reserve. + /// Copy constructor - creates another buffer with the same codeblock pool. + tx_buffer_impl(const tx_buffer_impl& other) noexcept : codeblock_pool(other.codeblock_pool) {} + + /// Move constructor - creates another buffer with the same codeblock pool. + tx_buffer_impl(tx_buffer_impl&& other) noexcept : codeblock_pool(other.codeblock_pool) {} + + /// \brief Reserves a number of codeblocks from the pool. + /// \param nof_codeblocks Number of codeblocks to reserve. /// \return The reservation status. - tx_buffer_status reserve(const tx_buffer_identifier& id, const slot_point& expire_slot, unsigned nof_codeblocks) + tx_buffer_status reserve(unsigned nof_codeblocks) { - std::unique_lock lock(fsm_mutex); - - // It cannot be reserved if it is locked. - if (current_state == state::locked) { + // It cannot reserve resources if it is locked. + if (current_state.load() == state::locked) { return tx_buffer_status::already_in_use; } - // Update reservation information. - reservation_id = id; - reservation_expire_slot = expire_slot; - // If the current number of codeblocks is larger than required, free the excess of codeblocks. while (codeblock_ids.size() > nof_codeblocks) { // Get the codeblock identifier at the back and remove from the list. @@ -127,56 +111,29 @@ class tx_buffer_impl : public unique_tx_buffer::lockable_buffer // If the current number of codeblocks is less than required, reserve the remaining codeblocks. while (codeblock_ids.size() < nof_codeblocks) { // Reserve codeblock. - unsigned cb_id = codeblock_pool.reserve(); + optional cb_id = codeblock_pool.reserve(); - // Make sure the CB identifier is valid. - if (cb_id == tx_buffer_codeblock_pool::UNRESERVED_CB_ID) { - // Free the rest of the buffer. + // Free the entire buffer if one codeblock cannot be reserved. + if (!cb_id.has_value()) { free(); + current_state = state::available; return tx_buffer_status::insufficient_cb; } // Append the codeblock identifier to the list. - codeblock_ids.push_back(cb_id); + codeblock_ids.push_back(cb_id.value()); } - // Transition to reserved. - current_state = state::reserved; - return tx_buffer_status::successful; - } - - /// \brief It runs buffers housekeeping as per slot basis. - /// - /// It frees the buffer if it is not locked, and the identifier is default or the reservation time expired. - /// - /// \param[in] slot Current slot. - /// \return \c true if the buffer is available, otherwise \c false. - bool run_slot(const slot_point& slot) - { - std::unique_lock lock(fsm_mutex); - - bool is_reserved = (current_state == state::reserved); - - // Check if the - bool default_id = match_id({}); + // Resize CRCs. + crc.resize(nof_codeblocks); - // Check if it is expired. - bool is_expired = (reservation_expire_slot <= slot); - - // Check the expiration of the buffer reservation. - if (is_reserved && (default_id || is_expired)) { - // Free codeblocks and transition to available. - free(); - } + current_state = state::reserved; - return current_state == state::available; + return tx_buffer_status::successful; } - /// Returns true if the buffer matches the given identifier, false otherwise. It does not require state protection. - bool match_id(const tx_buffer_identifier& identifier) const { return reservation_id == identifier; } - // See interface for documentation. - unsigned get_nof_codeblocks() const override { return codeblock_ids.size(); } + unsigned get_nof_codeblocks() const override { return crc.size(); } // See interface for documentation. unsigned get_absolute_codeblock_id(unsigned codeblock_id) const override @@ -205,18 +162,40 @@ class tx_buffer_impl : public unique_tx_buffer::lockable_buffer // See interface for documentation. void lock() override { - std::unique_lock lock(fsm_mutex); - srsran_assert(current_state == state::reserved, "It is only possible to reserve in reserved state."); - current_state = state::locked; + state previous_state = current_state.exchange(state::locked); + srsran_assert(previous_state == state::reserved, "Failed to lock. Invalid state."); } // See interface for documentation. void unlock() override { - std::unique_lock lock(fsm_mutex); - if (current_state == state::locked) { - current_state = state::reserved; + state previous_state = current_state.exchange(state::reserved); + srsran_assert(previous_state == state::locked, "Failed to unlock. Invalid state."); + } + + /// Returns true if the buffer is free. + bool is_free() const { return current_state == state::available; } + + /// \brief Expires the buffer. + /// + /// The buffer pool shall use this method when the buffer expires. The buffer frees the reserved codeblocks if it is + /// not blocked. + /// + /// \return \c true if the buffer is not locked. + bool expire() + { + state expected_state = state::reserved; + bool from_reserved = current_state.compare_exchange_weak(expected_state, state::available); + + // The buffer cannot be freed if it is locked. + if (!from_reserved) { + return false; } + + // Release resources. + free(); + + return true; } }; diff --git a/lib/phy/upper/tx_buffer_pool_impl.cpp b/lib/phy/upper/tx_buffer_pool_impl.cpp index 6ffcc2fb5b..ca0b9e65ff 100644 --- a/lib/phy/upper/tx_buffer_pool_impl.cpp +++ b/lib/phy/upper/tx_buffer_pool_impl.cpp @@ -9,138 +9,130 @@ */ #include "tx_buffer_pool_impl.h" +#include "tx_buffer_impl.h" +#include "srsran/phy/upper/trx_buffer_identifier.h" +#include "srsran/phy/upper/tx_buffer_pool.h" +#include "srsran/phy/upper/unique_tx_buffer.h" +#include "srsran/ran/slot_point.h" +#include +#include using namespace srsran; -namespace fmt { - -/// Default formatter for tx_buffer_identifier. -template <> -struct formatter { - template - auto parse(ParseContext& ctx) -> decltype(ctx.begin()) - { - return ctx.begin(); - } - - template - auto format(const srsran::tx_buffer_identifier& value, FormatContext& ctx) - -> decltype(std::declval().out()) - { - return format_to(ctx.out(), "rnti={} h_id={}", value.rnti, value.harq_ack_id); - } -}; - -} // namespace fmt - -unique_tx_buffer -tx_buffer_pool_impl::reserve_buffer(const slot_point& slot, const tx_buffer_identifier& id, unsigned nof_codeblocks) +unique_tx_buffer tx_buffer_pool_impl::reserve(const slot_point& slot, trx_buffer_identifier id, unsigned nof_codeblocks) { - std::unique_lock lock(mutex); - slot_point expire_slot = slot + expire_timeout_slots; - - // Look for the same identifier within the reserved buffers. - for (unsigned i_buffer : reserved_buffers) { - tx_buffer_impl& buffer = *buffer_pool[i_buffer]; - if (buffer.match_id(id)) { - // Reserve buffer. - tx_buffer_status status = buffer.reserve(id, expire_slot, nof_codeblocks); - if (status != tx_buffer_status::successful) { - logger.warning(slot.sfn(), slot.slot_index(), "DL HARQ {}: failed to reserve, {}.", id, to_string(status)); - - // If the reservation failed, return an invalid buffer. - return unique_tx_buffer(); - } + // Try to find the HARQ identifier. + auto id_found = std::find(identifiers.begin(), identifiers.end(), id); - return unique_tx_buffer(buffer); - } + // Find an available buffer if no buffer was found with the same identifier. + if (id_found == identifiers.end()) { + id_found = std::find(identifiers.begin(), identifiers.end(), trx_buffer_identifier::invalid()); } - // If no available buffer is available, return an invalid buffer. - if (available_buffers.empty()) { + // Report warning and return invalid buffer if no available buffer has been found. + if (id_found == identifiers.end()) { logger.warning( slot.sfn(), slot.slot_index(), "DL HARQ {}: failed to reserve, insufficient buffers in the pool.", id); return unique_tx_buffer(); } - // Select the first available buffer. - unsigned buffer_i = available_buffers.top(); + // Get buffer index within the pool. + unsigned i_buffer = id_found - identifiers.begin(); - // Select an available buffer. - tx_buffer_impl& buffer = *buffer_pool[buffer_i]; + // Get reference to the buffer. + tx_buffer_impl& buffer = buffers[i_buffer]; - // Try to reserve codeblocks. - tx_buffer_status status = buffer.reserve(id, expire_slot, nof_codeblocks); + // Reserve codeblocks. + tx_buffer_status status = buffer.reserve(nof_codeblocks); - // If the reservation failed, return an invalid buffer. + // Report warning and return invalid buffer if the reservation is not successful. if (status != tx_buffer_status::successful) { - logger.warning(slot.sfn(), slot.slot_index(), "DL HARQ {}: failed to reserve, {}.", id, to_string(status)); + logger.warning(slot.sfn(), + slot.slot_index(), + "DL HARQ {}: failed to reserve, {}.", + id, + (status == tx_buffer_status::already_in_use) ? "HARQ already in use" : "insufficient CBs"); return unique_tx_buffer(); } - // Move the buffer to reserved list and remove from available if the reservation was successful. - unique_tx_buffer unique_buffer(buffer); - reserved_buffers.push(buffer_i); - available_buffers.pop(); - return unique_buffer; + // Update identifier and expiration. + identifiers[i_buffer] = id; + expirations[i_buffer] = slot + expire_timeout_slots; + + // Create buffer. + return unique_tx_buffer(buffer); } -unique_tx_buffer tx_buffer_pool_impl::reserve_buffer(const slot_point& slot, unsigned nof_codeblocks) +unique_tx_buffer tx_buffer_pool_impl::reserve(const slot_point& slot, unsigned nof_codeblocks) { - std::unique_lock lock(mutex); - slot_point expire_slot = slot + 1; + // Find an available buffer if no buffer was found with the same identifier. + auto id_found = std::find(identifiers.begin(), identifiers.end(), trx_buffer_identifier::invalid()); - // If no available buffer is available, return an invalid buffer. - if (available_buffers.empty()) { + // Report warning and return invalid buffer if no available buffer has been found. + if (id_found == identifiers.end()) { logger.warning( - slot.sfn(), slot.slot_index(), "DL HARQ unknown: failed to reserve, insufficient buffers in the pool."); + slot.sfn(), slot.slot_index(), "DL HARQ invalid: failed to reserve, insufficient buffers in the pool."); return unique_tx_buffer(); } - // Select the first available buffer. - unsigned buffer_i = available_buffers.top(); + // Get buffer index within the pool. + unsigned i_buffer = id_found - identifiers.begin(); - // Select an available buffer. - tx_buffer_impl& buffer = *buffer_pool[buffer_i]; + // Get reference to the buffer. + tx_buffer_impl& buffer = buffers[i_buffer]; - // Try to reserve codeblocks. - tx_buffer_status status = buffer.reserve(unknown_id, expire_slot, nof_codeblocks); + // Reserve codeblocks. + tx_buffer_status status = buffer.reserve(nof_codeblocks); - // If the reservation failed, return an invalid buffer. + // Report warning and return invalid buffer if the reservation is not successful. if (status != tx_buffer_status::successful) { - logger.warning(slot.sfn(), slot.slot_index(), "DL HARQ unknown: failed to reserve, {}.", to_string(status)); + logger.warning(slot.sfn(), + slot.slot_index(), + "DL HARQ invalid: failed to reserve, {}.", + (status == tx_buffer_status::already_in_use) ? "HARQ already in use" : "insufficient CBs"); return unique_tx_buffer(); } - // Move the buffer to reserved list and remove from available if the reservation was successful. - unique_tx_buffer unique_buffer(buffer); - reserved_buffers.push(buffer_i); - available_buffers.pop(); - return unique_buffer; + // Update identifier and expiration. + identifiers[i_buffer] = trx_buffer_identifier::unknown(); + expirations[i_buffer] = slot + expire_timeout_slots; + + // Create buffer. + return unique_tx_buffer(buffer); } void tx_buffer_pool_impl::run_slot(const slot_point& slot) { - std::unique_lock lock(mutex); - - // Run TTI for each reserved buffer. - unsigned count = reserved_buffers.size(); - for (unsigned i = 0; i != count; ++i) { - // Pop top reserved buffer identifier. - unsigned buffer_i = reserved_buffers.top(); - reserved_buffers.pop(); - - // Select buffer. - tx_buffer_impl& buffer = *buffer_pool[buffer_i]; - - // Run buffer slot. - bool available = buffer.run_slot(slot); - - // Return buffer to queue. - if (available) { - available_buffers.push(buffer_i); - } else { - reserved_buffers.push(buffer_i); + // Predicate for finding available buffers. + auto pred = [](trx_buffer_identifier id) { return id != trx_buffer_identifier::invalid(); }; + + // Iterate over all the buffers that are currently reserved. + for (auto it = std::find_if(identifiers.begin(), identifiers.end(), pred); it != identifiers.end(); + it = std::find_if(++it, identifiers.end(), pred)) { + // Calculate buffer index. + unsigned i_buffer = it - identifiers.begin(); + + // Get reference to the buffer. + tx_buffer_impl& buffer = buffers[i_buffer]; + + // Determines whether the buffer is free. + bool is_free = buffer.is_free(); + + // A buffer is expired if the expiration slot is lower than or equal to the current slot. + if ((expirations[i_buffer] != null_expiration) && (expirations[i_buffer] <= slot)) { + // Try to expire the buffer. + is_free = buffer.expire(); + + // If the buffer is not available, increase the expiration time and continue to the next buffer. + if (!is_free) { + expirations[i_buffer] = slot + expire_timeout_slots; + } + } + + // Clear identifier and expiration. + if (is_free) { + identifiers[i_buffer] = trx_buffer_identifier::invalid(); + expirations[i_buffer] = null_expiration; } } } diff --git a/lib/phy/upper/tx_buffer_pool_impl.h b/lib/phy/upper/tx_buffer_pool_impl.h index ac94af18c6..4c289cc219 100644 --- a/lib/phy/upper/tx_buffer_pool_impl.h +++ b/lib/phy/upper/tx_buffer_pool_impl.h @@ -10,65 +10,62 @@ #pragma once +#include "tx_buffer_codeblock_pool.h" #include "tx_buffer_impl.h" -#include "srsran/adt/ring_buffer.h" -#include "srsran/adt/static_vector.h" -#include "srsran/phy/upper/codeblock_metadata.h" #include "srsran/phy/upper/tx_buffer_pool.h" #include "srsran/phy/upper/unique_tx_buffer.h" -#include "srsran/support/error_handling.h" -#include "srsran/support/math_utils.h" -#include +#include "srsran/ran/slot_point.h" +#include "srsran/srslog/logger.h" +#include "srsran/srslog/srslog.h" +#include namespace srsran { -/// Describes a receiver buffer pool. +/// Implements a PDSCH rate matcher buffer pool. class tx_buffer_pool_impl : public tx_buffer_pool { +private: + /// No expiration time value. + slot_point null_expiration = slot_point(); + + /// Code block buffer pool. + tx_buffer_codeblock_pool codeblock_pool; + /// Actual buffer pool. + std::vector buffers; + /// \brief List of buffer identifiers. + /// + /// Maps buffer identifiers to buffers. Each position indicates the buffer identifier assign to each of the buffers. + /// Buffers with \c trx_buffer_identifier::invalid() identifier are not reserved. + std::vector identifiers; + /// Tracks expiration times. + std::vector expirations; + + /// Indicates the lifetime of a buffer reservation as a number of slots. + unsigned expire_timeout_slots; + /// Logger. + srslog::basic_logger& logger; + public: /// \brief Creates a generic receiver buffer pool. /// \param[in] config Provides the pool required parameters. tx_buffer_pool_impl(const tx_buffer_pool_config& config) : - logger(srslog::fetch_basic_logger("PHY", true)), codeblock_pool(config.nof_codeblocks, config.max_codeblock_size, config.external_soft_bits), - available_buffers(config.nof_buffers), - reserved_buffers(config.nof_buffers), - expire_timeout_slots(config.expire_timeout_slots) + buffers(config.nof_buffers, tx_buffer_impl(codeblock_pool)), + identifiers(config.nof_buffers, trx_buffer_identifier::invalid()), + expirations(config.nof_buffers, null_expiration), + expire_timeout_slots(config.expire_timeout_slots), + logger(srslog::fetch_basic_logger("PHY", true)) { - for (unsigned i = 0, i_end = config.nof_buffers; i != i_end; ++i) { - buffer_pool.emplace_back(std::make_unique(codeblock_pool)); - available_buffers.push(i); - } } // See interface for documentation. - unique_tx_buffer - reserve_buffer(const slot_point& slot, const tx_buffer_identifier& id, unsigned nof_codeblocks) override; + unique_tx_buffer reserve(const slot_point& slot, trx_buffer_identifier id, unsigned nof_codeblocks) override; // See interface for documentation. - unique_tx_buffer reserve_buffer(const slot_point& slot, unsigned nof_codeblocks) override; + unique_tx_buffer reserve(const slot_point& slot, unsigned nof_codeblocks) override; // See interface for documentation. void run_slot(const slot_point& slot) override; - -private: - /// Buffer identifier for non specified RNTI and HARQ. - const tx_buffer_identifier unknown_id = {0, 16}; - - /// Protects methods from concurrent calls. - std::mutex mutex; - /// General physical layer logger. - srslog::basic_logger& logger; - /// Codeblock buffer pool. - tx_buffer_codeblock_pool codeblock_pool; - /// Actual buffer pool. - std::vector> buffer_pool; - /// Storage of available buffer identifier. - ring_buffer available_buffers; - /// Storage of reserved buffer identifier. - ring_buffer reserved_buffers; - /// Indicates the lifetime of a buffer reservation as a number of slots. - unsigned expire_timeout_slots; }; } // namespace srsran diff --git a/lib/phy/upper/uplink_processor_impl.cpp b/lib/phy/upper/uplink_processor_impl.cpp index 0ff4f3320b..23126fad70 100644 --- a/lib/phy/upper/uplink_processor_impl.cpp +++ b/lib/phy/upper/uplink_processor_impl.cpp @@ -12,7 +12,7 @@ #include "srsran/instrumentation/traces/du_traces.h" #include "srsran/phy/support/prach_buffer.h" #include "srsran/phy/support/prach_buffer_context.h" -#include "srsran/phy/upper/unique_rx_softbuffer.h" +#include "srsran/phy/upper/unique_rx_buffer.h" #include "srsran/phy/upper/upper_phy_rx_results_notifier.h" using namespace srsran; @@ -69,7 +69,7 @@ void uplink_processor_impl::process_prach(upper_phy_rx_results_notifier& notifie } void uplink_processor_impl::process_pusch(span data, - unique_rx_softbuffer softbuffer, + unique_rx_buffer rm_buffer, upper_phy_rx_results_notifier& notifier, const resource_grid_reader& grid, const uplink_processor::pusch_pdu& pdu) @@ -91,7 +91,7 @@ void uplink_processor_impl::process_pusch(span dat notifier, to_rnti(pdu.pdu.rnti), pdu.pdu.slot, to_harq_id(pdu.harq_id), data); // Process PUSCH. - pusch_proc->process(data, std::move(softbuffer), processor_notifier, grid, pdu.pdu); + pusch_proc->process(data, std::move(rm_buffer), processor_notifier, grid, pdu.pdu); l1_tracer << trace_event("process_pusch", tp); } diff --git a/lib/phy/upper/uplink_processor_impl.h b/lib/phy/upper/uplink_processor_impl.h index c4ae104959..26b3d30c2f 100644 --- a/lib/phy/upper/uplink_processor_impl.h +++ b/lib/phy/upper/uplink_processor_impl.h @@ -147,7 +147,7 @@ class uplink_processor_impl : public uplink_processor // See interface for documentation. void process_pusch(span data, - unique_rx_softbuffer softbuffer, + unique_rx_buffer rm_buffer, upper_phy_rx_results_notifier& notifier, const resource_grid_reader& grid, const uplink_processor::pusch_pdu& pdu) override; diff --git a/lib/phy/upper/uplink_processor_task_dispatcher.h b/lib/phy/upper/uplink_processor_task_dispatcher.h index 9939cfa4d9..45eba2748e 100644 --- a/lib/phy/upper/uplink_processor_task_dispatcher.h +++ b/lib/phy/upper/uplink_processor_task_dispatcher.h @@ -54,14 +54,14 @@ class uplink_processor_task_dispatcher : public uplink_processor // See interface for documentation. void process_pusch(span data, - unique_rx_softbuffer softbuffer, + unique_rx_buffer rm_buffer, upper_phy_rx_results_notifier& notifier, const resource_grid_reader& grid, const uplink_processor::pusch_pdu& pdu) override { bool success = - pusch_executor.execute([data, softbuffer2 = std::move(softbuffer), ¬ifier, &grid, pdu, this]() mutable { - processor->process_pusch(data, std::move(softbuffer2), notifier, grid, pdu); + pusch_executor.execute([data, rm_buffer2 = std::move(rm_buffer), ¬ifier, &grid, pdu, this]() mutable { + processor->process_pusch(data, std::move(rm_buffer2), notifier, grid, pdu); }); if (!success) { diff --git a/lib/phy/upper/upper_phy_factories.cpp b/lib/phy/upper/upper_phy_factories.cpp index 509aa04b2a..df3b5235ec 100644 --- a/lib/phy/upper/upper_phy_factories.cpp +++ b/lib/phy/upper/upper_phy_factories.cpp @@ -21,7 +21,7 @@ #include "srsran/phy/upper/channel_estimation.h" #include "srsran/phy/upper/channel_processors/channel_processor_factories.h" #include "srsran/phy/upper/channel_processors/pusch/factories.h" -#include "srsran/phy/upper/unique_rx_softbuffer.h" +#include "srsran/phy/upper/unique_rx_buffer.h" #include "srsran/support/error_handling.h" #include @@ -554,7 +554,7 @@ class upper_phy_factory_impl : public upper_phy_factory phy_config.tx_buf_pool = create_tx_buffer_pool(config.tx_buffer_config); report_fatal_error_if_not(phy_config.tx_buf_pool, "Invalid transmit buffer processor pool."); - phy_config.rx_buf_pool = create_rx_softbuffer_pool(config.rx_buffer_config); + phy_config.rx_buf_pool = create_rx_buffer_pool(config.rx_buffer_config); report_fatal_error_if_not(phy_config.tx_buf_pool, "Invalid receive buffer processor pool."); phy_config.ul_processor_pool = create_ul_processor_pool(*ul_processor_fact, config); @@ -567,8 +567,6 @@ class upper_phy_factory_impl : public upper_phy_factory phy_config.dl_pdu_validator = downlink_proc_factory->create_pdu_validator(); phy_config.ul_pdu_validator = ul_processor_fact->create_pdu_validator(); - phy_config.timing_handler_executor = config.pusch_executor; - return std::make_unique(std::move(phy_config)); } diff --git a/lib/phy/upper/upper_phy_impl.cpp b/lib/phy/upper/upper_phy_impl.cpp index 54ff80ddeb..8f8cb5a943 100644 --- a/lib/phy/upper/upper_phy_impl.cpp +++ b/lib/phy/upper/upper_phy_impl.cpp @@ -46,7 +46,7 @@ upper_phy_impl::upper_phy_impl(upper_phy_impl_config&& config) : *rx_buf_pool, rx_results_notifier, logger)), - timing_handler(logger, notifier_dummy, *rx_buf_pool, config.timing_handler_executor) + timing_handler(notifier_dummy) { srsran_assert(dl_processor_pool, "Invalid downlink processor pool"); srsran_assert(dl_rg_pool, "Invalid downlink resource grid pool"); diff --git a/lib/phy/upper/upper_phy_impl.h b/lib/phy/upper/upper_phy_impl.h index 0cd93a178a..dee167f982 100644 --- a/lib/phy/upper/upper_phy_impl.h +++ b/lib/phy/upper/upper_phy_impl.h @@ -18,7 +18,7 @@ #include "srsran/phy/support/prach_buffer_pool.h" #include "srsran/phy/support/resource_grid_pool.h" #include "srsran/phy/upper/downlink_processor.h" -#include "srsran/phy/upper/rx_softbuffer_pool.h" +#include "srsran/phy/upper/rx_buffer_pool.h" #include "srsran/phy/upper/tx_buffer_pool.h" #include "srsran/phy/upper/uplink_processor.h" #include "srsran/phy/upper/upper_phy.h" @@ -46,10 +46,10 @@ struct upper_phy_impl_config { std::unique_ptr ul_processor_pool; /// PRACH buffer pool. std::unique_ptr prach_pool; - /// Transmit softbuffer pool. + /// Transmit buffer pool. std::unique_ptr tx_buf_pool; - /// Receive softbuffer pool. - std::unique_ptr rx_buf_pool; + /// Receive buffer pool. + std::unique_ptr rx_buf_pool; /// Symbol request notifier. upper_phy_rx_symbol_request_notifier* rx_symbol_request_notifier; /// Log level. @@ -66,8 +66,6 @@ struct upper_phy_impl_config { std::unique_ptr dl_pdu_validator; /// Uplink PDU validator. std::unique_ptr ul_pdu_validator; - /// Executor for handling full slot boundary event. - task_executor* timing_handler_executor = nullptr; }; /// \brief Implementation of the upper PHY interface. @@ -78,19 +76,10 @@ class upper_phy_impl : public upper_phy /// Upper PHY timing handler implementation class. class upper_phy_timing_handler_impl : public upper_phy_timing_handler { - srslog::basic_logger& logger; std::reference_wrapper notifier; - rx_softbuffer_pool& softbuffer_pool; - task_executor& executor; public: - upper_phy_timing_handler_impl(srslog::basic_logger& logger_, - upper_phy_timing_notifier& notifier_, - rx_softbuffer_pool& softbuffer_pool_, - task_executor* executor_) : - logger(logger_), notifier(notifier_), softbuffer_pool(softbuffer_pool_), executor(*executor_) - { - } + upper_phy_timing_handler_impl(upper_phy_timing_notifier& notifier_) : notifier(notifier_) {} // See interface for documentation. void handle_tti_boundary(const upper_phy_timing_context& context) override @@ -103,17 +92,7 @@ class upper_phy_impl : public upper_phy void handle_ul_half_slot_boundary(const upper_phy_timing_context& context) override {} // See interface for documentation. - void handle_ul_full_slot_boundary(const upper_phy_timing_context& context) override - { - bool success = executor.execute([this, context]() { - // Advance the timing in the softbuffer pool. - softbuffer_pool.run_slot(context.slot); - }); - - if (!success) { - logger.warning(context.slot.sfn(), context.slot.slot_index(), "Failed to execute soft buffer pool slot."); - } - } + void handle_ul_full_slot_boundary(const upper_phy_timing_context& context) override {} void set_upper_phy_notifier(upper_phy_timing_notifier& n) { notifier = std::ref(n); } }; @@ -173,10 +152,10 @@ class upper_phy_impl : public upper_phy std::unique_ptr ul_processor_pool; /// PRACH buffer pool. std::unique_ptr prach_pool; - /// Transmit softbuffer pool. + /// Transmit buffer pool. std::unique_ptr tx_buf_pool; - /// Receive softbuffer pool. - std::unique_ptr rx_buf_pool; + /// Receive buffer pool. + std::unique_ptr rx_buf_pool; /// Downlink processor PDUs validator. std::unique_ptr dl_pdu_validator; /// Uplink processor PDUs validator. diff --git a/lib/phy/upper/upper_phy_rx_results_notifier_wrapper.h b/lib/phy/upper/upper_phy_rx_results_notifier_wrapper.h index 6946aa88ce..9f72fa7e5c 100644 --- a/lib/phy/upper/upper_phy_rx_results_notifier_wrapper.h +++ b/lib/phy/upper/upper_phy_rx_results_notifier_wrapper.h @@ -14,7 +14,7 @@ namespace srsran { -class rx_softbuffer_pool; +class rx_buffer_pool; /// \brief Wrapper class of the upper PHY receive results notifier. /// diff --git a/lib/phy/upper/upper_phy_rx_symbol_handler_impl.cpp b/lib/phy/upper/upper_phy_rx_symbol_handler_impl.cpp index 53204e030e..8e28f8f76b 100644 --- a/lib/phy/upper/upper_phy_rx_symbol_handler_impl.cpp +++ b/lib/phy/upper/upper_phy_rx_symbol_handler_impl.cpp @@ -11,20 +11,24 @@ #include "upper_phy_rx_symbol_handler_impl.h" #include "upper_phy_rx_results_notifier_wrapper.h" #include "srsran/phy/support/prach_buffer_context.h" -#include "srsran/phy/upper/unique_rx_softbuffer.h" +#include "srsran/phy/upper/channel_coding/ldpc/ldpc.h" +#include "srsran/phy/upper/channel_processors/pusch/formatters.h" +#include "srsran/phy/upper/rx_buffer_pool.h" +#include "srsran/phy/upper/unique_rx_buffer.h" #include "srsran/phy/upper/uplink_processor.h" #include "srsran/support/error_handling.h" +#include using namespace srsran; upper_phy_rx_symbol_handler_impl::upper_phy_rx_symbol_handler_impl(uplink_processor_pool& ul_processor_pool_, uplink_slot_pdu_repository& ul_pdu_repository_, - rx_softbuffer_pool& softbuffer_pool_, + rx_buffer_pool& rm_buffer_pool_, upper_phy_rx_results_notifier& rx_results_notifier_, srslog::basic_logger& logger_) : ul_processor_pool(ul_processor_pool_), ul_pdu_repository(ul_pdu_repository_), - softbuffer_pool(softbuffer_pool_), + rm_buffer_pool(rm_buffer_pool_), rx_results_notifier(rx_results_notifier_), logger(logger_) { @@ -95,6 +99,9 @@ void upper_phy_rx_symbol_handler_impl::handle_rx_symbol(const upper_phy_rx_symbo ul_processor.process_pucch(rx_results_notifier, grid, pucch_pdu); } } + + // Run PUSCH buffer housekeeping. + rm_buffer_pool.run_slot(context.slot); } void upper_phy_rx_symbol_handler_impl::handle_rx_prach_window(const prach_buffer_context& context, @@ -120,19 +127,24 @@ void upper_phy_rx_symbol_handler_impl::process_pusch(const uplink_processor::pus const pusch_processor::pdu_t& proc_pdu = pdu.pdu; // Temporal sanity check as PUSCH is only supported for data. Remove the check when the UCI is supported for PUSCH. - srsran_assert(proc_pdu.codeword.has_value(), "PUSCH PDU doesn't contain data. Currently, that mode is not supported"); + srsran_assert(proc_pdu.codeword.has_value(), + "PUSCH PDU doesn't contain data. Currently, that mode is not supported."); + + // Create buffer identifier. + trx_buffer_identifier id(proc_pdu.rnti, pdu.harq_id); - rx_softbuffer_identifier id; - id.rnti = static_cast(proc_pdu.rnti); - id.harq_ack_id = pdu.harq_id; + // Determine the number of codeblocks from the TBS and base graph. + unsigned nof_codeblocks = ldpc::compute_nof_codeblocks(pdu.tb_size.to_bits(), proc_pdu.codeword->ldpc_base_graph); - unsigned nof_codeblocks = - ldpc::compute_nof_codeblocks(units::bytes(pdu.tb_size).to_bits(), proc_pdu.codeword->ldpc_base_graph); + // Reserve receive buffer. + unique_rx_buffer buffer = rm_buffer_pool.reserve(slot, id, nof_codeblocks); - unique_rx_softbuffer buffer = softbuffer_pool.reserve_softbuffer(slot, id, nof_codeblocks); - if (buffer.is_valid()) { - auto payload = rx_payload_pool.acquire_payload_buffer(pdu.tb_size); - ul_processor.process_pusch(payload, std::move(buffer), rx_results_notifier, grid, pdu); + // Skip processing if the buffer is not valid. The pool shall log the context and the reason of the failure. + if (!buffer.is_valid()) { return; } + + // Retrieves transport block data and starts PUSCH processing. + auto payload = rx_payload_pool.acquire_payload_buffer(pdu.tb_size); + ul_processor.process_pusch(payload, std::move(buffer), rx_results_notifier, grid, pdu); } diff --git a/lib/phy/upper/upper_phy_rx_symbol_handler_impl.h b/lib/phy/upper/upper_phy_rx_symbol_handler_impl.h index 8f6861991a..0140e1288e 100644 --- a/lib/phy/upper/upper_phy_rx_symbol_handler_impl.h +++ b/lib/phy/upper/upper_phy_rx_symbol_handler_impl.h @@ -11,7 +11,7 @@ #pragma once #include "srsran/adt/circular_array.h" -#include "srsran/phy/upper/rx_softbuffer_pool.h" +#include "srsran/phy/upper/rx_buffer_pool.h" #include "srsran/phy/upper/uplink_slot_pdu_repository.h" #include "srsran/phy/upper/upper_phy_rx_symbol_handler.h" #include "srsran/srslog/srslog.h" @@ -58,7 +58,7 @@ class upper_phy_rx_symbol_handler_impl : public upper_phy_rx_symbol_handler public: upper_phy_rx_symbol_handler_impl(uplink_processor_pool& ul_processor_pool_, uplink_slot_pdu_repository& ul_pdu_repository_, - rx_softbuffer_pool& softbuffer_pool_, + rx_buffer_pool& buffer_pool_, upper_phy_rx_results_notifier& rx_results_notifier_, srslog::basic_logger& logger_); @@ -83,8 +83,8 @@ class upper_phy_rx_symbol_handler_impl : public upper_phy_rx_symbol_handler uplink_processor_pool& ul_processor_pool; /// Uplink slot PDU registry. uplink_slot_pdu_repository& ul_pdu_repository; - /// Softbuffer pool. - rx_softbuffer_pool& softbuffer_pool; + /// buffer pool. + rx_buffer_pool& rm_buffer_pool; /// Upper PHY results notifier. upper_phy_rx_results_notifier& rx_results_notifier; /// Upper PHY logger. diff --git a/lib/scheduler/ue_scheduling/ue_scheduler_impl.cpp b/lib/scheduler/ue_scheduling/ue_scheduler_impl.cpp index baa584abbb..32974dfbe8 100644 --- a/lib/scheduler/ue_scheduling/ue_scheduler_impl.cpp +++ b/lib/scheduler/ue_scheduling/ue_scheduler_impl.cpp @@ -195,7 +195,7 @@ void ue_scheduler_impl::handle_error_indication(slot_point // - The UE won't send the associated PUSCHs, which means that the lower layers will later forward CRC indications // with CRC=KO, and the respective UL HARQs will need to be retransmitted. No action needed. We do not cancel // the respective PUSCH grant, because it is important that the PUSCH "new_data" flag reaches the lower layers, - // telling them whether the UL HARQ softbuffer needs to be reset or not. + // telling them whether the UL HARQ buffer needs to be reset or not. // - Any UCI in the respective PUSCH will be reported as DTX, and the DL HARQ will be retransmitted. No action // needed. 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 d388e01cf6..4a953ab807 100644 --- a/tests/benchmarks/phy/upper/channel_processors/pdsch_processor_benchmark.cpp +++ b/tests/benchmarks/phy/upper/channel_processors/pdsch_processor_benchmark.cpp @@ -543,17 +543,15 @@ static void thread_process(pdsch_processor& proc, const pdsch_processor::pdu_t& // Compute the number of codeblocks. unsigned nof_codeblocks = ldpc::compute_nof_codeblocks(units::bytes(data.size()).to_bits(), config.ldpc_base_graph); - tx_buffer_pool_config softbuffer_pool_config; - softbuffer_pool_config.max_codeblock_size = ldpc::MAX_CODEBLOCK_SIZE; - softbuffer_pool_config.nof_buffers = 1; - softbuffer_pool_config.nof_codeblocks = pdsch_constants::CODEWORD_MAX_SIZE.value() / ldpc::MAX_MESSAGE_SIZE; - softbuffer_pool_config.expire_timeout_slots = 0; - softbuffer_pool_config.external_soft_bits = false; - std::shared_ptr softbuffer_pool = create_tx_buffer_pool(softbuffer_pool_config); - - tx_buffer_identifier softbuffer_id; - softbuffer_id.harq_ack_id = 0; - softbuffer_id.rnti = 0; + tx_buffer_pool_config buffer_pool_config; + buffer_pool_config.max_codeblock_size = ldpc::MAX_CODEBLOCK_SIZE; + buffer_pool_config.nof_buffers = 1; + buffer_pool_config.nof_codeblocks = pdsch_constants::CODEWORD_MAX_SIZE.value() / ldpc::MAX_MESSAGE_SIZE; + buffer_pool_config.expire_timeout_slots = 0; + buffer_pool_config.external_soft_bits = false; + std::shared_ptr buffer_pool = create_tx_buffer_pool(buffer_pool_config); + + trx_buffer_identifier buffer_id(0, 0); // Notify finish count. { @@ -582,17 +580,17 @@ static void thread_process(pdsch_processor& proc, const pdsch_processor::pdu_t& // Reset any notification. notifier.reset(); - unique_tx_buffer softbuffer = softbuffer_pool->reserve_buffer(config.slot, softbuffer_id, nof_codeblocks); + unique_tx_buffer rm_buffer = buffer_pool->reserve(config.slot, buffer_id, nof_codeblocks); // Process PDU. if (worker_pool) { bool success = - worker_pool->push_task([&proc, &grid, sb = std::move(softbuffer), ¬ifier, &data, &config]() mutable { + worker_pool->push_task([&proc, &grid, sb = std::move(rm_buffer), ¬ifier, &data, &config]() mutable { proc.process(grid->get_mapper(), std::move(sb), notifier, {data}, config); }); (void)success; } else { - proc.process(grid->get_mapper(), std::move(softbuffer), notifier, {data}, config); + proc.process(grid->get_mapper(), std::move(rm_buffer), notifier, {data}, config); } // Wait for the processor to finish. diff --git a/tests/benchmarks/phy/upper/channel_processors/pusch/pusch_decoder_hwacc_benchmark.cpp b/tests/benchmarks/phy/upper/channel_processors/pusch/pusch_decoder_hwacc_benchmark.cpp index 3869e3425a..5187bf1f80 100644 --- a/tests/benchmarks/phy/upper/channel_processors/pusch/pusch_decoder_hwacc_benchmark.cpp +++ b/tests/benchmarks/phy/upper/channel_processors/pusch/pusch_decoder_hwacc_benchmark.cpp @@ -18,8 +18,8 @@ #include "../../../lib/scheduler/support/tbs_calculator.h" #include "srsran/phy/upper/channel_processors/pusch/factories.h" #include "srsran/phy/upper/channel_processors/pusch/pusch_decoder_buffer.h" -#include "srsran/phy/upper/rx_softbuffer_pool.h" -#include "srsran/phy/upper/unique_rx_softbuffer.h" +#include "srsran/phy/upper/rx_buffer_pool.h" +#include "srsran/phy/upper/unique_rx_buffer.h" #include "srsran/support/test_utils.h" #ifdef DPDK_FOUND #include "srsran/hal/dpdk/bbdev/bbdev_acc.h" @@ -354,7 +354,7 @@ int main(int argc, char** argv) std::unique_ptr hwacc_decoder = hwacc_pusch_dec_factory->create(); TESTASSERT(hwacc_decoder); - rx_softbuffer_pool_config pool_config = {}; + rx_buffer_pool_config pool_config = {}; // Create a vector to hold the randomly generated LLRs. unsigned max_nof_ch_symbols = 14 * 270 * NRE; @@ -387,7 +387,7 @@ int main(int argc, char** argv) // The codeword is the concatenation of codeblocks. However, since codeblock sizes can vary slightly, we add some // extra margin. pool_config.max_codeblock_size = ldpc::MAX_CODEBLOCK_SIZE; - pool_config.max_softbuffers = 1; + pool_config.nof_buffers = 1; pool_config.max_nof_codeblocks = nof_codeblocks; pool_config.expire_timeout_slots = 10; pool_config.external_soft_bits = true; @@ -395,8 +395,8 @@ int main(int argc, char** argv) // Call the ACC100 hardware-accelerator PUSCH decoder function. uint64_t total_acc100_time = 0; - // Create Rx softbuffer pool. - std::unique_ptr pool_acc100 = create_rx_softbuffer_pool(pool_config); + // Create Rx buffer pool. + std::unique_ptr pool_acc100 = create_rx_buffer_pool(pool_config); TESTASSERT(pool_acc100); pusch_decoder::configuration dec_cfg = {}; @@ -411,8 +411,8 @@ int main(int argc, char** argv) dec_cfg.Nref = cfg.Nref; dec_cfg.nof_layers = cfg.nof_layers; - // Reserve softbuffer. - unique_rx_softbuffer softbuffer_acc100 = pool_acc100->reserve_softbuffer({}, {}, nof_codeblocks); + // Reserve tbuffer. + unique_rx_buffer softbuffer_acc100 = pool_acc100->reserve({}, {}, nof_codeblocks); TESTASSERT(softbuffer_acc100.is_valid()); // Force all CRCs to false to test LLR combining. @@ -435,9 +435,9 @@ int main(int argc, char** argv) // Call the software PUSCH decoder function. uint64_t total_gen_time = 0; - // Create Rx softbuffer pool. - pool_config.external_soft_bits = false; - std::unique_ptr pool_cpu = create_rx_softbuffer_pool(pool_config); + // Create Rx buffer pool. + pool_config.external_soft_bits = false; + std::unique_ptr pool_cpu = create_rx_buffer_pool(pool_config); TESTASSERT(pool_cpu); // Prepare decoder configuration. @@ -452,7 +452,7 @@ int main(int argc, char** argv) dec_cfg.nof_layers = cfg.nof_layers; // Reserve softbuffer. - unique_rx_softbuffer softbuffer_cpu = pool_cpu->reserve_softbuffer({}, {}, nof_codeblocks); + unique_rx_buffer softbuffer_cpu = pool_cpu->reserve({}, {}, nof_codeblocks); TESTASSERT(softbuffer_cpu.is_valid()); // Force all CRCs to false to test LLR combining. 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 4f068033ad..61ac76b8d0 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 @@ -8,7 +8,7 @@ * */ -#include "../../../lib/phy/upper/rx_softbuffer_pool_impl.h" +#include "../../../lib/phy/upper/rx_buffer_pool_impl.h" #include "../../../lib/scheduler/support/tbs_calculator.h" #include "srsran/phy/support/resource_grid_reader.h" #include "srsran/phy/support/resource_grid_writer.h" @@ -508,20 +508,19 @@ static void thread_process(pusch_processor& proc, // Compute the number of codeblocks. unsigned nof_codeblocks = ldpc::compute_nof_codeblocks(units::bits(tbs), config.codeword.value().ldpc_base_graph); - // Softbuffer pool configuration. - rx_softbuffer_pool_config softbuffer_config = {}; - softbuffer_config.max_softbuffers = 1; - softbuffer_config.max_nof_codeblocks = nof_codeblocks; - softbuffer_config.max_codeblock_size = ldpc::MAX_CODEBLOCK_SIZE; - softbuffer_config.expire_timeout_slots = + // Buffer pool configuration. + rx_buffer_pool_config buffer_pool_config = {}; + buffer_pool_config.nof_buffers = 1; + buffer_pool_config.max_nof_codeblocks = nof_codeblocks; + buffer_pool_config.max_codeblock_size = ldpc::MAX_CODEBLOCK_SIZE; + buffer_pool_config.expire_timeout_slots = 100 * get_nof_slots_per_subframe(to_subcarrier_spacing(config.slot.numerology())); - softbuffer_config.external_soft_bits = false; + buffer_pool_config.external_soft_bits = false; - rx_softbuffer_identifier softbuffer_id = {}; - softbuffer_id.rnti = config.rnti; + trx_buffer_identifier buffer_id = trx_buffer_identifier(config.rnti, 0); - // Create softbuffer pool. - std::unique_ptr softbuffer_pool = create_rx_softbuffer_pool(softbuffer_config); + // Create buffer pool. + std::unique_ptr buffer_pool = create_rx_buffer_pool(buffer_pool_config); // Prepare receive data buffer. std::vector data(tbs / 8); @@ -548,21 +547,21 @@ static void thread_process(pusch_processor& proc, pending_count--; } - // Reserve softbuffer. - unique_rx_softbuffer softbuffer = softbuffer_pool->reserve_softbuffer(config.slot, softbuffer_id, nof_codeblocks); + // Reserve buffer. + unique_rx_buffer rm_buffer = buffer_pool->reserve(config.slot, buffer_id, nof_codeblocks); // Reset notifier. result_notifier.reset(); // Process PDU. if (executor) { - if (not executor->execute([&proc, &data, &softbuffer, &result_notifier, &grid, config]() { - proc.process(data, std::move(softbuffer), result_notifier, grid, config); + if (not executor->execute([&proc, &data, &rm_buffer, &result_notifier, &grid, config]() { + proc.process(data, std::move(rm_buffer), result_notifier, grid, config); })) { fmt::print("Failed to enqueue task.\n"); } } else { - proc.process(data, std::move(softbuffer), result_notifier, grid, config); + proc.process(data, std::move(rm_buffer), result_notifier, grid, config); } // Wait for finish the task. diff --git a/tests/unittests/fapi_adaptor/phy/fapi_to_phy_translator_test.cpp b/tests/unittests/fapi_adaptor/phy/fapi_to_phy_translator_test.cpp index 7303273333..3e89893ed3 100644 --- a/tests/unittests/fapi_adaptor/phy/fapi_to_phy_translator_test.cpp +++ b/tests/unittests/fapi_adaptor/phy/fapi_to_phy_translator_test.cpp @@ -12,7 +12,7 @@ #include "../../fapi/validators/helpers.h" #include "../../phy/support/resource_grid_test_doubles.h" #include "../../phy/upper/downlink_processor_test_doubles.h" -#include "../../phy/upper/tx_softbuffer_pool_test_doubles.h" +#include "../../phy/upper/tx_buffer_pool_test_doubles.h" #include "../../phy/upper/uplink_request_processor_test_doubles.h" #include "srsran/fapi_adaptor/precoding_matrix_table_generator.h" #include "srsran/fapi_adaptor/uci_part2_correspondence_generator.h" @@ -117,21 +117,20 @@ class fapi_to_phy_translator_fixture : public ::testing::Test uplink_pdu_validator_dummy ul_pdu_validator; slot_error_message_notifier_spy error_notifier_spy; manual_task_worker worker; - tx_softbuffer_pool_spy softbuffer_pool_spy; + tx_buffer_pool_spy buffer_pool_spy; fapi_to_phy_translator_config config = {sector_id, headroom_in_slots, scs, scs, &prach_cfg, &carrier_cfg, {0}}; fapi_to_phy_translator_dependencies dependencies = { &srslog::fetch_basic_logger("FAPI"), &dl_processor_pool, &rg_pool, &dl_pdu_validator, - &softbuffer_pool_spy, + &buffer_pool_spy, &ul_request_processor, &rg_pool, &pdu_repo, &ul_pdu_validator, std::move(std::get>(generate_precoding_matrix_tables(1))), - std::move(std::get>(generate_uci_part2_correspondence(1))), - &worker}; + std::move(std::get>(generate_uci_part2_correspondence(1)))}; fapi_to_phy_translator translator; public: @@ -148,14 +147,13 @@ TEST_F(fapi_to_phy_translator_fixture, downlink_processor_is_not_configured_on_n ASSERT_FALSE(dl_processor_pool.processor(slot).has_configure_resource_grid_method_been_called()); ASSERT_FALSE(grid.has_set_all_zero_method_been_called()); - // Assert that the softbuffer pool ran the slot. - auto& run_slot_entries = softbuffer_pool_spy.get_run_slot_entries(); - ASSERT_EQ(run_slot_entries.size(), 1); - ASSERT_EQ(run_slot_entries.front(), slot); + // Assert that the transmit buffer pool did not run the slot. + auto& run_slot_entries = buffer_pool_spy.get_run_slot_entries(); + ASSERT_TRUE(run_slot_entries.empty()); - // Assert that no softbuffer reservation was done. - auto& reserve_softbuffer_entries = softbuffer_pool_spy.get_reserve_softbuffer_entries(); - ASSERT_TRUE(reserve_softbuffer_entries.empty()); + // Assert that no buffer reservation was done. + auto& reserve_buffer_entries = buffer_pool_spy.get_reserve_entries(); + ASSERT_TRUE(reserve_buffer_entries.empty()); ASSERT_FALSE(error_notifier_spy.has_on_error_indication_been_called()); } @@ -174,6 +172,10 @@ TEST_F(fapi_to_phy_translator_fixture, downlink_processor_is_configured_on_new_d // Assert that the downlink processor is configured. ASSERT_TRUE(dl_processor_pool.processor(slot).has_configure_resource_grid_method_been_called()); + // Assert that the transmit buffer pool did not run the slot. + auto& run_slot_entries = buffer_pool_spy.get_run_slot_entries(); + ASSERT_TRUE(run_slot_entries.empty()); + // Assert that the resource grid has not been set to zero. ASSERT_FALSE(grid.has_set_all_zero_method_been_called()); ASSERT_FALSE(error_notifier_spy.has_on_error_indication_been_called()); diff --git a/tests/unittests/phy/upper/CMakeLists.txt b/tests/unittests/phy/upper/CMakeLists.txt index 0cf43d4ded..84cd32e864 100644 --- a/tests/unittests/phy/upper/CMakeLists.txt +++ b/tests/unittests/phy/upper/CMakeLists.txt @@ -34,9 +34,9 @@ add_executable(log_likelihood_ratio_test log_likelihood_ratio_test.cpp) target_link_libraries(log_likelihood_ratio_test log_likelihood_ratio srslog) add_test(log_likelihood_ratio_test log_likelihood_ratio_test) -add_executable(rx_softbuffer_pool_test rx_softbuffer_pool_test.cpp) -target_link_libraries(rx_softbuffer_pool_test srsran_upper_phy_support srslog) -add_test(rx_softbuffer_pool_test rx_softbuffer_pool_test) +add_executable(rx_buffer_pool_test rx_buffer_pool_test.cpp) +target_link_libraries(rx_buffer_pool_test srsran_upper_phy_support srslog gtest srsran_support) +gtest_discover_tests(rx_buffer_pool_test) add_executable(uplink_processor_test uplink_processor_test.cpp) target_link_libraries(uplink_processor_test srsran_uplink_processor srslog gtest gtest_main) diff --git a/tests/unittests/phy/upper/channel_processors/pdsch_encoder_test.cpp b/tests/unittests/phy/upper/channel_processors/pdsch_encoder_test.cpp index 62e5579e2e..c60f983969 100644 --- a/tests/unittests/phy/upper/channel_processors/pdsch_encoder_test.cpp +++ b/tests/unittests/phy/upper/channel_processors/pdsch_encoder_test.cpp @@ -42,17 +42,15 @@ int main() std::shared_ptr pdsch_encoder = encoder_factory->create(); TESTASSERT(pdsch_encoder); - tx_buffer_pool_config softbuffer_pool_config; - softbuffer_pool_config.max_codeblock_size = ldpc::MAX_CODEBLOCK_SIZE; - softbuffer_pool_config.nof_buffers = 1; - softbuffer_pool_config.nof_codeblocks = pdsch_constants::CODEWORD_MAX_SIZE.value() / ldpc::MAX_MESSAGE_SIZE; - softbuffer_pool_config.expire_timeout_slots = 0; - softbuffer_pool_config.external_soft_bits = false; - std::shared_ptr softbuffer_pool = create_tx_buffer_pool(softbuffer_pool_config); - - tx_buffer_identifier softbuffer_id; - softbuffer_id.harq_ack_id = 0; - softbuffer_id.rnti = 0; + tx_buffer_pool_config buffer_pool_config; + buffer_pool_config.max_codeblock_size = ldpc::MAX_CODEBLOCK_SIZE; + buffer_pool_config.nof_buffers = 1; + buffer_pool_config.nof_codeblocks = pdsch_constants::CODEWORD_MAX_SIZE.value() / ldpc::MAX_MESSAGE_SIZE; + buffer_pool_config.expire_timeout_slots = 0; + buffer_pool_config.external_soft_bits = false; + std::shared_ptr rm_buffer_pool = create_tx_buffer_pool(buffer_pool_config); + + trx_buffer_identifier buffer_id(0, 0); for (const test_case_t& test_case : pdsch_encoder_test_data) { // Load the TB. @@ -71,7 +69,7 @@ int main() unsigned nof_codeblocks = ldpc::compute_nof_codeblocks(units::bits(transport_block.size() * 8), test_case.config.base_graph); - unique_tx_buffer softbuffer = softbuffer_pool->reserve_buffer(slot_point(), softbuffer_id, nof_codeblocks); + unique_tx_buffer rm_buffer = rm_buffer_pool->reserve(slot_point(), buffer_id, nof_codeblocks); pdsch_encoder::configuration config; config.new_data = true; @@ -83,14 +81,14 @@ int main() config.nof_ch_symbols = test_case.config.nof_ch_symbols; // Encode the TB. - pdsch_encoder->encode(codeword, softbuffer.get(), transport_block, config); + pdsch_encoder->encode(codeword, rm_buffer.get(), transport_block, config); // Assert encoded data. TESTASSERT_EQ(span(codeword), span(expected_codeword)); - // Repeat test reusing the softbuffer. + // Repeat test reusing the buffer. config.new_data = false; - pdsch_encoder->encode(codeword, softbuffer.get(), transport_block, config); + pdsch_encoder->encode(codeword, rm_buffer.get(), transport_block, config); TESTASSERT_EQ(span(codeword), span(expected_codeword)); } } diff --git a/tests/unittests/phy/upper/channel_processors/pdsch_encoder_test_doubles.h b/tests/unittests/phy/upper/channel_processors/pdsch_encoder_test_doubles.h index d5d96c6281..9d318ee8db 100644 --- a/tests/unittests/phy/upper/channel_processors/pdsch_encoder_test_doubles.h +++ b/tests/unittests/phy/upper/channel_processors/pdsch_encoder_test_doubles.h @@ -20,7 +20,7 @@ class pdsch_encoder_spy : public pdsch_encoder public: void encode(span codeword, - tx_buffer& softbuffer, + tx_buffer& rm_buffer, span transport_block, const configuration& cfg) override { // Generate new entry. diff --git a/tests/unittests/phy/upper/channel_processors/pdsch_processor_test_doubles.h b/tests/unittests/phy/upper/channel_processors/pdsch_processor_test_doubles.h index 28cf87172c..a05f72997d 100644 --- a/tests/unittests/phy/upper/channel_processors/pdsch_processor_test_doubles.h +++ b/tests/unittests/phy/upper/channel_processors/pdsch_processor_test_doubles.h @@ -23,7 +23,7 @@ class pdsch_processor_spy : public pdsch_processor public: void process(resource_grid_mapper& mapper, - unique_tx_buffer softbuffer, + unique_tx_buffer rm_buffer, pdsch_processor_notifier& notifier, static_vector, MAX_NOF_TRANSPORT_BLOCKS> data, const pdu_t& pdu) override diff --git a/tests/unittests/phy/upper/channel_processors/pdsch_processor_unittest.cpp b/tests/unittests/phy/upper/channel_processors/pdsch_processor_unittest.cpp index 8f18aadbb8..730eb4b391 100644 --- a/tests/unittests/phy/upper/channel_processors/pdsch_processor_unittest.cpp +++ b/tests/unittests/phy/upper/channel_processors/pdsch_processor_unittest.cpp @@ -10,7 +10,7 @@ #include "../../support/resource_grid_test_doubles.h" #include "../signal_processors/dmrs_pdsch_processor_test_doubles.h" -#include "../tx_softbuffer_test_doubles.h" +#include "../tx_buffer_test_doubles.h" #include "pdsch_encoder_test_doubles.h" #include "pdsch_modulator_test_doubles.h" #include "pdsch_processor_test_doubles.h" @@ -202,11 +202,11 @@ TEST_P(PdschProcessorFixture, UnitTest) dmrs_spy->reset(); notifier.reset(); - tx_buffer_spy softbuffer_spy(0, 0); - unique_tx_buffer softbuffer(softbuffer_spy); + tx_buffer_spy rm_buffer_spy(0, 0); + unique_tx_buffer rm_buffer(rm_buffer_spy); // Process PDU. - pdsch->process(mapper_dummy, std::move(softbuffer), notifier, data, pdu); + pdsch->process(mapper_dummy, std::move(rm_buffer), notifier, data, pdu); // Wait for the processor to finish. notifier.wait_for_finished(); diff --git a/tests/unittests/phy/upper/channel_processors/pdsch_processor_validator_test.cpp b/tests/unittests/phy/upper/channel_processors/pdsch_processor_validator_test.cpp index e7001c2ba3..3126ac6887 100644 --- a/tests/unittests/phy/upper/channel_processors/pdsch_processor_validator_test.cpp +++ b/tests/unittests/phy/upper/channel_processors/pdsch_processor_validator_test.cpp @@ -9,8 +9,8 @@ */ #include "../../support/resource_grid_mapper_test_doubles.h" -#include "../rx_softbuffer_test_doubles.h" -#include "../tx_softbuffer_test_doubles.h" +#include "../rx_buffer_test_doubles.h" +#include "../tx_buffer_test_doubles.h" #include "pdsch_processor_test_doubles.h" #include "srsran/phy/support/support_factories.h" #include "srsran/phy/upper/channel_processors/channel_processor_factories.h" @@ -270,15 +270,15 @@ TEST_P(pdschProcessorFixture, pdschProcessorValidatorDeathTest) // Prepare receive data. std::vector data; - // Prepare softbuffer. - tx_buffer_spy softbuffer_spy(ldpc::MAX_CODEBLOCK_SIZE, 0); - unique_tx_buffer softbuffer(softbuffer_spy); + // Prepare buffer. + tx_buffer_spy rm_buffer_spy(ldpc::MAX_CODEBLOCK_SIZE, 0); + unique_tx_buffer rm_buffer(rm_buffer_spy); pdsch_processor_notifier_spy notifier_spy; // Process pdsch PDU. #ifdef ASSERTS_ENABLED - ASSERT_DEATH({ pdsch_proc->process(*mapper, std::move(softbuffer), notifier_spy, {data}, param.get_pdu()); }, + ASSERT_DEATH({ pdsch_proc->process(*mapper, std::move(rm_buffer), notifier_spy, {data}, param.get_pdu()); }, param.expr); #endif // ASSERTS_ENABLED } diff --git a/tests/unittests/phy/upper/channel_processors/pdsch_processor_vectortest.cpp b/tests/unittests/phy/upper/channel_processors/pdsch_processor_vectortest.cpp index 294f59274c..a5d04fb88f 100644 --- a/tests/unittests/phy/upper/channel_processors/pdsch_processor_vectortest.cpp +++ b/tests/unittests/phy/upper/channel_processors/pdsch_processor_vectortest.cpp @@ -132,8 +132,8 @@ class PdschProcessorFixture : public ::testing::TestWithParam pdsch_proc; // PDSCH validator. std::unique_ptr pdu_validator; - // Softbuffer pool. - std::unique_ptr softbuffer_pool; + // PDSCH rate matcher buffer pool. + std::unique_ptr rm_buffer_pool; // Worker pool. std::unique_ptr> worker_pool; std::unique_ptr> executor; @@ -155,15 +155,15 @@ class PdschProcessorFixture : public ::testing::TestWithParamcreate_validator(); ASSERT_NE(pdu_validator, nullptr) << "Cannot create PDSCH validator"; - // Create softbuffer pool. - tx_buffer_pool_config softbuffer_pool_config; - softbuffer_pool_config.max_codeblock_size = ldpc::MAX_CODEBLOCK_SIZE; - softbuffer_pool_config.nof_buffers = 1; - softbuffer_pool_config.nof_codeblocks = pdsch_constants::CODEWORD_MAX_SIZE.value() / ldpc::MAX_MESSAGE_SIZE; - softbuffer_pool_config.expire_timeout_slots = 0; - softbuffer_pool_config.external_soft_bits = false; - softbuffer_pool = create_tx_buffer_pool(softbuffer_pool_config); - ASSERT_NE(softbuffer_pool, nullptr) << "Cannot create softbuffer pool"; + // Create buffer pool. + tx_buffer_pool_config buffer_pool_config; + buffer_pool_config.max_codeblock_size = ldpc::MAX_CODEBLOCK_SIZE; + buffer_pool_config.nof_buffers = 1; + buffer_pool_config.nof_codeblocks = pdsch_constants::CODEWORD_MAX_SIZE.value() / ldpc::MAX_MESSAGE_SIZE; + buffer_pool_config.expire_timeout_slots = 0; + buffer_pool_config.external_soft_bits = false; + rm_buffer_pool = create_tx_buffer_pool(buffer_pool_config); + ASSERT_NE(rm_buffer_pool, nullptr) << "Cannot create buffer pool"; } void TearDown() override @@ -202,17 +202,15 @@ TEST_P(PdschProcessorFixture, PdschProcessorVectortest) // Make sure the configuration is valid. ASSERT_TRUE(pdu_validator->is_valid(config)); - tx_buffer_identifier softbuffer_id; - softbuffer_id.harq_ack_id = 0; - softbuffer_id.rnti = 0; + trx_buffer_identifier buffer_id(0, 0); unsigned nof_codeblocks = ldpc::compute_nof_codeblocks(units::bits(transport_block.size() * 8), config.ldpc_base_graph); - unique_tx_buffer softbuffer = softbuffer_pool->reserve_buffer(slot_point(), softbuffer_id, nof_codeblocks); + unique_tx_buffer rm_buffer = rm_buffer_pool->reserve(slot_point(), buffer_id, nof_codeblocks); // Process PDSCH. - pdsch_proc->process(*mapper, std::move(softbuffer), notifier_spy, transport_blocks, config); + pdsch_proc->process(*mapper, std::move(rm_buffer), notifier_spy, transport_blocks, config); // Waits for the processor to finish. notifier_spy.wait_for_finished(); diff --git a/tests/unittests/phy/upper/channel_processors/pusch/pusch_decoder_test_doubles.h b/tests/unittests/phy/upper/channel_processors/pusch/pusch_decoder_test_doubles.h index e48f255427..aeb62be80e 100644 --- a/tests/unittests/phy/upper/channel_processors/pusch/pusch_decoder_test_doubles.h +++ b/tests/unittests/phy/upper/channel_processors/pusch/pusch_decoder_test_doubles.h @@ -25,7 +25,7 @@ class pusch_decoder_spy : public pusch_decoder struct entry_t { span transport_block; pusch_decoder_result stats; - unique_rx_softbuffer softbuffer; + unique_rx_buffer rm_buffer; pusch_decoder_buffer_spy input; configuration config; pusch_decoder_notifier* notifier; @@ -34,7 +34,7 @@ class pusch_decoder_spy : public pusch_decoder ~pusch_decoder_spy() { srsran_assert(entries.empty(), "Entries must be cleared."); } pusch_decoder_buffer& new_data(span transport_block, - unique_rx_softbuffer softbuffer, + unique_rx_buffer rm_buffer, pusch_decoder_notifier& notifier, const configuration& cfg) override { @@ -42,7 +42,7 @@ class pusch_decoder_spy : public pusch_decoder entry_t& entry = entries.back(); entry.transport_block = transport_block; entry.stats = {}; - entry.softbuffer = std::move(softbuffer); + entry.rm_buffer = std::move(rm_buffer); entry.notifier = ¬ifier; entry.config = cfg; @@ -64,4 +64,4 @@ class pusch_decoder_spy : public pusch_decoder PHY_SPY_FACTORY_TEMPLATE(pusch_decoder); -} // namespace srsran \ No newline at end of file +} // namespace srsran diff --git a/tests/unittests/phy/upper/channel_processors/pusch/pusch_decoder_vectortest.cpp b/tests/unittests/phy/upper/channel_processors/pusch/pusch_decoder_vectortest.cpp index e7028a6199..83cf261c85 100644 --- a/tests/unittests/phy/upper/channel_processors/pusch/pusch_decoder_vectortest.cpp +++ b/tests/unittests/phy/upper/channel_processors/pusch/pusch_decoder_vectortest.cpp @@ -21,8 +21,8 @@ #include "pusch_decoder_test_data.h" #include "srsran/phy/upper/channel_processors/pusch/factories.h" #include "srsran/phy/upper/channel_processors/pusch/pusch_decoder_buffer.h" -#include "srsran/phy/upper/rx_softbuffer_pool.h" -#include "srsran/phy/upper/unique_rx_softbuffer.h" +#include "srsran/phy/upper/rx_buffer_pool.h" +#include "srsran/phy/upper/unique_rx_buffer.h" #include "srsran/support/test_utils.h" #ifdef HWACC_PUSCH_ENABLED #include "srsran/hal/dpdk/bbdev/bbdev_acc.h" @@ -259,7 +259,7 @@ int main(int argc, char** argv) std::unique_ptr decoder = pusch_dec_factory->create(); TESTASSERT(decoder); - rx_softbuffer_pool_config pool_config = {}; + rx_buffer_pool_config pool_config = {}; for (const auto& test_data : pusch_decoder_test_data) { segmenter_config cfg = test_data.config; @@ -283,7 +283,7 @@ int main(int argc, char** argv) // The codeword is the concatenation of codeblocks. However, since codeblock sizes can vary slightly, we add some // extra margin. pool_config.max_codeblock_size = static_cast(std::round(cws * 5 / nof_codeblocks)); - pool_config.max_softbuffers = 1; + pool_config.nof_buffers = 1; pool_config.max_nof_codeblocks = nof_codeblocks; pool_config.expire_timeout_slots = 10; pool_config.external_soft_bits = false; @@ -293,8 +293,8 @@ int main(int argc, char** argv) } #endif // HWACC_PUSCH_ENABLED - // Create Rx softbuffer pool. - std::unique_ptr pool = create_rx_softbuffer_pool(pool_config); + // Create Rx buffer pool. + std::unique_ptr pool = create_rx_buffer_pool(pool_config); TESTASSERT(pool); pusch_decoder::configuration dec_cfg = {}; @@ -314,17 +314,16 @@ int main(int argc, char** argv) dec_cfg.Nref = cfg.Nref; dec_cfg.nof_layers = cfg.nof_layers; - // Reserve softbuffer. - unique_rx_softbuffer softbuffer = pool->reserve_softbuffer({}, {}, nof_codeblocks); - TESTASSERT(softbuffer.is_valid()); + // Reserve buffer. + unique_rx_buffer buffer = pool->reserve({}, trx_buffer_identifier(0, 0), nof_codeblocks); + TESTASSERT(buffer.is_valid()); // Reset code blocks CRCs. - softbuffer.get().reset_codeblocks_crc(); + buffer.get().reset_codeblocks_crc(); // Setup decoder for new data. pusch_decoder_notifier_spy decoder_notifier_spy; - pusch_decoder_buffer& decoder_buffer = - decoder->new_data(rx_tb, std::move(softbuffer), decoder_notifier_spy, dec_cfg); + pusch_decoder_buffer& decoder_buffer = decoder->new_data(rx_tb, std::move(buffer), decoder_notifier_spy, dec_cfg); // Feed codeword. decoder_buffer.on_new_softbits(span(llrs_all).subspan(cw_offset, cws)); diff --git a/tests/unittests/phy/upper/channel_processors/pusch/pusch_processor_test_doubles.h b/tests/unittests/phy/upper/channel_processors/pusch/pusch_processor_test_doubles.h index d898516193..f484d3d920 100644 --- a/tests/unittests/phy/upper/channel_processors/pusch/pusch_processor_test_doubles.h +++ b/tests/unittests/phy/upper/channel_processors/pusch/pusch_processor_test_doubles.h @@ -18,7 +18,7 @@ class pusch_processor_dummy : public pusch_processor { public: void process(span data, - unique_rx_softbuffer softbuffer, + unique_rx_buffer buffer, pusch_processor_result_notifier& notifier, const resource_grid_reader& grid, const pdu_t& pdu) override diff --git a/tests/unittests/phy/upper/channel_processors/pusch/pusch_processor_unittest.cpp b/tests/unittests/phy/upper/channel_processors/pusch/pusch_processor_unittest.cpp index b0f0a81192..6a7e0fddec 100644 --- a/tests/unittests/phy/upper/channel_processors/pusch/pusch_processor_unittest.cpp +++ b/tests/unittests/phy/upper/channel_processors/pusch/pusch_processor_unittest.cpp @@ -9,7 +9,7 @@ */ #include "../../../support/resource_grid_test_doubles.h" -#include "../../rx_softbuffer_test_doubles.h" +#include "../../rx_buffer_test_doubles.h" #include "../../signal_processors/dmrs_pusch_estimator_test_doubles.h" #include "../uci/uci_decoder_test_doubles.h" #include "pusch_decoder_test_doubles.h" @@ -351,16 +351,16 @@ TEST_P(PuschProcessorFixture, PuschProcessorUnittest) ulsch_info.nof_csi_part1_bits.value(), ulsch_info.nof_csi_part2_bits.value()); - // Create receive softbuffer. - rx_softbuffer_spy softbuffer_spy; - unique_rx_softbuffer softbuffer(softbuffer_spy); + // Create receive buffer. + rx_buffer_spy rm_buffer_spy; + unique_rx_buffer rm_buffer(rm_buffer_spy); // Resource grid spy. resource_grid_reader_spy rg_spy; // Process PDU. pusch_processor_result_notifier_spy result_notifier; - pusch_proc->process(transport_block, std::move(softbuffer), result_notifier, rg_spy, pdu); + pusch_proc->process(transport_block, std::move(rm_buffer), result_notifier, rg_spy, pdu); // Extract results. const auto& sch_entries = result_notifier.get_sch_entries(); @@ -369,9 +369,9 @@ TEST_P(PuschProcessorFixture, PuschProcessorUnittest) // Make sure PDU is valid. ASSERT_TRUE(validator->is_valid(pdu)); - // Calling resource grid and softbuffer methods are not permitted. + // Calling resource grid and buffer methods are not permitted. ASSERT_EQ(0, rg_spy.get_count()); - ASSERT_EQ(0, softbuffer_spy.get_total_count()); + ASSERT_EQ(0, rm_buffer_spy.get_total_count()); // Assert channel estimator inputs. ASSERT_EQ(1, estimator_spy->get_entries().size()); @@ -429,7 +429,7 @@ TEST_P(PuschProcessorFixture, PuschProcessorUnittest) const pusch_decoder_spy::entry_t& decoder_entry = decoder_spy->get_entries().front(); ASSERT_EQ(decoder_entry.transport_block.data(), transport_block.data()); ASSERT_EQ(decoder_entry.transport_block.size(), transport_block.size()); - ASSERT_EQ(&softbuffer_spy, &decoder_entry.softbuffer.get()); + ASSERT_EQ(&rm_buffer_spy, &decoder_entry.rm_buffer.get()); ASSERT_EQ(span(demux_entry.sch_data), decoder_entry.input.get_data()); ASSERT_EQ(pdu.codeword.value().ldpc_base_graph, decoder_entry.config.base_graph); ASSERT_EQ(pdu.mcs_descr.modulation, decoder_entry.config.mod); @@ -501,16 +501,16 @@ TEST_P(PuschProcessorFixture, HealthTestFormatterInfo) std::vector transport_block(tbs_dist(rgen)); std::generate(transport_block.begin(), transport_block.end(), [&]() { return static_cast(rgen()); }); - // Create receive softbuffer. - rx_softbuffer_spy softbuffer_spy; - unique_rx_softbuffer softbuffer(softbuffer_spy); + // Create receive buffer. + rx_buffer_spy rm_buffer_spy; + unique_rx_buffer rm_buffer(rm_buffer_spy); // Resource grid spy. resource_grid_reader_spy rg_spy; // Process PDU. pusch_processor_result_notifier_spy result_notifier; - pusch_proc_info->process(transport_block, std::move(softbuffer), result_notifier, rg_spy, pdu); + pusch_proc_info->process(transport_block, std::move(rm_buffer), result_notifier, rg_spy, pdu); // Clear decoder spy entries - It makes sure the soft buffer is unlocked before destroying the pool. decoder_spy_info->clear(); @@ -522,16 +522,16 @@ TEST_P(PuschProcessorFixture, HealthTestFormatterDebug) std::vector transport_block(tbs_dist(rgen)); std::generate(transport_block.begin(), transport_block.end(), [&]() { return static_cast(rgen()); }); - // Create receive softbuffer. - rx_softbuffer_spy softbuffer_spy; - unique_rx_softbuffer softbuffer(softbuffer_spy); + // Create receive buffer. + rx_buffer_spy rm_buffer_spy; + unique_rx_buffer rm_buffer(rm_buffer_spy); // Resource grid spy. resource_grid_reader_spy rg_spy; // Process PDU. pusch_processor_result_notifier_spy result_notifier; - pusch_proc_debug->process(transport_block, std::move(softbuffer), result_notifier, rg_spy, pdu); + pusch_proc_debug->process(transport_block, std::move(rm_buffer), result_notifier, rg_spy, pdu); // Clear decoder spy entries - It makes sure the soft buffer is unlocked before destroying the pool. decoder_spy_debug->clear(); 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 54245300fd..adcc988871 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 @@ -9,7 +9,7 @@ */ #include "../../../support/resource_grid_test_doubles.h" -#include "../../rx_softbuffer_test_doubles.h" +#include "../../rx_buffer_test_doubles.h" #include "pusch_processor_result_test_doubles.h" #include "srsran/phy/upper/channel_processors/pusch/factories.h" #include "srsran/phy/upper/channel_processors/pusch/formatters.h" @@ -276,14 +276,14 @@ TEST_P(PuschProcessorFixture, PuschProcessorValidatortest) // Prepare receive data. std::vector data; - // Prepare softbuffer. - rx_softbuffer_spy softbuffer_spy(ldpc::MAX_CODEBLOCK_SIZE, 0); - unique_rx_softbuffer softbuffer(softbuffer_spy); + // Prepare buffer. + rx_buffer_spy rm_buffer_spy(ldpc::MAX_CODEBLOCK_SIZE, 0); + unique_rx_buffer rm_buffer(rm_buffer_spy); // Process PUSCH PDU. #ifdef ASSERTS_ENABLED pusch_processor_result_notifier_spy result_notifier_spy; - ASSERT_DEATH({ pusch_proc->process(data, std::move(softbuffer), result_notifier_spy, grid, param.get_pdu()); }, + ASSERT_DEATH({ pusch_proc->process(data, std::move(rm_buffer), result_notifier_spy, grid, param.get_pdu()); }, param.expr); #endif // ASSERTS_ENABLED } 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 7a4f2b228c..771ec9118d 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 @@ -8,7 +8,7 @@ * */ -#include "../../rx_softbuffer_test_doubles.h" +#include "../../rx_buffer_test_doubles.h" #include "pusch_processor_result_test_doubles.h" #include "pusch_processor_test_data.h" #include "srsran/phy/upper/channel_processors/pusch/factories.h" @@ -171,18 +171,18 @@ TEST_P(PuschProcessorFixture, PuschProcessorVectortest) // Prepare receive data. std::vector data(expected_data.size()); - // Prepare softbuffer. - rx_softbuffer_spy softbuffer_spy(ldpc::MAX_CODEBLOCK_SIZE, - ldpc::compute_nof_codeblocks(units::bytes(expected_data.size()).to_bits(), - config.codeword.value().ldpc_base_graph)); - unique_rx_softbuffer softbuffer(softbuffer_spy); + // Prepare buffer. + rx_buffer_spy rm_buffer_spy(ldpc::MAX_CODEBLOCK_SIZE, + ldpc::compute_nof_codeblocks(units::bytes(expected_data.size()).to_bits(), + config.codeword.value().ldpc_base_graph)); + unique_rx_buffer rm_buffer(rm_buffer_spy); // Make sure the configuration is valid. ASSERT_TRUE(pdu_validator->is_valid(config)); // Process PUSCH PDU. pusch_processor_result_notifier_spy results_notifier; - pusch_proc->process(data, std::move(softbuffer), results_notifier, grid, config); + pusch_proc->process(data, std::move(rm_buffer), results_notifier, grid, config); // Verify UL-SCH decode results. const auto& sch_entries = results_notifier.get_sch_entries(); @@ -250,18 +250,18 @@ TEST_P(PuschProcessorFixture, PuschProcessorVectortestZero) // Prepare receive data. std::vector data(test_case.sch_data.read().size()); - // Prepare softbuffer. - rx_softbuffer_spy softbuffer_spy( + // Prepare buffer. + rx_buffer_spy rm_buffer_spy( ldpc::MAX_CODEBLOCK_SIZE, ldpc::compute_nof_codeblocks(units::bytes(data.size()).to_bits(), config.codeword.value().ldpc_base_graph)); - unique_rx_softbuffer softbuffer(softbuffer_spy); + unique_rx_buffer rm_buffer(rm_buffer_spy); // Make sure the configuration is valid. ASSERT_TRUE(pdu_validator->is_valid(config)); // Process PUSCH PDU. pusch_processor_result_notifier_spy results_notifier; - pusch_proc->process(data, std::move(softbuffer), results_notifier, grid, config); + pusch_proc->process(data, std::move(rm_buffer), results_notifier, grid, config); // Verify UL-SCH decode results are invalid. const auto& sch_entries = results_notifier.get_sch_entries(); diff --git a/tests/unittests/phy/upper/downlink_processor_test.cpp b/tests/unittests/phy/upper/downlink_processor_test.cpp index 2f6199c59e..58ab1ded39 100644 --- a/tests/unittests/phy/upper/downlink_processor_test.cpp +++ b/tests/unittests/phy/upper/downlink_processor_test.cpp @@ -15,7 +15,7 @@ #include "channel_processors/pdsch_processor_test_doubles.h" #include "channel_processors/ssb_processor_test_doubles.h" #include "signal_processors/nzp_csi_rs_generator_test_doubles.h" -#include "tx_softbuffer_test_doubles.h" +#include "tx_buffer_test_doubles.h" #include "upper_phy_rg_gateway_test_doubles.h" #include "srsran/phy/upper/unique_tx_buffer.h" #include "srsran/ran/precoding/precoding_codebooks.h" @@ -28,7 +28,7 @@ static srslog::basic_logger& logger = srslog::fetch_basic_logger("PHY"); TEST(downlinkProcessorTest, worksInOrder) { - tx_buffer_spy softbuffer_spy; + tx_buffer_spy rm_buffer_spy; upper_phy_rg_gateway_fto gw; manual_task_worker executor(10); @@ -70,8 +70,8 @@ TEST(downlinkProcessorTest, worksInOrder) ASSERT_TRUE(pdcch_ref.is_process_called()); std::vector data = {1, 2, 3, 4}; - unique_tx_buffer softbuffer(softbuffer_spy); - dl_processor->process_pdsch(std::move(softbuffer), {data}, {}); + unique_tx_buffer rm_buffer(rm_buffer_spy); + dl_processor->process_pdsch(std::move(rm_buffer), {data}, {}); ASSERT_TRUE(pdsch_ref.is_process_called()); dl_processor->process_nzp_csi_rs({}); @@ -86,7 +86,7 @@ TEST(downlinkProcessorTest, worksInOrder) TEST(downlinkProcessorTest, finishIsCalledBeforeProcessingPdus) { - tx_buffer_spy softbuffer_spy; + tx_buffer_spy buffer_spy; upper_phy_rg_gateway_fto gw; manual_task_worker_always_enqueue_tasks executor(10); @@ -119,8 +119,8 @@ TEST(downlinkProcessorTest, finishIsCalledBeforeProcessingPdus) pdu.dci.precoding = precoding_configuration::make_wideband(make_single_port()); dl_processor->process_pdcch(pdu); std::vector data = {1, 2, 3, 4}; - unique_tx_buffer softbuffer(softbuffer_spy); - dl_processor->process_pdsch(std::move(softbuffer), {data}, {}); + unique_tx_buffer rm_buffer(buffer_spy); + dl_processor->process_pdsch(std::move(rm_buffer), {data}, {}); dl_processor->process_nzp_csi_rs({}); ASSERT_FALSE(pdcch_ref.is_process_called()); @@ -145,7 +145,7 @@ TEST(downlinkProcessorTest, finishIsCalledBeforeProcessingPdus) TEST(downlinkProcessorTest, processPduAfterFinishProcessingPdusDoesNothing) { - tx_buffer_spy softbuffer_spy; + tx_buffer_spy rm_buffer_spy; upper_phy_rg_gateway_fto gw; manual_task_worker executor(10); @@ -178,8 +178,8 @@ TEST(downlinkProcessorTest, processPduAfterFinishProcessingPdusDoesNothing) pdu.dci.precoding = precoding_configuration::make_wideband(make_single_port()); dl_processor->process_pdcch(pdu); std::vector data = {1, 2, 3, 4}; - unique_tx_buffer softbuffer(softbuffer_spy); - dl_processor->process_pdsch(std::move(softbuffer), {data}, {}); + unique_tx_buffer rm_buffer(rm_buffer_spy); + dl_processor->process_pdsch(std::move(rm_buffer), {data}, {}); dl_processor->finish_processing_pdus(); ASSERT_TRUE(pdcch_ref.is_process_called()); @@ -194,7 +194,7 @@ TEST(downlinkProcessorTest, processPduAfterFinishProcessingPdusDoesNothing) TEST(downlinkProcessorTest, processPduBeforeConfigureDoesNothing) { - tx_buffer_spy softbuffer_spy; + tx_buffer_spy rm_buffer_spy; upper_phy_rg_gateway_fto gw; manual_task_worker executor(10); @@ -222,8 +222,8 @@ TEST(downlinkProcessorTest, processPduBeforeConfigureDoesNothing) std::vector data = {1, 2, 3, 4}; dl_processor->process_pdcch(pdu); - unique_tx_buffer softbuffer(softbuffer_spy); - dl_processor->process_pdsch(std::move(softbuffer), {data}, {}); + unique_tx_buffer rm_buffer(rm_buffer_spy); + dl_processor->process_pdsch(std::move(rm_buffer), {data}, {}); dl_processor->process_nzp_csi_rs({}); ASSERT_FALSE(pdcch_ref.is_process_called()); @@ -261,7 +261,7 @@ TEST(downlinkProcessorTest, finishBeforeConfigureDeath) TEST(downlinkProcessorTest, twoConsecutiveSlots) { - tx_buffer_spy softbuffer_spy; + tx_buffer_spy rm_buffer_spy; upper_phy_rg_gateway_fto gw; manual_task_worker executor(10); @@ -284,8 +284,8 @@ TEST(downlinkProcessorTest, twoConsecutiveSlots) pdu.dci.precoding = precoding_configuration::make_wideband(make_single_port()); dl_processor->process_pdcch(pdu); std::vector data = {1, 2, 3, 4}; - unique_tx_buffer softbuffer(softbuffer_spy); - dl_processor->process_pdsch(std::move(softbuffer), {data}, {}); + unique_tx_buffer rm_buffer(rm_buffer_spy); + dl_processor->process_pdsch(std::move(rm_buffer), {data}, {}); dl_processor->process_nzp_csi_rs({}); ASSERT_TRUE(!gw.sent); @@ -300,8 +300,8 @@ TEST(downlinkProcessorTest, twoConsecutiveSlots) dl_processor->process_ssb({}); dl_processor->process_pdcch(pdu); - unique_tx_buffer softbuffer2(softbuffer_spy); - dl_processor->process_pdsch(std::move(softbuffer2), {data}, {}); + unique_tx_buffer rm_buffer2(rm_buffer_spy); + dl_processor->process_pdsch(std::move(rm_buffer2), {data}, {}); dl_processor->process_nzp_csi_rs({}); ASSERT_FALSE(gw.sent); diff --git a/tests/unittests/phy/upper/downlink_processor_test_doubles.h b/tests/unittests/phy/upper/downlink_processor_test_doubles.h index 9caf58e736..884b5433b4 100644 --- a/tests/unittests/phy/upper/downlink_processor_test_doubles.h +++ b/tests/unittests/phy/upper/downlink_processor_test_doubles.h @@ -36,7 +36,7 @@ class downlink_processor_spy : public downlink_processor void process_pdcch(const pdcch_processor::pdu_t& pdu) override {} - void process_pdsch(unique_tx_buffer softbuffer, + void process_pdsch(unique_tx_buffer rm_buffer, const static_vector, pdsch_processor::MAX_NOF_TRANSPORT_BLOCKS>& data, const pdsch_processor::pdu_t& pdu) override { diff --git a/tests/unittests/phy/upper/rx_buffer_pool_test.cpp b/tests/unittests/phy/upper/rx_buffer_pool_test.cpp new file mode 100644 index 0000000000..597c164772 --- /dev/null +++ b/tests/unittests/phy/upper/rx_buffer_pool_test.cpp @@ -0,0 +1,461 @@ +/* + * + * 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 "srsran/phy/upper/log_likelihood_ratio.h" +#include "srsran/phy/upper/rx_buffer_pool.h" +#include "srsran/phy/upper/unique_rx_buffer.h" +#include "srsran/support/executors/task_worker.h" +#include "srsran/support/executors/task_worker_pool.h" +#include + +using namespace srsran; + +namespace srsran { + +bool operator==(span left, span right) +{ + return std::equal(left.begin(), left.end(), right.begin(), right.end()); +} + +} // namespace srsran + +// Tests that the pool returns nullptr when the limit of buffers is reached. +TEST(rx_buffer_pool, buffer_limit) +{ + // Create pool configuration for the test. + rx_buffer_pool_config pool_config; + pool_config.max_codeblock_size = 16; + pool_config.nof_buffers = 4; + pool_config.max_nof_codeblocks = 4; + pool_config.expire_timeout_slots = 10; + pool_config.external_soft_bits = false; + + // Current slot. + slot_point slot(0, 0); + + // Create Rx buffer pool. + std::unique_ptr pool = create_rx_buffer_pool(pool_config); + ASSERT_TRUE(pool); + + // Create as many buffers as the limit is set. + std::vector buffers; + for (unsigned rnti = 0; rnti != pool_config.nof_buffers; ++rnti) { + trx_buffer_identifier buffer_id(rnti, 0); + + // Reserve buffer, it shall not fail. + buffers.emplace_back(pool->reserve(slot, buffer_id, 1)); + ASSERT_TRUE(buffers.back().is_valid()); + } + + // Create one more buffer. No buffers are available. It must fail to reserve. + trx_buffer_identifier buffer_id(static_cast(pool_config.nof_buffers), 0); + buffers.emplace_back(pool->reserve(slot, buffer_id, 1)); + ASSERT_TRUE(!buffers.back().is_valid()); +} + +// Tests that the pool returns nullptr when the limit of codeblocks is reached. +TEST(rx_buffer_pool, codeblock_limit) +{ + // Create pool configuration for the test. + rx_buffer_pool_config pool_config; + pool_config.max_codeblock_size = 16; + pool_config.nof_buffers = 2; + pool_config.max_nof_codeblocks = 1; + pool_config.expire_timeout_slots = 10; + pool_config.external_soft_bits = false; + + // Current slot. + slot_point slot(0, 0); + + // Create Rx buffer pool. + std::unique_ptr pool = create_rx_buffer_pool(pool_config); + ASSERT_TRUE(pool); + + // Reserve buffer with all the codeblocks, it shall not fail. + trx_buffer_identifier buffer_id0(0x1234, 0x3); + unique_rx_buffer buffer = pool->reserve(slot, buffer_id0, pool_config.max_nof_codeblocks); + ASSERT_TRUE(buffer.is_valid()); + + // Create one more buffer. No codeblocks are available. It must fail to reserve. + trx_buffer_identifier buffer_id1(0x1234, buffer_id0.get_harq() + 1); + ASSERT_TRUE(!pool->reserve(slot, buffer_id1, pool_config.max_nof_codeblocks).is_valid()); +} + +// Tests that the pool frees reserved buffer. +TEST(rx_buffer_pool, buffer_free) +{ + // Create pool configuration for the test. + rx_buffer_pool_config pool_config; + pool_config.max_codeblock_size = 16; + pool_config.nof_buffers = 1; + pool_config.max_nof_codeblocks = 1; + pool_config.expire_timeout_slots = 10; + pool_config.external_soft_bits = false; + + // Current slot. + slot_point slot(0, 0); + + // Create Rx buffer pool. + std::unique_ptr pool = create_rx_buffer_pool(pool_config); + ASSERT_TRUE(pool); + + // Reserve buffer with all the codeblocks, it shall not fail. + trx_buffer_identifier buffer_id0(0x1234, 0x3); + unique_rx_buffer buffer = pool->reserve(slot, buffer_id0, pool_config.max_nof_codeblocks); + ASSERT_TRUE(buffer.is_valid()); + + // Extract CRCs. + span crc = buffer->get_codeblocks_crc(); + + // Check the CRC are all false. + ASSERT_TRUE(std::find(crc.begin(), crc.end(), true) == crc.end()); + + // Fill codeblocks with true. + std::fill(crc.begin(), crc.end(), true); + + // Unlock buffer. It is still reserved. + buffer = unique_rx_buffer(); + + // Reserve buffer with the same identifier. It shall not fail. + buffer = pool->reserve(slot, buffer_id0, pool_config.max_nof_codeblocks); + ASSERT_TRUE(buffer.is_valid()); + + // Reserve buffer with a different identifier. It shall fail. + trx_buffer_identifier buffer_id1(0x1234, buffer_id0.get_harq() + 1); + ASSERT_TRUE(!pool->reserve(slot, buffer_id1, pool_config.max_nof_codeblocks).is_valid()); + + // Extract CRCs. + crc = buffer->get_codeblocks_crc(); + + // Check the CRC are all true. + ASSERT_TRUE(std::find(crc.begin(), crc.end(), false) == crc.end()); + + // Free the first buffer identifier. + buffer.release(); + + // Run slot for clearing the buffer. + pool->run_slot(slot); + + // Reserve buffer with all the codeblocks, it shall not fail. + buffer = pool->reserve(slot, buffer_id0, pool_config.max_nof_codeblocks); + ASSERT_TRUE(buffer.is_valid()); + + // Check the CRC are all false. + ASSERT_TRUE(std::find(crc.begin(), crc.end(), true) == crc.end()); +} + +// Tests that the pool expires buffers after the last reserved slot. +TEST(rx_buffer_pool, buffer_expire) +{ + unsigned delay = 3; + + // Create pool configuration for the test. + rx_buffer_pool_config pool_config; + pool_config.max_codeblock_size = 16; + pool_config.nof_buffers = 1; + pool_config.max_nof_codeblocks = 1; + pool_config.expire_timeout_slots = 4; + pool_config.external_soft_bits = false; + + // Current slot. + slot_point slot(0, 0); + + // Create Rx buffer pool. + std::unique_ptr pool = create_rx_buffer_pool(pool_config); + ASSERT_TRUE(pool); + + // Reserve buffer with all the codeblocks, it shall not fail. + trx_buffer_identifier buffer_id0(0x1234, 0x3); + ASSERT_TRUE(pool->reserve(slot, buffer_id0, pool_config.max_nof_codeblocks).is_valid()); + + // Run slot and reserve the same buffer. + slot += delay; + pool->run_slot(slot); + ASSERT_TRUE(pool->reserve(slot, buffer_id0, pool_config.max_nof_codeblocks).is_valid()); + + // Run for each slot until it expires. + do { + // Try to reserve another buffer. As there are no buffers available it shall fail. + trx_buffer_identifier buffer_id1(0x1234, buffer_id0.get_harq() + 1); + ASSERT_TRUE(!pool->reserve(slot, buffer_id1, pool_config.max_nof_codeblocks).is_valid()); + ++slot; + pool->run_slot(slot); + } while (slot.system_slot() < pool_config.expire_timeout_slots + delay); + + // After the first buffer expired, buffer reservation shall not fail. + trx_buffer_identifier buffer_id2(0x1234, buffer_id0.get_harq() + 2); + ASSERT_TRUE(pool->reserve(slot, buffer_id2, pool_config.max_nof_codeblocks).is_valid()); +} + +// Tests that the pool renews buffer expiration if they are locked. +TEST(rx_buffer_pool, buffer_renew_expire) +{ + unsigned expire_timeout_slots = 4; + + // Create pool configuration for the test. + rx_buffer_pool_config pool_config; + pool_config.max_codeblock_size = 16; + pool_config.nof_buffers = 2; + pool_config.max_nof_codeblocks = 1; + pool_config.expire_timeout_slots = expire_timeout_slots; + pool_config.external_soft_bits = false; + + // Current slot. + slot_point slot(0, 0); + + // Create Rx buffer pool. + std::unique_ptr pool = create_rx_buffer_pool(pool_config); + ASSERT_TRUE(pool); + + // Reserve buffer with all the codeblocks, it shall not fail. + trx_buffer_identifier buffer_id0(0x1234, 0x3); + unique_rx_buffer buffer = pool->reserve(slot, buffer_id0, pool_config.max_nof_codeblocks); + ASSERT_TRUE(buffer.is_valid()); + + // Advance slots. As the buffer is locked, the expiration shall be renewed. + slot += expire_timeout_slots; + pool->run_slot(slot); + + // Try to get the same buffer. It must fail as the buffer is locked. + unique_rx_buffer locked_buffer = pool->reserve(slot, buffer_id0, pool_config.max_nof_codeblocks); + ASSERT_FALSE(locked_buffer.is_valid()); + + // Unlock buffer. + buffer = unique_rx_buffer(); + + // Run for each slot until it expires. + do { + // Try to reserve another buffer. As there are no buffers available it shall fail. + trx_buffer_identifier buffer_id1(0x1234, buffer_id0.get_harq() + 1); + unique_rx_buffer invalid_buffer = pool->reserve(slot, buffer_id1, pool_config.max_nof_codeblocks); + ASSERT_FALSE(invalid_buffer.is_valid()); + ++slot; + pool->run_slot(slot); + } while (slot.system_slot() < pool_config.expire_timeout_slots + expire_timeout_slots); + + // After the first buffer expired, buffer reservation shall not fail. + trx_buffer_identifier buffer_id2(0x1234, buffer_id0.get_harq() + 2); + ASSERT_TRUE(pool->reserve(slot, buffer_id2, pool_config.max_nof_codeblocks).is_valid()); +} + +// Tests that the pool renews buffer expiration if they are locked. +TEST(rx_buffer_pool, buffer_resize) +{ + static constexpr unsigned max_nof_codeblocks = 4; + + // Create pool configuration for the test. + rx_buffer_pool_config pool_config; + pool_config.max_codeblock_size = 16; + pool_config.nof_buffers = 1; + pool_config.max_nof_codeblocks = max_nof_codeblocks; + pool_config.expire_timeout_slots = 4; + pool_config.external_soft_bits = false; + + // Current slot. + slot_point slot(0, 0); + + // Create Rx buffer pool. + std::unique_ptr pool = create_rx_buffer_pool(pool_config); + ASSERT_TRUE(pool); + + // Reserve buffer with max_nof_codeblocks - 1 codeblocks, it shall not fail. + trx_buffer_identifier buffer_id0(0x1234, 0x3); + unique_rx_buffer buffer = pool->reserve(slot, buffer_id0, max_nof_codeblocks); + ASSERT_TRUE(buffer.is_valid()); + + // Check the number of codeblock matches. + ASSERT_EQ(buffer.get().get_nof_codeblocks(), max_nof_codeblocks); + + // Set all CRC to true. + span crc = buffer.get().get_codeblocks_crc(); + std::fill(crc.begin(), crc.end(), true); + + // Unlock the buffer. + buffer = unique_rx_buffer(); + + // Reserve the same buffer with more codeblocks. + buffer = pool->reserve(slot, buffer_id0, max_nof_codeblocks - 1); + + // Check the number of codeblock matches. + ASSERT_EQ(buffer.get().get_nof_codeblocks(), max_nof_codeblocks - 1); + + // Check the CRC have been reset. + std::array expected_crc = {false}; + ASSERT_EQ(buffer->get_codeblocks_crc(), span(expected_crc)); +} + +// Tests buffer soft bits contents persists between retransmissions. +TEST(rx_buffer_pool, buffer_contents) +{ + unsigned nof_cb_x_buffer = 2; + unsigned cb_size = 16; + // Data size cannot be larger than cb_size / 3 (recall that 1/3 is the maximum coding rate). + unsigned data_size = 5; + + // Create pool configuration for the test. + rx_buffer_pool_config pool_config; + pool_config.max_codeblock_size = cb_size; + pool_config.nof_buffers = 4; + pool_config.max_nof_codeblocks = pool_config.nof_buffers * nof_cb_x_buffer; + pool_config.expire_timeout_slots = 10; + pool_config.external_soft_bits = false; + + // Current slot. + slot_point slot(0, 0); + + // Create Rx buffer pool. + std::unique_ptr pool = create_rx_buffer_pool(pool_config); + ASSERT_TRUE(pool); + + // Create as many buffers as the limit is set. + trx_buffer_identifier buffer_id(0x1234, 0x3); + + // Temporal storage of buffer codeblock information. + std::vector> cb_soft_bits; + std::vector cb_data_bits; + + // Note: two buffers with the same identifier cannot be simultaneously in scope. + { + // Reserve buffer, it shall not fail. + unique_rx_buffer rm_buffer = pool->reserve(slot, buffer_id, nof_cb_x_buffer); + ASSERT_TRUE(rm_buffer.is_valid()); + + // For each codeblock... + for (unsigned cb_id = 0; cb_id != nof_cb_x_buffer; ++cb_id) { + // Get codeblock soft and data bits. + span buffer = rm_buffer.get().get_codeblock_soft_bits(cb_id, cb_size); + bit_buffer data_buffer = rm_buffer.get().get_codeblock_data_bits(cb_id, data_size); + + cb_soft_bits.emplace_back(buffer); + cb_data_bits.emplace_back(data_buffer); + + // Make sure size matches. + ASSERT_TRUE(buffer.size() == cb_size); + ASSERT_TRUE(data_buffer.size() == data_size); + + // Write data in codeblock. + for (unsigned bit_idx = 0; bit_idx != cb_size; ++bit_idx) { + int8_t data = (cb_id << 4) | bit_idx; + buffer[bit_idx] = data; + if (bit_idx < data_size) { + data_buffer.insert(bit_idx & 1U, bit_idx, 1); + } + } + } + } + + // Reserve buffer, it shall not fail. + unique_rx_buffer buffer = pool->reserve(slot, buffer_id, nof_cb_x_buffer); + ASSERT_TRUE(buffer.is_valid()); + + // For each codeblock... + for (unsigned cb_id = 0; cb_id != nof_cb_x_buffer; ++cb_id) { + // Get codeblock soft bits. + span buffer0 = cb_soft_bits[cb_id]; + span buffer1 = buffer.get().get_codeblock_soft_bits(cb_id, cb_size); + bit_buffer data_buffer0 = cb_data_bits[cb_id]; + bit_buffer data_buffer1 = buffer.get().get_codeblock_data_bits(cb_id, data_size); + + // Make sure absolute codeblock indexes match. + ASSERT_EQ(buffer.get().get_absolute_codeblock_id(cb_id), cb_id); + + // Make sure the data pointers match. + ASSERT_TRUE(buffer0.data() == buffer1.data()); + ASSERT_TRUE(data_buffer0.get_buffer().data() == data_buffer1.get_buffer().data()); + + // Validate data persists in the codeblock. + for (unsigned bit_idx = 0; bit_idx != cb_size; ++bit_idx) { + log_likelihood_ratio data = static_cast((cb_id << 4) | bit_idx); + ASSERT_EQ(buffer0[bit_idx], data); + if (bit_idx < data_size) { + ASSERT_EQ(data_buffer0.extract(bit_idx, 1), bit_idx & 1U); + } + } + } +} + +TEST(rx_buffer_pool, concurrent) +{ + unsigned nof_repetitions = 1000; + unsigned nof_release_threads = 4; + unsigned max_nof_buffers = 16; + unsigned nof_cb_x_buffer = 8; + unsigned cb_size = 16; + + task_worker_pool release_worker_pool( + nof_release_threads, max_nof_buffers, "release"); + + task_worker asynch_worker("asynch", nof_repetitions); + + // Create pool configuration for the test. + rx_buffer_pool_config pool_config; + pool_config.max_codeblock_size = cb_size; + pool_config.nof_buffers = max_nof_buffers; + pool_config.max_nof_codeblocks = max_nof_buffers * nof_cb_x_buffer; + pool_config.expire_timeout_slots = 10; + pool_config.external_soft_bits = false; + + // Current slot. + slot_point slot(0, 0); + + // Create Rx buffer pool. + std::unique_ptr pool = create_rx_buffer_pool(pool_config); + ASSERT_TRUE(pool); + + for (unsigned i_repetition = 0; i_repetition != 10; ++i_repetition) { + for (unsigned i_buffer = 0; i_buffer != max_nof_buffers; ++i_buffer) { + // Reserve buffer. + unique_rx_buffer buffer = pool->reserve(slot, trx_buffer_identifier(0x1234, i_buffer), nof_cb_x_buffer); + + // The reservation should be successful for the first time. + ASSERT_TRUE((i_repetition > 0) || buffer.is_valid()); + + // Release or unlock buffer asynchronously in the worker pool. + if (buffer.is_valid()) { + if (i_repetition & 1) { + ASSERT_TRUE(release_worker_pool.push_task([buffer2 = std::move(buffer)]() mutable { buffer2.unlock(); })); + } else { + ASSERT_TRUE(release_worker_pool.push_task([buffer2 = std::move(buffer)]() mutable { buffer2.release(); })); + } + } + } + + // Process housekeeping asynchronously. + pool->run_slot(slot++); + } + + // Wait for tasks to finish. + while (release_worker_pool.nof_pending_tasks() != 0) { + std::this_thread::sleep_for(std::chrono::microseconds(10)); + } + while (asynch_worker.nof_pending_tasks() != 0) { + std::this_thread::sleep_for(std::chrono::microseconds(10)); + } + + release_worker_pool.stop(); + asynch_worker.stop(); +} + +int main(int argc, char** argv) +{ + testing::InitGoogleTest(&argc, argv); + + // Make sure logger is enabled and use /dev/null as sink. + srslog::set_default_sink(*srslog::create_file_sink("/dev/null")); + srslog::init(); + srslog::basic_logger& logger = srslog::fetch_basic_logger("PHY", true); + logger.set_level(srslog::basic_levels::debug); + + int ret = RUN_ALL_TESTS(); + + srslog::flush(); + + return ret; +} diff --git a/tests/unittests/phy/upper/rx_softbuffer_test_doubles.h b/tests/unittests/phy/upper/rx_buffer_test_doubles.h similarity index 88% rename from tests/unittests/phy/upper/rx_softbuffer_test_doubles.h rename to tests/unittests/phy/upper/rx_buffer_test_doubles.h index 62bd035381..a33c23486b 100644 --- a/tests/unittests/phy/upper/rx_softbuffer_test_doubles.h +++ b/tests/unittests/phy/upper/rx_buffer_test_doubles.h @@ -11,16 +11,16 @@ #pragma once #include "srsran/adt/tensor.h" -#include "srsran/phy/upper/unique_rx_softbuffer.h" +#include "srsran/phy/upper/unique_rx_buffer.h" namespace srsran { -class rx_softbuffer_spy : public unique_rx_softbuffer::softbuffer +class rx_buffer_spy : public unique_rx_buffer::callback { public: - rx_softbuffer_spy() = default; + rx_buffer_spy() = default; - rx_softbuffer_spy(unsigned max_codeblock_size, unsigned nof_codeblocks) : + rx_buffer_spy(unsigned max_codeblock_size, unsigned nof_codeblocks) : soft_bits({max_codeblock_size, nof_codeblocks}), crc(nof_codeblocks) { for (unsigned i_cb = 0; i_cb != nof_codeblocks; ++i_cb) { @@ -71,7 +71,7 @@ class rx_softbuffer_spy : public unique_rx_softbuffer::softbuffer /// Get the total number of times the methods have been called. unsigned get_total_count() const { return count + const_count; } - /// Returns true if the softbuffer is locked. + /// Returns true if the buffer is locked. bool is_locked() const { return locked; } private: diff --git a/tests/unittests/phy/upper/rx_softbuffer_pool_test.cpp b/tests/unittests/phy/upper/rx_softbuffer_pool_test.cpp deleted file mode 100644 index 167f9a68ac..0000000000 --- a/tests/unittests/phy/upper/rx_softbuffer_pool_test.cpp +++ /dev/null @@ -1,306 +0,0 @@ -/* - * - * 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 "srsran/phy/upper/log_likelihood_ratio.h" -#include "srsran/phy/upper/rx_softbuffer_pool.h" -#include "srsran/phy/upper/unique_rx_softbuffer.h" -#include "srsran/srsvec/compare.h" -#include "srsran/support/srsran_test.h" - -using namespace srsran; - -// Tests that the pool returns nullptr when the limit of softbuffers is reached. -static void test_softbuffer_limit() -{ - // Create pool configuration for the test. - rx_softbuffer_pool_config pool_config; - pool_config.max_codeblock_size = 16; - pool_config.max_softbuffers = 4; - pool_config.max_nof_codeblocks = 4; - pool_config.expire_timeout_slots = 10; - pool_config.external_soft_bits = false; - - // Current slot. - slot_point slot(0, 0); - - // Create Rx softbuffer pool. - std::unique_ptr pool = create_rx_softbuffer_pool(pool_config); - TESTASSERT(pool); - - // Create as many softbuffers as the limit is set. - std::vector softbuffers; - for (unsigned rnti = 0; rnti != pool_config.max_softbuffers; ++rnti) { - rx_softbuffer_identifier softbuffer_id; - softbuffer_id.harq_ack_id = 0; - softbuffer_id.rnti = static_cast(rnti); - - // Reserve softbuffer, it shall not fail. - softbuffers.emplace_back(pool->reserve_softbuffer(slot, softbuffer_id, 1)); - TESTASSERT(softbuffers.back().is_valid()); - } - - // Create one more softbuffer. No softbuffers are available. It must fail to reserve. - rx_softbuffer_identifier softbuffer_id; - softbuffer_id.harq_ack_id = 0; - softbuffer_id.rnti = static_cast(pool_config.max_softbuffers); - softbuffers.emplace_back(pool->reserve_softbuffer(slot, softbuffer_id, 1)); - TESTASSERT(!softbuffers.back().is_valid()); -} - -// Tests that the pool returns nullptr when the limit of codeblocks is reached. -static void test_codeblock_limit() -{ - // Create pool configuration for the test. - rx_softbuffer_pool_config pool_config; - pool_config.max_codeblock_size = 16; - pool_config.max_softbuffers = 2; - pool_config.max_nof_codeblocks = 1; - pool_config.expire_timeout_slots = 10; - pool_config.external_soft_bits = false; - - // Current slot. - slot_point slot(0, 0); - - // Create Rx softbuffer pool. - std::unique_ptr pool = create_rx_softbuffer_pool(pool_config); - TESTASSERT(pool); - - // Reserve softbuffer with all the codeblocks, it shall not fail. - rx_softbuffer_identifier softbuffer_id0; - softbuffer_id0.harq_ack_id = 0x3; - softbuffer_id0.rnti = 0x1234; - unique_rx_softbuffer softbuffer = pool->reserve_softbuffer(slot, softbuffer_id0, pool_config.max_nof_codeblocks); - TESTASSERT(softbuffer.is_valid()); - - // Create one more softbuffer. No codeblocks are available. It must fail to reserve. - rx_softbuffer_identifier softbuffer_id1; - softbuffer_id1.harq_ack_id = softbuffer_id0.harq_ack_id + 1; - softbuffer_id1.rnti = 0x1234; - TESTASSERT(!pool->reserve_softbuffer(slot, softbuffer_id1, pool_config.max_nof_codeblocks).is_valid()); -} - -// Tests that the pool frees reserved softbuffer. -static void test_softbuffer_free() -{ - // Create pool configuration for the test. - rx_softbuffer_pool_config pool_config; - pool_config.max_codeblock_size = 16; - pool_config.max_softbuffers = 1; - pool_config.max_nof_codeblocks = 1; - pool_config.expire_timeout_slots = 10; - pool_config.external_soft_bits = false; - - // Current slot. - slot_point slot(0, 0); - - // Create Rx softbuffer pool. - std::unique_ptr pool = create_rx_softbuffer_pool(pool_config); - TESTASSERT(pool); - - // Reserve softbuffer with all the codeblocks, it shall not fail. - rx_softbuffer_identifier softbuffer_id0; - softbuffer_id0.harq_ack_id = 0x3; - softbuffer_id0.rnti = 0x1234; - unique_rx_softbuffer softbuffer = pool->reserve_softbuffer(slot, softbuffer_id0, pool_config.max_nof_codeblocks); - TESTASSERT(softbuffer.is_valid()); - - // Extract CRCs. - span crc = softbuffer->get_codeblocks_crc(); - - // Check the CRC are all false. - TESTASSERT(std::find(crc.begin(), crc.end(), true) == crc.end()); - - // Fill codeblocks with true. - std::fill(crc.begin(), crc.end(), true); - - // Unlock softbuffer. It is still reserved. - softbuffer = unique_rx_softbuffer(); - - // Reserve softbuffer with the same identifier. It shall not fail. - softbuffer = pool->reserve_softbuffer(slot, softbuffer_id0, pool_config.max_nof_codeblocks); - TESTASSERT(softbuffer.is_valid()); - - // Reserve softbuffer with a different identifier. It shall fail. - rx_softbuffer_identifier softbuffer_id1; - softbuffer_id1.harq_ack_id = softbuffer_id0.harq_ack_id + 1; - softbuffer_id1.rnti = 0x1234; - TESTASSERT(!pool->reserve_softbuffer(slot, softbuffer_id1, pool_config.max_nof_codeblocks).is_valid()); - - // Extract CRCs. - crc = softbuffer->get_codeblocks_crc(); - - // Check the CRC are all true. - TESTASSERT(std::find(crc.begin(), crc.end(), false) == crc.end()); - - // Free the first softbuffer identifier. - softbuffer.release(); - - // Run slot for clearing the buffer. - pool->run_slot(slot); - - // Reserve softbuffer with all the codeblocks, it shall not fail. - softbuffer = pool->reserve_softbuffer(slot, softbuffer_id0, pool_config.max_nof_codeblocks); - TESTASSERT(softbuffer.is_valid()); - - // Check the CRC are all false. - TESTASSERT(std::find(crc.begin(), crc.end(), true) == crc.end()); -} - -// Tests that the pool expires softbuffers after the last reserved slot. -static void test_softbuffer_expire() -{ - unsigned delay = 3; - - // Create pool configuration for the test. - rx_softbuffer_pool_config pool_config; - pool_config.max_codeblock_size = 16; - pool_config.max_softbuffers = 1; - pool_config.max_nof_codeblocks = 1; - pool_config.expire_timeout_slots = 4; - pool_config.external_soft_bits = false; - - // Current slot. - slot_point slot(0, 0); - - // Create Rx softbuffer pool. - std::unique_ptr pool = create_rx_softbuffer_pool(pool_config); - TESTASSERT(pool); - - // Reserve softbuffer with all the codeblocks, it shall not fail. - rx_softbuffer_identifier softbuffer_id0; - softbuffer_id0.harq_ack_id = 0x3; - softbuffer_id0.rnti = 0x1234; - TESTASSERT(pool->reserve_softbuffer(slot, softbuffer_id0, pool_config.max_nof_codeblocks).is_valid()); - - // Run slot and reserve the same softbuffer. - slot += delay; - pool->run_slot(slot); - TESTASSERT(pool->reserve_softbuffer(slot, softbuffer_id0, pool_config.max_nof_codeblocks).is_valid()); - - // Run for each slot until it expires. - do { - // Try to reserve another buffer. As there are no buffers available it shall fail. - rx_softbuffer_identifier softbuffer_id1; - softbuffer_id1.harq_ack_id = softbuffer_id0.harq_ack_id + 1; - softbuffer_id1.rnti = 0x1234; - TESTASSERT(!pool->reserve_softbuffer(slot, softbuffer_id1, pool_config.max_nof_codeblocks).is_valid()); - ++slot; - pool->run_slot(slot); - } while (slot.system_slot() < pool_config.expire_timeout_slots + delay); - - // After the first buffer expired, buffer reservation shall not fail. - rx_softbuffer_identifier softbuffer_id2; - softbuffer_id2.harq_ack_id = softbuffer_id0.harq_ack_id + 2; - softbuffer_id2.rnti = 0x1234; - TESTASSERT(pool->reserve_softbuffer(slot, softbuffer_id2, pool_config.max_nof_codeblocks).is_valid()); -} - -// Tests softbuffer soft bits contents persists between retransmissions. -static void test_softbuffer_contents() -{ - unsigned nof_cb_x_buffer = 2; - unsigned cb_size = 16; - // Data size cannot be larger than cb_size / 3 (recall that 1/3 is the maximum coding rate). - unsigned data_size = 5; - - // Create pool configuration for the test. - rx_softbuffer_pool_config pool_config; - pool_config.max_codeblock_size = cb_size; - pool_config.max_softbuffers = 4; - pool_config.max_nof_codeblocks = pool_config.max_softbuffers * nof_cb_x_buffer; - pool_config.expire_timeout_slots = 10; - pool_config.external_soft_bits = false; - - // Current slot. - slot_point slot(0, 0); - - // Create Rx softbuffer pool. - std::unique_ptr pool = create_rx_softbuffer_pool(pool_config); - TESTASSERT(pool); - - // Create as many softbuffers as the limit is set. - rx_softbuffer_identifier softbuffer_id; - softbuffer_id.harq_ack_id = 0x3; - softbuffer_id.rnti = 0x1234; - - // Temporal storage of softbuffer codeblock information. - std::vector> cb_soft_bits; - std::vector cb_data_bits; - - // Note: two softbuffers with the same identifier cannot be simultaneously in scope. - { - // Reserve softbuffer, it shall not fail. - unique_rx_softbuffer softbuffer = pool->reserve_softbuffer(slot, softbuffer_id, nof_cb_x_buffer); - TESTASSERT(softbuffer.is_valid()); - - // For each codeblock... - for (unsigned cb_id = 0; cb_id != nof_cb_x_buffer; ++cb_id) { - // Get codeblock soft and data bits. - span buffer = softbuffer.get().get_codeblock_soft_bits(cb_id, cb_size); - bit_buffer data_buffer = softbuffer.get().get_codeblock_data_bits(cb_id, data_size); - - cb_soft_bits.emplace_back(buffer); - cb_data_bits.emplace_back(data_buffer); - - // Make sure size matches. - TESTASSERT(buffer.size() == cb_size); - TESTASSERT(data_buffer.size() == data_size); - - // Write data in codeblock. - for (unsigned bit_idx = 0; bit_idx != cb_size; ++bit_idx) { - int8_t data = (cb_id << 4) | bit_idx; - buffer[bit_idx] = data; - if (bit_idx < data_size) { - data_buffer.insert(bit_idx & 1U, bit_idx, 1); - } - } - } - } - - // Reserve softbuffer, it shall not fail. - unique_rx_softbuffer softbuffer = pool->reserve_softbuffer(slot, softbuffer_id, nof_cb_x_buffer); - TESTASSERT(softbuffer.is_valid()); - - // For each codeblock... - for (unsigned cb_id = 0; cb_id != nof_cb_x_buffer; ++cb_id) { - // Get codeblock soft bits. - span buffer0 = cb_soft_bits[cb_id]; - span buffer1 = softbuffer.get().get_codeblock_soft_bits(cb_id, cb_size); - bit_buffer data_buffer0 = cb_data_bits[cb_id]; - bit_buffer data_buffer1 = softbuffer.get().get_codeblock_data_bits(cb_id, data_size); - - // Make sure absolute codeblock indexes match. - TESTASSERT_EQ(softbuffer.get().get_absolute_codeblock_id(cb_id), cb_id); - - // Make sure the data pointers match. - TESTASSERT(buffer0.data() == buffer1.data()); - TESTASSERT(data_buffer0.get_buffer().data() == data_buffer1.get_buffer().data()); - - // Validate data persists in the codeblock. - for (unsigned bit_idx = 0; bit_idx != cb_size; ++bit_idx) { - log_likelihood_ratio data = static_cast((cb_id << 4) | bit_idx); - TESTASSERT_EQ(buffer0[bit_idx], data); - if (bit_idx < data_size) { - TESTASSERT_EQ(data_buffer0.extract(bit_idx, 1), bit_idx & 1U); - } - } - } -} - -int main() -{ - test_softbuffer_limit(); - test_codeblock_limit(); - test_softbuffer_free(); - test_softbuffer_expire(); - test_softbuffer_contents(); - - return 0; -} diff --git a/tests/unittests/phy/upper/tx_buffer_pool_test_doubles.h b/tests/unittests/phy/upper/tx_buffer_pool_test_doubles.h new file mode 100644 index 0000000000..b7f1800935 --- /dev/null +++ b/tests/unittests/phy/upper/tx_buffer_pool_test_doubles.h @@ -0,0 +1,58 @@ +/* + * + * 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 "tx_buffer_test_doubles.h" +#include "srsran/phy/upper/tx_buffer_pool.h" + +namespace srsran { + +class tx_buffer_pool_spy : public tx_buffer_pool +{ + struct reserve_entry { + slot_point slot; + trx_buffer_identifier id; + unsigned nof_codeblocks; + }; + +public: + unique_tx_buffer reserve(const slot_point& slot, trx_buffer_identifier id, unsigned nof_codeblocks) override + { + reserve_entries.emplace_back(); + reserve_entry& entry = reserve_entries.back(); + entry.slot = slot; + entry.id = id; + entry.nof_codeblocks = nof_codeblocks; + return unique_tx_buffer(rm_buffer_spy); + } + + unique_tx_buffer reserve(const slot_point& slot, unsigned nof_codeblocks) override + { + reserve_entries.emplace_back(); + reserve_entry& entry = reserve_entries.back(); + entry.slot = slot; + entry.id = trx_buffer_identifier::invalid(); + entry.nof_codeblocks = nof_codeblocks; + return unique_tx_buffer(rm_buffer_spy); + } + + void run_slot(const slot_point& slot) override { run_slot_entries.emplace_back(slot); } + + const std::vector& get_reserve_entries() const { return reserve_entries; } + + const std::vector& get_run_slot_entries() const { return run_slot_entries; } + +private: + std::vector reserve_entries; + std::vector run_slot_entries; + tx_buffer_spy rm_buffer_spy; +}; + +} // namespace srsran \ No newline at end of file diff --git a/tests/unittests/phy/upper/tx_softbuffer_test_doubles.h b/tests/unittests/phy/upper/tx_buffer_test_doubles.h similarity index 96% rename from tests/unittests/phy/upper/tx_softbuffer_test_doubles.h rename to tests/unittests/phy/upper/tx_buffer_test_doubles.h index dffa58017b..489ec7444d 100644 --- a/tests/unittests/phy/upper/tx_softbuffer_test_doubles.h +++ b/tests/unittests/phy/upper/tx_buffer_test_doubles.h @@ -16,7 +16,7 @@ namespace srsran { /// Implements a lockable transmit buffer spy. -class tx_buffer_spy : public unique_tx_buffer::lockable_buffer +class tx_buffer_spy : public unique_tx_buffer::callback { public: /// Default constructor - creates a buffer without any storage. diff --git a/tests/unittests/phy/upper/tx_softbuffer_pool_test_doubles.h b/tests/unittests/phy/upper/tx_softbuffer_pool_test_doubles.h deleted file mode 100644 index 350d8757bb..0000000000 --- a/tests/unittests/phy/upper/tx_softbuffer_pool_test_doubles.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * - * 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 "tx_softbuffer_test_doubles.h" -#include "srsran/phy/upper/tx_buffer_pool.h" - -namespace srsran { - -class tx_softbuffer_pool_spy : public tx_buffer_pool -{ - struct reserve_softbuffer_entry { - slot_point slot; - tx_buffer_identifier id; - unsigned nof_codeblocks; - }; - -public: - unique_tx_buffer - reserve_buffer(const slot_point& slot, const tx_buffer_identifier& id, unsigned nof_codeblocks) override - { - reserve_softbuffer_entries.emplace_back(); - reserve_softbuffer_entry& entry = reserve_softbuffer_entries.back(); - entry.slot = slot; - entry.id = id; - entry.nof_codeblocks = nof_codeblocks; - return unique_tx_buffer(softbuffer_spy); - } - - unique_tx_buffer reserve_buffer(const slot_point& slot, unsigned int nof_codeblocks) override - { - reserve_softbuffer_entries.emplace_back(); - reserve_softbuffer_entry& entry = reserve_softbuffer_entries.back(); - entry.slot = slot; - entry.id = {}; - entry.nof_codeblocks = nof_codeblocks; - return unique_tx_buffer(softbuffer_spy); - } - - void run_slot(const slot_point& slot) override { run_slot_entries.emplace_back(slot); } - - const std::vector& get_reserve_softbuffer_entries() const - { - return reserve_softbuffer_entries; - } - - const std::vector& get_run_slot_entries() const { return run_slot_entries; } - -private: - std::vector reserve_softbuffer_entries; - std::vector run_slot_entries; - tx_buffer_spy softbuffer_spy; -}; - -} // namespace srsran \ No newline at end of file diff --git a/tests/unittests/phy/upper/uplink_processor_test.cpp b/tests/unittests/phy/upper/uplink_processor_test.cpp index 550f06deda..7a9aa08ddb 100644 --- a/tests/unittests/phy/upper/uplink_processor_test.cpp +++ b/tests/unittests/phy/upper/uplink_processor_test.cpp @@ -14,7 +14,7 @@ #include "channel_processors/pucch_processor_test_doubles.h" #include "channel_processors/pusch/pusch_processor_test_doubles.h" #include "upper_phy_rx_results_notifier_test_doubles.h" -#include "srsran/phy/upper/unique_rx_softbuffer.h" +#include "srsran/phy/upper/unique_rx_buffer.h" #include using namespace srsran; diff --git a/tests/unittests/phy/upper/uplink_processor_test_doubles.h b/tests/unittests/phy/upper/uplink_processor_test_doubles.h index 953d353ace..43b4900f84 100644 --- a/tests/unittests/phy/upper/uplink_processor_test_doubles.h +++ b/tests/unittests/phy/upper/uplink_processor_test_doubles.h @@ -29,7 +29,7 @@ class uplink_processor_spy : public uplink_processor } void process_pusch(span data, - unique_rx_softbuffer softbuffer, + unique_rx_buffer rm_buffer, upper_phy_rx_results_notifier& notifier, const resource_grid_reader& grid, const uplink_processor::pusch_pdu& pdu) override diff --git a/tests/unittests/phy/upper/upper_phy_rx_symbol_handler_test.cpp b/tests/unittests/phy/upper/upper_phy_rx_symbol_handler_test.cpp index 1e785ae13c..d49c92d63a 100644 --- a/tests/unittests/phy/upper/upper_phy_rx_symbol_handler_test.cpp +++ b/tests/unittests/phy/upper/upper_phy_rx_symbol_handler_test.cpp @@ -24,7 +24,7 @@ namespace { class UpperPhyRxSymbolHandlerFixture : public ::testing::Test { protected: - std::unique_ptr softbuffer_pool; + std::unique_ptr rm_buffer_pool; uplink_processor_spy* ul_proc_spy; std::unique_ptr ul_processor_pool; uplink_slot_pdu_repository pdu_repo; @@ -93,12 +93,12 @@ class UpperPhyRxSymbolHandlerFixture : public ::testing::Test } UpperPhyRxSymbolHandlerFixture() : - softbuffer_pool(create_rx_softbuffer_pool(rx_softbuffer_pool_config{16, 2, 2, 16})), + rm_buffer_pool(create_rx_buffer_pool(rx_buffer_pool_config{16, 2, 2, 16})), ul_processor_pool(create_ul_processor_pool()), pdu_repo(2), rx_handler(*ul_processor_pool, pdu_repo, - *softbuffer_pool, + *rm_buffer_pool, rx_results_wrapper, srslog::fetch_basic_logger("TEST", true)) { From eff65ad2a3cc77a9bdca9f4f10e920279c34a978 Mon Sep 17 00:00:00 2001 From: Alejandro Leal Date: Tue, 19 Dec 2023 16:16:46 +0100 Subject: [PATCH 089/134] ofh: added a warning when the number of symbols skipped is bigger than a slot --- lib/ofh/timing/realtime_timing_worker.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/ofh/timing/realtime_timing_worker.cpp b/lib/ofh/timing/realtime_timing_worker.cpp index 14208912a7..f2a1039df5 100644 --- a/lib/ofh/timing/realtime_timing_worker.cpp +++ b/lib/ofh/timing/realtime_timing_worker.cpp @@ -163,6 +163,12 @@ void realtime_timing_worker::poll() delta); } + // Print a warning when the sleep is bigger than one slot. + // :TODO: this is active in a different PR. Make sure to remove it when the other is merged. + if (delta > 14) { + logger.warning("Real-time timing worker late, skipped {} symbols", delta); + } + slot_symbol_point symbol_point( calculate_slot_point(scs, std::chrono::time_point_cast(now).time_since_epoch().count(), From f1e266a97f44995887f7941bc0acc5530c2c8e66 Mon Sep 17 00:00:00 2001 From: Alejandro Leal Date: Tue, 19 Dec 2023 16:20:51 +0100 Subject: [PATCH 090/134] ofh: added a reception message lost logger decorator that will log lost/unnotified messages to the higher layers when the reception window closes --- lib/ofh/ofh_factories.cpp | 2 +- lib/ofh/receiver/CMakeLists.txt | 1 + lib/ofh/receiver/ofh_receiver_factories.cpp | 5 +- lib/ofh/receiver/ofh_receiver_impl.cpp | 10 ++- lib/ofh/receiver/ofh_receiver_impl.h | 12 ++- .../ofh_rx_lost_message_logger_decorator.cpp | 89 +++++++++++++++++++ .../ofh_rx_lost_message_logger_decorator.h | 59 ++++++++++++ lib/ofh/timing/realtime_timing_worker.cpp | 6 -- 8 files changed, 172 insertions(+), 12 deletions(-) create mode 100644 lib/ofh/receiver/ofh_rx_lost_message_logger_decorator.cpp create mode 100644 lib/ofh/receiver/ofh_rx_lost_message_logger_decorator.h diff --git a/lib/ofh/ofh_factories.cpp b/lib/ofh/ofh_factories.cpp index 62b25fb15d..d7af7be6f5 100644 --- a/lib/ofh/ofh_factories.cpp +++ b/lib/ofh/ofh_factories.cpp @@ -73,7 +73,7 @@ static transmitter_config generate_transmitter_config(const sector_configuration tx_config.mtu_size = sector_cfg.mtu_size; tx_config.ru_working_bw = sector_cfg.ru_operating_bw; tx_config.symbol_handler_cfg = { - sector_cfg.tx_window_timing_params, get_nsymb_per_slot(sector_cfg.cp), sector_cfg.scs}; + sector_cfg.tx_window_timing_params, get_nsymb_per_slot(sector_cfg.cp), sector_cfg.scs}; tx_config.dl_compr_params = sector_cfg.dl_compression_params; tx_config.ul_compr_params = sector_cfg.ul_compression_params; tx_config.prach_compr_params = sector_cfg.prach_compression_params; diff --git a/lib/ofh/receiver/CMakeLists.txt b/lib/ofh/receiver/CMakeLists.txt index e18870cfdd..caba8abc8a 100644 --- a/lib/ofh/receiver/CMakeLists.txt +++ b/lib/ofh/receiver/CMakeLists.txt @@ -13,6 +13,7 @@ set(SOURCES ofh_receiver_controller.cpp ofh_receiver_factories.cpp ofh_receiver_impl.cpp + ofh_rx_lost_message_logger_decorator.cpp ofh_rx_window_checker.cpp ofh_uplane_rx_symbol_data_flow_notifier.cpp ofh_uplane_rx_symbol_data_flow_writer.cpp diff --git a/lib/ofh/receiver/ofh_receiver_factories.cpp b/lib/ofh/receiver/ofh_receiver_factories.cpp index 8b0b85fd8c..f30b4b81c0 100644 --- a/lib/ofh/receiver/ofh_receiver_factories.cpp +++ b/lib/ofh/receiver/ofh_receiver_factories.cpp @@ -101,7 +101,10 @@ resolve_receiver_dependencies(const receiver_config& { receiver_impl_dependencies dependencies; - dependencies.logger = &logger; + dependencies.logger = &logger; + dependencies.prach_context_repo_ptr = prach_context_repo; + dependencies.ul_context_repo_ptr = ul_slot_context_repo; + dependencies.uplane_decoder = create_uplane_decoder(receiver_cfg, logger); if (receiver_cfg.ignore_ecpri_payload_size_field) { diff --git a/lib/ofh/receiver/ofh_receiver_impl.cpp b/lib/ofh/receiver/ofh_receiver_impl.cpp index 1374c38296..623ea99585 100644 --- a/lib/ofh/receiver/ofh_receiver_impl.cpp +++ b/lib/ofh/receiver/ofh_receiver_impl.cpp @@ -55,6 +55,14 @@ receiver_impl::receiver_impl(const receiver_config& config, receiver_impl_depend config.rx_timing_params, std::chrono::duration( 1e6 / (get_nsymb_per_slot(config.cp) * get_nof_slots_per_subframe(config.scs)))), + lost_message_decorator(config.rx_timing_params, + config.cp, + std::chrono::duration( + 1e6 / (get_nsymb_per_slot(config.cp) * get_nof_slots_per_subframe(config.scs))), + *dependencies.logger, + window_checker, + dependencies.prach_context_repo_ptr, + dependencies.ul_context_repo_ptr), msg_receiver(get_message_receiver_configuration(config), get_message_receiver_dependencies(std::move(dependencies), window_checker)), ctrl(msg_receiver) @@ -68,7 +76,7 @@ ether::frame_notifier& receiver_impl::get_ethernet_frame_notifier() ota_symbol_boundary_notifier& receiver_impl::get_ota_symbol_boundary_notifier() { - return window_checker; + return lost_message_decorator; } controller& receiver_impl::get_controller() diff --git a/lib/ofh/receiver/ofh_receiver_impl.h b/lib/ofh/receiver/ofh_receiver_impl.h index e13396202e..276e04d811 100644 --- a/lib/ofh/receiver/ofh_receiver_impl.h +++ b/lib/ofh/receiver/ofh_receiver_impl.h @@ -15,6 +15,7 @@ #include "../support/uplink_cplane_context_repository.h" #include "ofh_message_receiver.h" #include "ofh_receiver_controller.h" +#include "ofh_rx_lost_message_logger_decorator.h" #include "ofh_rx_window_checker.h" #include "srsran/ofh/receiver/ofh_receiver.h" #include "srsran/ofh/receiver/ofh_receiver_configuration.h" @@ -36,6 +37,10 @@ struct receiver_impl_dependencies { std::unique_ptr data_flow_uplink; /// User-Plane uplink PRACH data flow. std::unique_ptr data_flow_prach; + /// PRACH context repository. + std::shared_ptr prach_context_repo_ptr; + /// Uplink context repository. + std::shared_ptr ul_context_repo_ptr; }; /// \brief Open Fronthaul receiver. @@ -62,9 +67,10 @@ class receiver_impl : public receiver } private: - rx_window_checker window_checker; - message_receiver msg_receiver; - receiver_controller ctrl; + rx_window_checker window_checker; + rx_lost_message_logger_decorator lost_message_decorator; + message_receiver msg_receiver; + receiver_controller ctrl; }; } // namespace ofh diff --git a/lib/ofh/receiver/ofh_rx_lost_message_logger_decorator.cpp b/lib/ofh/receiver/ofh_rx_lost_message_logger_decorator.cpp new file mode 100644 index 0000000000..204eeeee33 --- /dev/null +++ b/lib/ofh/receiver/ofh_rx_lost_message_logger_decorator.cpp @@ -0,0 +1,89 @@ +/* + * + * 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 "ofh_rx_lost_message_logger_decorator.h" + +using namespace srsran; +using namespace ofh; + +rx_lost_message_logger_decorator::rx_lost_message_logger_decorator( + const du_rx_window_timing_parameters& params, + cyclic_prefix cp, + std::chrono::duration symbol_duration, + srslog::basic_logger& logger_, + ota_symbol_boundary_notifier& notifier_, + std::shared_ptr prach_context_repo_ptr_, + std::shared_ptr ul_context_repo_ptr_) : + // Add one extra symbol to the variable that controls when the reception window closes, in case that a message arrives + // in the last symbol. + nof_symbols_rx_window_closes(std::floor(params.Ta4_max / symbol_duration) + 1U), + nof_symbols(get_nsymb_per_slot(cp)), + logger(logger_), + notifier(notifier_), + prach_context_repo_ptr(prach_context_repo_ptr_), + prach_context_repo(*prach_context_repo_ptr), + ul_context_repo_ptr(ul_context_repo_ptr_), + ul_context_repo(*ul_context_repo_ptr) +{ + srsran_assert(prach_context_repo_ptr, "Invalid PRACH context repository"); + srsran_assert(ul_context_repo_ptr, "Invalid uplink context repository"); +} + +void rx_lost_message_logger_decorator::on_new_symbol(slot_symbol_point symbol_point) +{ + // First notify the symbol point. + notifier.on_new_symbol(symbol_point); + + log_lost_message(symbol_point); +} + +void rx_lost_message_logger_decorator::log_lost_message(slot_symbol_point symbol_point) +{ + slot_point rx_window_closing_slot = (symbol_point - nof_symbols_rx_window_closes).get_slot(); + + // Initialize the last slot checked. + if (!last_slot_checked.valid()) { + last_slot_checked = rx_window_closing_slot; + + return; + } + + // Do nothing if the slot is the same. + if (last_slot_checked == rx_window_closing_slot) { + return; + } + + int interval = rx_window_closing_slot - last_slot_checked; + srsran_assert(interval > 0, + "Last slot checked '{}' cannot be bigger than the current slot to check '{}'", + last_slot_checked, + rx_window_closing_slot); + + // Check for every missed slot in the repository for no notified PRACH/PUSCH. + for (unsigned i = 0, e = interval; i != e; ++i) { + ++last_slot_checked; + + const prach_context& prach = prach_context_repo.get(last_slot_checked); + if (!prach.empty()) { + logger.warning("Missed incoming User-Plane PRACH messages for slot '{}'", last_slot_checked); + } + + for (unsigned symb_id = 0; symb_id != nof_symbols; ++symb_id) { + const uplink_context& uplink = ul_context_repo.get(last_slot_checked, symb_id); + if (uplink.empty()) { + continue; + } + + logger.warning("Missed incoming User-Plane uplink messages for slot '{}'", last_slot_checked); + + break; + } + } +} diff --git a/lib/ofh/receiver/ofh_rx_lost_message_logger_decorator.h b/lib/ofh/receiver/ofh_rx_lost_message_logger_decorator.h new file mode 100644 index 0000000000..b83bf20510 --- /dev/null +++ b/lib/ofh/receiver/ofh_rx_lost_message_logger_decorator.h @@ -0,0 +1,59 @@ +/* + * + * 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 "../support/prach_context_repository.h" +#include "../support/uplink_context_repository.h" +#include "srsran/ofh/receiver/ofh_receiver_timing_parameters.h" +#include "srsran/ofh/timing/ofh_ota_symbol_boundary_notifier.h" + +namespace srsran { + +class task_executor; + +namespace ofh { + +/// Open Fronthaul lost received message logger decorator. +/// +/// The decorator will check the slot when the reception window closes and report if OFH messages were expected for that +/// slot. +class rx_lost_message_logger_decorator : public ota_symbol_boundary_notifier +{ +public: + rx_lost_message_logger_decorator(const du_rx_window_timing_parameters& params, + cyclic_prefix cp, + std::chrono::duration symbol_duration, + srslog::basic_logger& logger_, + ota_symbol_boundary_notifier& notifier_, + std::shared_ptr prach_context_repo_ptr_, + std::shared_ptr ul_context_repo_ptr_); + + // See interface for documentation. + void on_new_symbol(slot_symbol_point symbol_point) override; + +private: + /// Logs the lost messages for the given symbol point. + void log_lost_message(slot_symbol_point symbol_point); + +private: + const unsigned nof_symbols_rx_window_closes; + const unsigned nof_symbols; + slot_point last_slot_checked; + srslog::basic_logger& logger; + ota_symbol_boundary_notifier& notifier; + std::shared_ptr prach_context_repo_ptr; + prach_context_repository& prach_context_repo; + std::shared_ptr ul_context_repo_ptr; + uplink_context_repository& ul_context_repo; +}; + +} // namespace ofh +} // namespace srsran diff --git a/lib/ofh/timing/realtime_timing_worker.cpp b/lib/ofh/timing/realtime_timing_worker.cpp index f2a1039df5..14208912a7 100644 --- a/lib/ofh/timing/realtime_timing_worker.cpp +++ b/lib/ofh/timing/realtime_timing_worker.cpp @@ -163,12 +163,6 @@ void realtime_timing_worker::poll() delta); } - // Print a warning when the sleep is bigger than one slot. - // :TODO: this is active in a different PR. Make sure to remove it when the other is merged. - if (delta > 14) { - logger.warning("Real-time timing worker late, skipped {} symbols", delta); - } - slot_symbol_point symbol_point( calculate_slot_point(scs, std::chrono::time_point_cast(now).time_since_epoch().count(), From 3bc023b5f431e76c952603f4140029001554ef77 Mon Sep 17 00:00:00 2001 From: Alejandro Leal Date: Wed, 10 Jan 2024 10:49:13 +0100 Subject: [PATCH 091/134] ofh: added the reception lost message functionality to the repositories and removed the decorator --- lib/ofh/ofh_factories.cpp | 6 +- lib/ofh/receiver/CMakeLists.txt | 1 - lib/ofh/receiver/ofh_receiver_impl.cpp | 10 +-- lib/ofh/receiver/ofh_receiver_impl.h | 8 +- .../ofh_rx_lost_message_logger_decorator.cpp | 89 ------------------- .../ofh_rx_lost_message_logger_decorator.h | 59 ------------ lib/ofh/support/prach_context_repository.h | 18 +++- lib/ofh/support/uplink_context_repository.h | 14 ++- ...data_flow_uplane_uplink_data_impl_test.cpp | 7 +- ...ata_flow_uplane_uplink_prach_impl_test.cpp | 20 +++-- ...h_uplane_prach_data_flow_notifier_test.cpp | 16 ++-- ...ane_prach_symbol_data_flow_writer_test.cpp | 5 +- ...lane_rx_symbol_data_flow_notifier_test.cpp | 20 ++--- ...uplane_rx_symbol_data_flow_writer_test.cpp | 19 ++-- .../ofh_uplink_request_handler_impl_test.cpp | 4 +- 15 files changed, 84 insertions(+), 212 deletions(-) delete mode 100644 lib/ofh/receiver/ofh_rx_lost_message_logger_decorator.cpp delete mode 100644 lib/ofh/receiver/ofh_rx_lost_message_logger_decorator.h diff --git a/lib/ofh/ofh_factories.cpp b/lib/ofh/ofh_factories.cpp index d7af7be6f5..caa561cca4 100644 --- a/lib/ofh/ofh_factories.cpp +++ b/lib/ofh/ofh_factories.cpp @@ -73,7 +73,7 @@ static transmitter_config generate_transmitter_config(const sector_configuration tx_config.mtu_size = sector_cfg.mtu_size; tx_config.ru_working_bw = sector_cfg.ru_operating_bw; tx_config.symbol_handler_cfg = { - sector_cfg.tx_window_timing_params, get_nsymb_per_slot(sector_cfg.cp), sector_cfg.scs}; + sector_cfg.tx_window_timing_params, get_nsymb_per_slot(sector_cfg.cp), sector_cfg.scs}; tx_config.dl_compr_params = sector_cfg.dl_compression_params; tx_config.ul_compr_params = sector_cfg.ul_compression_params; tx_config.prach_compr_params = sector_cfg.prach_compression_params; @@ -93,8 +93,8 @@ std::unique_ptr srsran::ofh::create_ofh_sector(const sector_configuratio unsigned repository_size = sector_cfg.max_processing_delay_slots * 4; auto cp_repo = std::make_shared(repository_size); - auto prach_repo = std::make_shared(repository_size); - auto slot_repo = std::make_shared(repository_size); + auto prach_repo = std::make_shared(repository_size, *sector_deps.logger); + auto slot_repo = std::make_shared(repository_size, *sector_deps.logger); // Build the OFH receiver. auto rx_config = generate_receiver_config(sector_cfg); diff --git a/lib/ofh/receiver/CMakeLists.txt b/lib/ofh/receiver/CMakeLists.txt index caba8abc8a..e18870cfdd 100644 --- a/lib/ofh/receiver/CMakeLists.txt +++ b/lib/ofh/receiver/CMakeLists.txt @@ -13,7 +13,6 @@ set(SOURCES ofh_receiver_controller.cpp ofh_receiver_factories.cpp ofh_receiver_impl.cpp - ofh_rx_lost_message_logger_decorator.cpp ofh_rx_window_checker.cpp ofh_uplane_rx_symbol_data_flow_notifier.cpp ofh_uplane_rx_symbol_data_flow_writer.cpp diff --git a/lib/ofh/receiver/ofh_receiver_impl.cpp b/lib/ofh/receiver/ofh_receiver_impl.cpp index 623ea99585..1374c38296 100644 --- a/lib/ofh/receiver/ofh_receiver_impl.cpp +++ b/lib/ofh/receiver/ofh_receiver_impl.cpp @@ -55,14 +55,6 @@ receiver_impl::receiver_impl(const receiver_config& config, receiver_impl_depend config.rx_timing_params, std::chrono::duration( 1e6 / (get_nsymb_per_slot(config.cp) * get_nof_slots_per_subframe(config.scs)))), - lost_message_decorator(config.rx_timing_params, - config.cp, - std::chrono::duration( - 1e6 / (get_nsymb_per_slot(config.cp) * get_nof_slots_per_subframe(config.scs))), - *dependencies.logger, - window_checker, - dependencies.prach_context_repo_ptr, - dependencies.ul_context_repo_ptr), msg_receiver(get_message_receiver_configuration(config), get_message_receiver_dependencies(std::move(dependencies), window_checker)), ctrl(msg_receiver) @@ -76,7 +68,7 @@ ether::frame_notifier& receiver_impl::get_ethernet_frame_notifier() ota_symbol_boundary_notifier& receiver_impl::get_ota_symbol_boundary_notifier() { - return lost_message_decorator; + return window_checker; } controller& receiver_impl::get_controller() diff --git a/lib/ofh/receiver/ofh_receiver_impl.h b/lib/ofh/receiver/ofh_receiver_impl.h index 276e04d811..bd74614ade 100644 --- a/lib/ofh/receiver/ofh_receiver_impl.h +++ b/lib/ofh/receiver/ofh_receiver_impl.h @@ -15,7 +15,6 @@ #include "../support/uplink_cplane_context_repository.h" #include "ofh_message_receiver.h" #include "ofh_receiver_controller.h" -#include "ofh_rx_lost_message_logger_decorator.h" #include "ofh_rx_window_checker.h" #include "srsran/ofh/receiver/ofh_receiver.h" #include "srsran/ofh/receiver/ofh_receiver_configuration.h" @@ -67,10 +66,9 @@ class receiver_impl : public receiver } private: - rx_window_checker window_checker; - rx_lost_message_logger_decorator lost_message_decorator; - message_receiver msg_receiver; - receiver_controller ctrl; + rx_window_checker window_checker; + message_receiver msg_receiver; + receiver_controller ctrl; }; } // namespace ofh diff --git a/lib/ofh/receiver/ofh_rx_lost_message_logger_decorator.cpp b/lib/ofh/receiver/ofh_rx_lost_message_logger_decorator.cpp deleted file mode 100644 index 204eeeee33..0000000000 --- a/lib/ofh/receiver/ofh_rx_lost_message_logger_decorator.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * - * 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 "ofh_rx_lost_message_logger_decorator.h" - -using namespace srsran; -using namespace ofh; - -rx_lost_message_logger_decorator::rx_lost_message_logger_decorator( - const du_rx_window_timing_parameters& params, - cyclic_prefix cp, - std::chrono::duration symbol_duration, - srslog::basic_logger& logger_, - ota_symbol_boundary_notifier& notifier_, - std::shared_ptr prach_context_repo_ptr_, - std::shared_ptr ul_context_repo_ptr_) : - // Add one extra symbol to the variable that controls when the reception window closes, in case that a message arrives - // in the last symbol. - nof_symbols_rx_window_closes(std::floor(params.Ta4_max / symbol_duration) + 1U), - nof_symbols(get_nsymb_per_slot(cp)), - logger(logger_), - notifier(notifier_), - prach_context_repo_ptr(prach_context_repo_ptr_), - prach_context_repo(*prach_context_repo_ptr), - ul_context_repo_ptr(ul_context_repo_ptr_), - ul_context_repo(*ul_context_repo_ptr) -{ - srsran_assert(prach_context_repo_ptr, "Invalid PRACH context repository"); - srsran_assert(ul_context_repo_ptr, "Invalid uplink context repository"); -} - -void rx_lost_message_logger_decorator::on_new_symbol(slot_symbol_point symbol_point) -{ - // First notify the symbol point. - notifier.on_new_symbol(symbol_point); - - log_lost_message(symbol_point); -} - -void rx_lost_message_logger_decorator::log_lost_message(slot_symbol_point symbol_point) -{ - slot_point rx_window_closing_slot = (symbol_point - nof_symbols_rx_window_closes).get_slot(); - - // Initialize the last slot checked. - if (!last_slot_checked.valid()) { - last_slot_checked = rx_window_closing_slot; - - return; - } - - // Do nothing if the slot is the same. - if (last_slot_checked == rx_window_closing_slot) { - return; - } - - int interval = rx_window_closing_slot - last_slot_checked; - srsran_assert(interval > 0, - "Last slot checked '{}' cannot be bigger than the current slot to check '{}'", - last_slot_checked, - rx_window_closing_slot); - - // Check for every missed slot in the repository for no notified PRACH/PUSCH. - for (unsigned i = 0, e = interval; i != e; ++i) { - ++last_slot_checked; - - const prach_context& prach = prach_context_repo.get(last_slot_checked); - if (!prach.empty()) { - logger.warning("Missed incoming User-Plane PRACH messages for slot '{}'", last_slot_checked); - } - - for (unsigned symb_id = 0; symb_id != nof_symbols; ++symb_id) { - const uplink_context& uplink = ul_context_repo.get(last_slot_checked, symb_id); - if (uplink.empty()) { - continue; - } - - logger.warning("Missed incoming User-Plane uplink messages for slot '{}'", last_slot_checked); - - break; - } - } -} diff --git a/lib/ofh/receiver/ofh_rx_lost_message_logger_decorator.h b/lib/ofh/receiver/ofh_rx_lost_message_logger_decorator.h deleted file mode 100644 index b83bf20510..0000000000 --- a/lib/ofh/receiver/ofh_rx_lost_message_logger_decorator.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * - * 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 "../support/prach_context_repository.h" -#include "../support/uplink_context_repository.h" -#include "srsran/ofh/receiver/ofh_receiver_timing_parameters.h" -#include "srsran/ofh/timing/ofh_ota_symbol_boundary_notifier.h" - -namespace srsran { - -class task_executor; - -namespace ofh { - -/// Open Fronthaul lost received message logger decorator. -/// -/// The decorator will check the slot when the reception window closes and report if OFH messages were expected for that -/// slot. -class rx_lost_message_logger_decorator : public ota_symbol_boundary_notifier -{ -public: - rx_lost_message_logger_decorator(const du_rx_window_timing_parameters& params, - cyclic_prefix cp, - std::chrono::duration symbol_duration, - srslog::basic_logger& logger_, - ota_symbol_boundary_notifier& notifier_, - std::shared_ptr prach_context_repo_ptr_, - std::shared_ptr ul_context_repo_ptr_); - - // See interface for documentation. - void on_new_symbol(slot_symbol_point symbol_point) override; - -private: - /// Logs the lost messages for the given symbol point. - void log_lost_message(slot_symbol_point symbol_point); - -private: - const unsigned nof_symbols_rx_window_closes; - const unsigned nof_symbols; - slot_point last_slot_checked; - srslog::basic_logger& logger; - ota_symbol_boundary_notifier& notifier; - std::shared_ptr prach_context_repo_ptr; - prach_context_repository& prach_context_repo; - std::shared_ptr ul_context_repo_ptr; - uplink_context_repository& ul_context_repo; -}; - -} // namespace ofh -} // namespace srsran diff --git a/lib/ofh/support/prach_context_repository.h b/lib/ofh/support/prach_context_repository.h index e79326363c..b8fd487cac 100644 --- a/lib/ofh/support/prach_context_repository.h +++ b/lib/ofh/support/prach_context_repository.h @@ -82,6 +82,9 @@ class prach_context /// Returns true if this context is empty, otherwise false. bool empty() const { return context_info.buffer == nullptr; } + /// Returns the PRACH buffer context. + const prach_buffer_context& get_context() const { return context_info.context; } + /// Returns the number of REs of one PRACH repetition or zero if no PRACH buffer is associated with this context. unsigned get_prach_nof_re() const { return empty() ? 0U : preamble_info.sequence_length; } @@ -161,6 +164,7 @@ class prach_context_repository /// System frame number maximum value in this repository. static constexpr unsigned SFN_MAX_VALUE = 1U << 8; + srslog::basic_logger& logger; std::vector buffer; //: TODO: make this lock free mutable std::mutex mutex; @@ -182,7 +186,7 @@ class prach_context_repository } public: - explicit prach_context_repository(unsigned size_) : buffer(size_) {} + prach_context_repository(unsigned size_, srslog::basic_logger& logger_) : logger(logger_), buffer(size_) {} /// Adds the given entry to the repository at slot. void add(const prach_buffer_context& context, @@ -191,7 +195,17 @@ class prach_context_repository slot_point slot = slot_point()) { std::lock_guard lock(mutex); - entry(slot.valid() ? slot : context.slot) = prach_context(context, buffer_, nof_ports); + + slot_point current_slot = slot.valid() ? slot : context.slot; + + if (!entry(current_slot).empty()) { + const prach_buffer_context& previous_context = entry(current_slot).get_context(); + logger.warning("Missed incoming User-Plane PRACH messages for slot '{}' and sector#{}", + previous_context.slot, + previous_context.sector); + } + + entry(current_slot) = prach_context(context, buffer_, nof_ports); } /// Function to write the uplink PRACH buffer. diff --git a/lib/ofh/support/uplink_context_repository.h b/lib/ofh/support/uplink_context_repository.h index a26099ed5a..d6eb3fa2d9 100644 --- a/lib/ofh/support/uplink_context_repository.h +++ b/lib/ofh/support/uplink_context_repository.h @@ -56,6 +56,9 @@ class uplink_context return (grid.grid) ? (grid.grid->get_writer().get_nof_subc() / NOF_SUBCARRIERS_PER_RB) : 0U; } + /// Returns the resource grid context. + const resource_grid_context& get_grid_context() const { return grid.context; } + /// Returns a span of bitmaps that indicate the REs that have been written for the given symbol. Each element of the /// span corresponds to a port. span> get_re_written_mask() const { return re_written; } @@ -109,6 +112,7 @@ class uplink_context_repository /// System frame number maximum value in this repository. static constexpr unsigned SFN_MAX_VALUE = 1U << 8; + srslog::basic_logger& logger; std::vector> buffer; //: TODO: make this lock free mutable std::mutex mutex; @@ -134,7 +138,7 @@ class uplink_context_repository } public: - explicit uplink_context_repository(unsigned size_) : buffer(size_) {} + uplink_context_repository(unsigned size_, srslog::basic_logger& logger_) : logger(logger_), buffer(size_) {} /// Adds the given entry to the repository at slot. void add(const resource_grid_context& context, resource_grid& grid) @@ -142,6 +146,14 @@ class uplink_context_repository std::lock_guard lock(mutex); for (unsigned symbol_id = 0, symbol_end = grid.get_reader().get_nof_symbols(); symbol_id != symbol_end; ++symbol_id) { + if (!entry(context.slot, symbol_id).empty()) { + const resource_grid_context& previous_context = entry(context.slot, symbol_id).get_grid_context(); + logger.warning("Missed incoming User-Plane uplink messages for slot '{}', symbol '{}' and sector#{}", + previous_context.slot, + symbol_id, + previous_context.sector); + } + entry(context.slot, symbol_id) = uplink_context(symbol_id, context, grid); } } diff --git a/tests/unittests/ofh/receiver/ofh_data_flow_uplane_uplink_data_impl_test.cpp b/tests/unittests/ofh/receiver/ofh_data_flow_uplane_uplink_data_impl_test.cpp index 7fa36c6156..d501294416 100644 --- a/tests/unittests/ofh/receiver/ofh_data_flow_uplane_uplink_data_impl_test.cpp +++ b/tests/unittests/ofh/receiver/ofh_data_flow_uplane_uplink_data_impl_test.cpp @@ -56,9 +56,10 @@ class data_flow_uplane_uplink_data_impl_fixture : public ::testing::Test uplane_rx_symbol_notifier_spy* notifier; std::shared_ptr ul_cplane_context_repo_ptr = std::make_shared(1); - std::shared_ptr ul_context_repo = std::make_shared(1); - uplane_message_decoder_spy* uplane_decoder; - data_flow_uplane_uplink_data_impl data_flow; + std::shared_ptr ul_context_repo = + std::make_shared(1, srslog::fetch_basic_logger("TEST")); + uplane_message_decoder_spy* uplane_decoder; + data_flow_uplane_uplink_data_impl data_flow; public: data_flow_uplane_uplink_data_impl_fixture() : diff --git a/tests/unittests/ofh/receiver/ofh_data_flow_uplane_uplink_prach_impl_test.cpp b/tests/unittests/ofh/receiver/ofh_data_flow_uplane_uplink_prach_impl_test.cpp index 1a1f28158d..16be00a9a4 100644 --- a/tests/unittests/ofh/receiver/ofh_data_flow_uplane_uplink_prach_impl_test.cpp +++ b/tests/unittests/ofh/receiver/ofh_data_flow_uplane_uplink_prach_impl_test.cpp @@ -57,18 +57,20 @@ class data_flow_uplane_uplink_prach_impl_fixture : public ::testing::TestWithPar bool is_cplane_enabled = std::get<1>(params); prach_format_type format = std::get<0>(params); - prach_buffer_context buffer_context; - prach_buffer_dummy buffer; - unsigned preamble_length; - unsigned nof_symbols; - message_decoder_results results; - std::shared_ptr repo = std::make_shared(1); + prach_buffer_context buffer_context; + prach_buffer_dummy buffer; + unsigned preamble_length; + unsigned nof_symbols; + message_decoder_results results; + std::shared_ptr repo = + std::make_shared(1, srslog::fetch_basic_logger("TEST")); uplane_rx_symbol_notifier_spy* notifier; std::shared_ptr ul_cplane_context_repo_ptr = std::make_shared(1); - std::shared_ptr prach_context_repo = std::make_shared(1); - uplane_message_decoder_spy* uplane_decoder; - data_flow_uplane_uplink_prach_impl data_flow; + std::shared_ptr prach_context_repo = + std::make_shared(1, srslog::fetch_basic_logger("TEST")); + uplane_message_decoder_spy* uplane_decoder; + data_flow_uplane_uplink_prach_impl data_flow; public: data_flow_uplane_uplink_prach_impl_fixture() : diff --git a/tests/unittests/ofh/receiver/ofh_uplane_prach_data_flow_notifier_test.cpp b/tests/unittests/ofh/receiver/ofh_uplane_prach_data_flow_notifier_test.cpp index 43005e6862..5a0ba4b3ae 100644 --- a/tests/unittests/ofh/receiver/ofh_uplane_prach_data_flow_notifier_test.cpp +++ b/tests/unittests/ofh/receiver/ofh_uplane_prach_data_flow_notifier_test.cpp @@ -19,8 +19,8 @@ using namespace ofh::testing; TEST(ofh_uplane_prach_data_flow_notifier, empty_context_does_not_notify) { - auto notifier = std::make_shared(); - auto repo = std::make_shared(1); + auto notifier = std::make_shared(); + auto repo = std::make_shared(1, srslog::fetch_basic_logger("TEST")); uplane_prach_data_flow_notifier sender(srslog::fetch_basic_logger("TEST"), repo, notifier); slot_point slot(0, 0, 1); @@ -33,8 +33,8 @@ TEST(ofh_uplane_prach_data_flow_notifier, empty_context_does_not_notify) TEST(ofh_uplane_prach_data_flow_notifier, unwritten_buffer_does_not_notify) { - auto notifier = std::make_shared(); - auto repo = std::make_shared(1); + auto notifier = std::make_shared(); + auto repo = std::make_shared(1, srslog::fetch_basic_logger("TEST")); uplane_prach_data_flow_notifier sender(srslog::fetch_basic_logger("TEST"), repo, notifier); slot_point slot(0, 0, 1); prach_buffer_dummy buffer(1); @@ -56,8 +56,8 @@ TEST(ofh_uplane_prach_data_flow_notifier, unwritten_buffer_does_not_notify) TEST(ofh_uplane_prach_data_flow_notifier, completed_long_prach_buffer_triggers_notification) { - auto notifier = std::make_shared(); - auto repo = std::make_shared(1); + auto notifier = std::make_shared(); + auto repo = std::make_shared(1, srslog::fetch_basic_logger("TEST")); uplane_prach_data_flow_notifier sender(srslog::fetch_basic_logger("TEST"), repo, notifier); slot_point slot(0, 0, 1); unsigned symbol = 0; @@ -90,8 +90,8 @@ TEST(ofh_uplane_prach_data_flow_notifier, completed_long_prach_buffer_triggers_n TEST(ofh_uplane_prach_data_flow_notifier, completed_short_prach_buffer_triggers_notification) { - auto notifier = std::make_shared(); - auto repo = std::make_shared(1); + auto notifier = std::make_shared(); + auto repo = std::make_shared(1, srslog::fetch_basic_logger("TEST")); uplane_prach_data_flow_notifier sender(srslog::fetch_basic_logger("TEST"), repo, notifier); slot_point slot(0, 0, 1); unsigned port = 0; diff --git a/tests/unittests/ofh/receiver/ofh_uplane_prach_symbol_data_flow_writer_test.cpp b/tests/unittests/ofh/receiver/ofh_uplane_prach_symbol_data_flow_writer_test.cpp index 3bcbda9fc6..8749126533 100644 --- a/tests/unittests/ofh/receiver/ofh_uplane_prach_symbol_data_flow_writer_test.cpp +++ b/tests/unittests/ofh/receiver/ofh_uplane_prach_symbol_data_flow_writer_test.cpp @@ -29,8 +29,9 @@ class ofh_uplane_prach_symbol_data_flow_writer_fixture : public ::testing::TestW unsigned preamble_length; unsigned nof_symbols; uplane_message_decoder_results results; - std::shared_ptr repo = std::make_shared(1); - uplane_prach_symbol_data_flow_writer writer; + std::shared_ptr repo = + std::make_shared(1, srslog::fetch_basic_logger("TEST")); + uplane_prach_symbol_data_flow_writer writer; public: ofh_uplane_prach_symbol_data_flow_writer_fixture() : diff --git a/tests/unittests/ofh/receiver/ofh_uplane_rx_symbol_data_flow_notifier_test.cpp b/tests/unittests/ofh/receiver/ofh_uplane_rx_symbol_data_flow_notifier_test.cpp index 79ac34a19a..ecbf462cb0 100644 --- a/tests/unittests/ofh/receiver/ofh_uplane_rx_symbol_data_flow_notifier_test.cpp +++ b/tests/unittests/ofh/receiver/ofh_uplane_rx_symbol_data_flow_notifier_test.cpp @@ -19,8 +19,8 @@ using namespace ofh::testing; TEST(ofh_data_flow_uplane_rx_symbol_notifier, empty_context_does_not_notify) { - auto notifier = std::make_shared(); - auto repo = std::make_shared(1); + auto notifier = std::make_shared(); + auto repo = std::make_shared(1, srslog::fetch_basic_logger("TEST")); uplane_rx_symbol_data_flow_notifier sender(srslog::fetch_basic_logger("TEST"), repo, notifier); slot_point slot(0, 0, 1); unsigned symbol = 0; @@ -34,8 +34,8 @@ TEST(ofh_data_flow_uplane_rx_symbol_notifier, empty_context_does_not_notify) TEST(ofh_data_flow_uplane_rx_symbol_notifier, unwritten_grid_does_not_notify) { - auto notifier = std::make_shared(); - auto repo = std::make_shared(1); + auto notifier = std::make_shared(); + auto repo = std::make_shared(1, srslog::fetch_basic_logger("TEST")); uplane_rx_symbol_data_flow_notifier sender(srslog::fetch_basic_logger("TEST"), repo, notifier); slot_point slot(0, 0, 1); unsigned symbol = 0; @@ -52,8 +52,8 @@ TEST(ofh_data_flow_uplane_rx_symbol_notifier, unwritten_grid_does_not_notify) TEST(ofh_data_flow_uplane_rx_symbol_notifier, completed_resource_grid_triggers_notification) { - auto notifier = std::make_shared(); - auto repo = std::make_shared(1); + auto notifier = std::make_shared(); + auto repo = std::make_shared(1, srslog::fetch_basic_logger("TEST")); uplane_rx_symbol_data_flow_notifier sender(srslog::fetch_basic_logger("TEST"), repo, notifier); slot_point slot(0, 0, 1); unsigned symbol = 0; @@ -81,8 +81,8 @@ TEST(ofh_data_flow_uplane_rx_symbol_notifier, completed_resource_grid_triggers_n TEST(ofh_data_flow_uplane_rx_symbol_notifier, uncompleted_port_does_not_notify) { - auto notifier = std::make_shared(); - auto repo = std::make_shared(1); + auto notifier = std::make_shared(); + auto repo = std::make_shared(1, srslog::fetch_basic_logger("TEST")); uplane_rx_symbol_data_flow_notifier sender(srslog::fetch_basic_logger("TEST"), repo, notifier); slot_point slot(0, 0, 1); unsigned symbol = 0; @@ -104,8 +104,8 @@ TEST(ofh_data_flow_uplane_rx_symbol_notifier, uncompleted_port_does_not_notify) TEST(ofh_data_flow_uplane_rx_symbol_notifier, uncompleted_prbs_does_not_notify) { - auto notifier = std::make_shared(); - auto repo = std::make_shared(1); + auto notifier = std::make_shared(); + auto repo = std::make_shared(1, srslog::fetch_basic_logger("TEST")); uplane_rx_symbol_data_flow_notifier sender(srslog::fetch_basic_logger("TEST"), repo, notifier); slot_point slot(0, 0, 1); unsigned symbol = 0; diff --git a/tests/unittests/ofh/receiver/ofh_uplane_rx_symbol_data_flow_writer_test.cpp b/tests/unittests/ofh/receiver/ofh_uplane_rx_symbol_data_flow_writer_test.cpp index f13a3dc615..f1afcdb8b0 100644 --- a/tests/unittests/ofh/receiver/ofh_uplane_rx_symbol_data_flow_writer_test.cpp +++ b/tests/unittests/ofh/receiver/ofh_uplane_rx_symbol_data_flow_writer_test.cpp @@ -20,15 +20,16 @@ using namespace ofh::testing; class ofh_uplane_rx_symbol_data_flow_writer_fixture : public ::testing::Test { protected: - static_vector eaxc = {0, 1, 2, 3}; - std::shared_ptr repo = std::make_shared(1); - unsigned sector = 0; - slot_point slot; - unsigned symbol_id = 0; - resource_grid_writer_bool_spy rg_writer; - resource_grid_dummy_with_spy_writer grid; - uplane_message_decoder_results results; - uplane_rx_symbol_data_flow_writer writer; + static_vector eaxc = {0, 1, 2, 3}; + std::shared_ptr repo = + std::make_shared(1, srslog::fetch_basic_logger("TEST")); + unsigned sector = 0; + slot_point slot; + unsigned symbol_id = 0; + resource_grid_writer_bool_spy rg_writer; + resource_grid_dummy_with_spy_writer grid; + uplane_message_decoder_results results; + uplane_rx_symbol_data_flow_writer writer; public: ofh_uplane_rx_symbol_data_flow_writer_fixture() : diff --git a/tests/unittests/ofh/transmitter/ofh_uplink_request_handler_impl_test.cpp b/tests/unittests/ofh/transmitter/ofh_uplink_request_handler_impl_test.cpp index 79de4d2207..0c3b3ce6d1 100644 --- a/tests/unittests/ofh/transmitter/ofh_uplink_request_handler_impl_test.cpp +++ b/tests/unittests/ofh/transmitter/ofh_uplink_request_handler_impl_test.cpp @@ -167,8 +167,8 @@ class ofh_uplink_request_handler_impl_fixture : public ::testing::Test uplink_request_handler_impl handler_prach_cp_en; explicit ofh_uplink_request_handler_impl_fixture() : - ul_slot_repo(std::make_shared(REPOSITORY_SIZE)), - ul_prach_repo(std::make_shared(REPOSITORY_SIZE)), + ul_slot_repo(std::make_shared(REPOSITORY_SIZE, srslog::fetch_basic_logger("TEST"))), + ul_prach_repo(std::make_shared(REPOSITORY_SIZE, srslog::fetch_basic_logger("TEST"))), handler(get_config_prach_cp_disabled(), get_dependencies_prach_cp_disabled()), handler_prach_cp_en(get_config_prach_cp_enabled(), get_dependencies_prach_cp_enabled()) { From 166d5e3fe649b54f8664a27e4c4f90e52638c5cd Mon Sep 17 00:00:00 2001 From: Alejandro Leal Date: Tue, 9 Jan 2024 15:41:40 +0100 Subject: [PATCH 092/134] ofh: added a parameter in the gnb configuration that configures to ignore the sequence id field of the eCPRI header in reception --- apps/gnb/gnb_appconfig.h | 2 + apps/gnb/gnb_appconfig_cli11_schema.cpp | 2 + apps/gnb/gnb_appconfig_translators.cpp | 1 + include/srsran/ofh/ofh_sector_config.h | 2 + .../ofh/receiver/ofh_receiver_configuration.h | 2 + include/srsran/ru/ru_ofh_configuration.h | 2 + lib/ofh/ofh_factories.cpp | 1 + lib/ofh/receiver/ofh_message_receiver.cpp | 4 +- lib/ofh/receiver/ofh_message_receiver.h | 6 +- lib/ofh/receiver/ofh_receiver_factories.cpp | 12 +- lib/ofh/receiver/ofh_receiver_impl.cpp | 2 + lib/ofh/receiver/ofh_receiver_impl.h | 6 +- lib/ofh/receiver/ofh_sequence_id_checker.h | 74 +---------- .../ofh_sequence_id_checker_dummy_impl.h | 27 ++++ .../receiver/ofh_sequence_id_checker_impl.h | 95 ++++++++++++++ lib/ru/ofh/ru_ofh_factory.cpp | 1 + tests/unittests/ofh/receiver/CMakeLists.txt | 2 +- .../receiver/ofh_message_receiver_test.cpp | 3 + ... => ofh_sequence_id_checker_impl_test.cpp} | 118 +++++++++--------- 19 files changed, 222 insertions(+), 140 deletions(-) create mode 100644 lib/ofh/receiver/ofh_sequence_id_checker_dummy_impl.h create mode 100644 lib/ofh/receiver/ofh_sequence_id_checker_impl.h rename tests/unittests/ofh/receiver/{ofh_sequence_id_checker_test.cpp => ofh_sequence_id_checker_impl_test.cpp} (56%) diff --git a/apps/gnb/gnb_appconfig.h b/apps/gnb/gnb_appconfig.h index e3650f94d6..91496e6a5d 100644 --- a/apps/gnb/gnb_appconfig.h +++ b/apps/gnb/gnb_appconfig.h @@ -964,6 +964,8 @@ struct ru_ofh_base_cell_appconfig { bool is_downlink_broadcast_enabled = false; /// If set to true, the payload size encoded in a eCPRI header is ignored. bool ignore_ecpri_payload_size_field = false; + /// If set to true, the sequence id encoded in a eCPRI packet is ignored. + bool ignore_ecpri_seq_id_field = false; /// Uplink compression method. std::string compression_method_ul = "bfp"; /// Uplink compression bitwidth. diff --git a/apps/gnb/gnb_appconfig_cli11_schema.cpp b/apps/gnb/gnb_appconfig_cli11_schema.cpp index 0b23738b64..7ceb7ba3e5 100644 --- a/apps/gnb/gnb_appconfig_cli11_schema.cpp +++ b/apps/gnb/gnb_appconfig_cli11_schema.cpp @@ -1726,6 +1726,8 @@ static void configure_cli11_ru_ofh_base_cell_args(CLI::App& app, ru_ofh_base_cel ->capture_default_str(); app.add_option("--is_dl_broadcast_enabled", config.is_downlink_broadcast_enabled, "Downlink broadcast enabled flag") ->capture_default_str(); + app.add_option("--ignore_ecpri_seq_id", config.ignore_ecpri_seq_id_field, "Ignore eCPRI sequence id field value") + ->capture_default_str(); app.add_option( "--ignore_ecpri_payload_size", config.ignore_ecpri_payload_size_field, "Ignore eCPRI payload size field value") ->capture_default_str(); diff --git a/apps/gnb/gnb_appconfig_translators.cpp b/apps/gnb/gnb_appconfig_translators.cpp index f409497fb6..5dfe0bf25a 100644 --- a/apps/gnb/gnb_appconfig_translators.cpp +++ b/apps/gnb/gnb_appconfig_translators.cpp @@ -1450,6 +1450,7 @@ generate_ru_ofh_config(ru_ofh_configuration& out_cfg, const gnb_appconfig& confi sector_cfg.is_prach_control_plane_enabled = cell_cfg.cell.is_prach_control_plane_enabled; sector_cfg.is_downlink_broadcast_enabled = cell_cfg.cell.is_downlink_broadcast_enabled; sector_cfg.ignore_ecpri_payload_size_field = cell_cfg.cell.ignore_ecpri_payload_size_field; + sector_cfg.ignore_ecpri_seq_id_field = cell_cfg.cell.ignore_ecpri_seq_id_field; sector_cfg.ul_compression_params = {ofh::to_compression_type(cell_cfg.cell.compression_method_ul), cell_cfg.cell.compression_bitwidth_ul}; sector_cfg.dl_compression_params = {ofh::to_compression_type(cell_cfg.cell.compression_method_dl), diff --git a/include/srsran/ofh/ofh_sector_config.h b/include/srsran/ofh/ofh_sector_config.h index 60312a45e1..df98a1a06f 100644 --- a/include/srsran/ofh/ofh_sector_config.h +++ b/include/srsran/ofh/ofh_sector_config.h @@ -73,6 +73,8 @@ struct sector_configuration { bool is_downlink_broadcast_enabled = false; /// If set to true, the payload size encoded in a eCPRI header is ignored. bool ignore_ecpri_payload_size_field = false; + /// If set to true, the sequence id encoded in a eCPRI packet is ignored. + bool ignore_ecpri_seq_id_field = false; /// Uplink compression parameters. ofh::ru_compression_params ul_compression_params; /// Downlink compression parameters. diff --git a/include/srsran/ofh/receiver/ofh_receiver_configuration.h b/include/srsran/ofh/receiver/ofh_receiver_configuration.h index 44ceb979c0..a714b9064b 100644 --- a/include/srsran/ofh/receiver/ofh_receiver_configuration.h +++ b/include/srsran/ofh/receiver/ofh_receiver_configuration.h @@ -54,6 +54,8 @@ struct receiver_config { bool is_prach_control_plane_enabled = false; /// If set to true, the payload size encoded in a eCPRI header is ignored. bool ignore_ecpri_payload_size_field = false; + /// If set to true, the sequence id encoded in a eCPRI packet is ignored. + bool ignore_ecpri_seq_id_field = false; }; } // namespace ofh diff --git a/include/srsran/ru/ru_ofh_configuration.h b/include/srsran/ru/ru_ofh_configuration.h index 756e50016b..f1a7a8728f 100644 --- a/include/srsran/ru/ru_ofh_configuration.h +++ b/include/srsran/ru/ru_ofh_configuration.h @@ -46,6 +46,8 @@ struct ru_ofh_sector_configuration { bool is_downlink_broadcast_enabled = false; /// If set to true, the payload size encoded in a eCPRI header is ignored. bool ignore_ecpri_payload_size_field = false; + /// If set to true, the sequence id encoded in a eCPRI packet is ignored. + bool ignore_ecpri_seq_id_field = false; /// Uplink compression parameters. ofh::ru_compression_params ul_compression_params; /// Downlink compression parameters. diff --git a/lib/ofh/ofh_factories.cpp b/lib/ofh/ofh_factories.cpp index caa561cca4..c30f953813 100644 --- a/lib/ofh/ofh_factories.cpp +++ b/lib/ofh/ofh_factories.cpp @@ -44,6 +44,7 @@ static receiver_config generate_receiver_config(const sector_configuration& conf rx_config.ul_compression_params = config.ul_compression_params; rx_config.is_prach_control_plane_enabled = config.is_prach_control_plane_enabled; rx_config.ignore_ecpri_payload_size_field = config.ignore_ecpri_payload_size_field; + rx_config.ignore_ecpri_seq_id_field = config.ignore_ecpri_seq_id_field; // In rx, dst and src addresses are swapped. rx_config.mac_dst_address = config.mac_src_address; diff --git a/lib/ofh/receiver/ofh_message_receiver.cpp b/lib/ofh/receiver/ofh_message_receiver.cpp index a1a0408757..97e780f729 100644 --- a/lib/ofh/receiver/ofh_message_receiver.cpp +++ b/lib/ofh/receiver/ofh_message_receiver.cpp @@ -21,6 +21,7 @@ message_receiver::message_receiver(const message_receiver_config& config, ul_prach_eaxc(config.prach_eaxc), ul_eaxc(config.ul_eaxc), window_checker(*dependencies.window_checker), + seq_id_checker(std::move(dependencies.seq_id_checker)), vlan_decoder(std::move(dependencies.eth_frame_decoder)), ecpri_decoder(std::move(dependencies.ecpri_decoder)), uplane_decoder(std::move(dependencies.uplane_decoder)), @@ -32,6 +33,7 @@ message_receiver::message_receiver(const message_receiver_config& config, srsran_assert(uplane_decoder, "Invalid User-Plane decoder"); srsran_assert(data_flow_uplink, "Invalid uplink IQ data flow"); srsran_assert(data_flow_prach, "Invalid uplink PRACH IQ data flow"); + srsran_assert(seq_id_checker, "Invalid sequence id checker"); } void message_receiver::on_new_frame(span payload) @@ -51,7 +53,7 @@ void message_receiver::on_new_frame(span payload) // Verify the sequence identifier. const ecpri::iq_data_parameters& ecpri_iq_params = variant_get(ecpri_params.type_params); int nof_skipped_seq_id = - seq_id_checker.update_and_compare_seq_id(ecpri_iq_params.pc_id, (ecpri_iq_params.seq_id >> 8)); + seq_id_checker->update_and_compare_seq_id(ecpri_iq_params.pc_id, (ecpri_iq_params.seq_id >> 8)); // Drop the message when it is from the past. if (nof_skipped_seq_id < 0) { logger.info("Dropped received Open Fronthaul User-Plane packet as sequence identifier field is from the past"); diff --git a/lib/ofh/receiver/ofh_message_receiver.h b/lib/ofh/receiver/ofh_message_receiver.h index 1b624ab404..3e3ffc3962 100644 --- a/lib/ofh/receiver/ofh_message_receiver.h +++ b/lib/ofh/receiver/ofh_message_receiver.h @@ -12,7 +12,7 @@ #include "ofh_data_flow_uplane_uplink_data.h" #include "ofh_data_flow_uplane_uplink_prach.h" -#include "ofh_sequence_id_checker.h" +#include "ofh_sequence_id_checker_impl.h" #include "srsran/adt/static_vector.h" #include "srsran/ofh/ecpri/ecpri_packet_decoder.h" #include "srsran/ofh/ethernet/ethernet_frame_notifier.h" @@ -54,6 +54,8 @@ struct message_receiver_dependencies { std::unique_ptr data_flow_uplink; /// User-Plane uplink PRACH data flow. std::unique_ptr data_flow_prach; + /// Sequence id checker. + std::unique_ptr seq_id_checker; }; /// Open Fronthaul message receiver. @@ -95,8 +97,8 @@ class message_receiver : public ether::frame_notifier const ether::vlan_frame_params vlan_params; const static_vector ul_prach_eaxc; const static_vector ul_eaxc; - sequence_id_checker seq_id_checker; rx_window_checker& window_checker; + std::unique_ptr seq_id_checker; std::unique_ptr vlan_decoder; std::unique_ptr ecpri_decoder; std::unique_ptr uplane_decoder; diff --git a/lib/ofh/receiver/ofh_receiver_factories.cpp b/lib/ofh/receiver/ofh_receiver_factories.cpp index f30b4b81c0..61c85af5a2 100644 --- a/lib/ofh/receiver/ofh_receiver_factories.cpp +++ b/lib/ofh/receiver/ofh_receiver_factories.cpp @@ -12,6 +12,8 @@ #include "ofh_data_flow_uplane_uplink_data_impl.h" #include "ofh_data_flow_uplane_uplink_prach_impl.h" #include "ofh_receiver_impl.h" +#include "ofh_sequence_id_checker_dummy_impl.h" +#include "ofh_sequence_id_checker_impl.h" #include "srsran/ofh/compression/compression_factory.h" #include "srsran/ofh/ecpri/ecpri_factories.h" #include "srsran/ofh/ethernet/ethernet_factories.h" @@ -101,10 +103,7 @@ resolve_receiver_dependencies(const receiver_config& { receiver_impl_dependencies dependencies; - dependencies.logger = &logger; - dependencies.prach_context_repo_ptr = prach_context_repo; - dependencies.ul_context_repo_ptr = ul_slot_context_repo; - + dependencies.logger = &logger; dependencies.uplane_decoder = create_uplane_decoder(receiver_cfg, logger); if (receiver_cfg.ignore_ecpri_payload_size_field) { @@ -119,6 +118,11 @@ resolve_receiver_dependencies(const receiver_config& dependencies.data_flow_prach = create_uplink_prach_data_flow(receiver_cfg, logger, notifier, prach_context_repo, ul_cp_context_repo); + dependencies.seq_id_checker = + (receiver_cfg.ignore_ecpri_seq_id_field) + ? static_cast>(std::make_unique()) + : static_cast>(std::make_unique()); + return dependencies; } diff --git a/lib/ofh/receiver/ofh_receiver_impl.cpp b/lib/ofh/receiver/ofh_receiver_impl.cpp index 1374c38296..e01ef6c2af 100644 --- a/lib/ofh/receiver/ofh_receiver_impl.cpp +++ b/lib/ofh/receiver/ofh_receiver_impl.cpp @@ -46,6 +46,8 @@ static message_receiver_dependencies get_message_receiver_dependencies(receiver_ srsran_assert(dependencies.data_flow_uplink, "Invalid uplink data flow decoder"); dependencies.data_flow_prach = std::move(rx_dependencies.data_flow_prach); srsran_assert(dependencies.data_flow_prach, "Invalid PRACH data flow decoder"); + dependencies.seq_id_checker = std::move(rx_dependencies.seq_id_checker); + srsran_assert(dependencies.seq_id_checker, "Invalid sequence id checker"); return dependencies; } diff --git a/lib/ofh/receiver/ofh_receiver_impl.h b/lib/ofh/receiver/ofh_receiver_impl.h index bd74614ade..6f658021de 100644 --- a/lib/ofh/receiver/ofh_receiver_impl.h +++ b/lib/ofh/receiver/ofh_receiver_impl.h @@ -36,10 +36,8 @@ struct receiver_impl_dependencies { std::unique_ptr data_flow_uplink; /// User-Plane uplink PRACH data flow. std::unique_ptr data_flow_prach; - /// PRACH context repository. - std::shared_ptr prach_context_repo_ptr; - /// Uplink context repository. - std::shared_ptr ul_context_repo_ptr; + /// Sequence id checker. + std::unique_ptr seq_id_checker; }; /// \brief Open Fronthaul receiver. diff --git a/lib/ofh/receiver/ofh_sequence_id_checker.h b/lib/ofh/receiver/ofh_sequence_id_checker.h index 4b1161f1e4..294e0cb4fe 100644 --- a/lib/ofh/receiver/ofh_sequence_id_checker.h +++ b/lib/ofh/receiver/ofh_sequence_id_checker.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 @@ -10,9 +10,7 @@ #pragma once -#include "srsran/adt/bounded_bitset.h" -#include "srsran/adt/circular_map.h" -#include "srsran/ofh/ofh_constants.h" +#include namespace srsran { namespace ofh { @@ -20,20 +18,9 @@ namespace ofh { /// Open Fronthaul sequence identifier checker. class sequence_id_checker { - static constexpr int NOF_SEQUENCES_IDENTIFIERS = 1u << 8; - static constexpr int HALF_NOF_SEQUENCES_IDENTIFIERS = NOF_SEQUENCES_IDENTIFIERS / 2; - - bounded_bitset initialized; - circular_map counters; - public: - /// Default constructor. - sequence_id_checker() : initialized(MAX_SUPPORTED_EAXC_ID_VALUE) - { - for (unsigned K = 0; K != MAX_SUPPORTED_EAXC_ID_VALUE; ++K) { - counters.insert(K, 0); - } - } + /// Default destructor. + virtual ~sequence_id_checker() = default; /// \brief Updates the expected sequence identifier value for the given eAxC and compares it with the given sequence /// identifier, returning the difference between them. @@ -42,58 +29,7 @@ class sequence_id_checker /// A difference of 0 means that the current sequence identifier matches the expected. /// A positive difference means that the sequence identifier belongs to the future. In this case, the expected /// sequence identifier is updated with the given sequence identifier. - int update_and_compare_seq_id(unsigned eaxc, uint8_t seq_id) - { - srsran_assert(eaxc < MAX_SUPPORTED_EAXC_ID_VALUE, - "Invalid eAxC value '{}'. Maximum eAxC value is '{}'", - eaxc, - MAX_SUPPORTED_EAXC_ID_VALUE); - - // First packet is always valid. - if (!initialized.test(eaxc)) { - initialized.set(eaxc); - counters[eaxc] = seq_id; - - return 0; - } - - // Get the expected sequence identifier and update its value. - uint8_t expected_seq_id = counters[eaxc] + 1; - - if (seq_id == expected_seq_id) { - ++counters[eaxc]; - - return 0; - } - - int nof_skipped_seq_id = get_nof_skipped_sequence_id(seq_id, expected_seq_id); - - // Update the expected sequence identifier when the sequence identifier is from the future. - if (nof_skipped_seq_id > 0) { - counters[eaxc] = seq_id; - } - - return nof_skipped_seq_id; - } - -private: - /// \brief Returns the number of skipped sequence identifiers using the given sequence identifier and expected - /// sequence identifier. - /// - /// A negative difference means that the sequence identifier received is from the past. - /// No difference means that the sequence identifier matches the expected. - /// A positive difference means that the sequence identifier is from the future. - static int get_nof_skipped_sequence_id(uint8_t seq_id, uint8_t expected_seq_id) - { - int a = static_cast(seq_id) - static_cast(expected_seq_id); - if (a >= HALF_NOF_SEQUENCES_IDENTIFIERS) { - return a - NOF_SEQUENCES_IDENTIFIERS; - } - if (a < -HALF_NOF_SEQUENCES_IDENTIFIERS) { - return a + NOF_SEQUENCES_IDENTIFIERS; - } - return a; - } + virtual int update_and_compare_seq_id(unsigned eaxc, uint8_t seq_id) = 0; }; } // namespace ofh diff --git a/lib/ofh/receiver/ofh_sequence_id_checker_dummy_impl.h b/lib/ofh/receiver/ofh_sequence_id_checker_dummy_impl.h new file mode 100644 index 0000000000..13537fdf13 --- /dev/null +++ b/lib/ofh/receiver/ofh_sequence_id_checker_dummy_impl.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 + +#include "ofh_sequence_id_checker.h" + +namespace srsran { +namespace ofh { + +/// Open Fronthaul sequence identifier checker dummy implementation. +class sequence_id_checker_dummy_impl : public sequence_id_checker +{ +public: + // See interface for documentation. + int update_and_compare_seq_id(unsigned eaxc, uint8_t seq_id) override { return 0; }; +}; + +} // namespace ofh +} // namespace srsran diff --git a/lib/ofh/receiver/ofh_sequence_id_checker_impl.h b/lib/ofh/receiver/ofh_sequence_id_checker_impl.h new file mode 100644 index 0000000000..ecf4dca63c --- /dev/null +++ b/lib/ofh/receiver/ofh_sequence_id_checker_impl.h @@ -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. + * + */ + +#pragma once + +#include "ofh_sequence_id_checker.h" +#include "srsran/adt/bounded_bitset.h" +#include "srsran/adt/circular_map.h" +#include "srsran/ofh/ofh_constants.h" + +namespace srsran { +namespace ofh { + +/// Open Fronthaul sequence identifier checker implementation. +class sequence_id_checker_impl : public sequence_id_checker +{ + static constexpr int NOF_SEQUENCES_IDENTIFIERS = 1u << 8; + static constexpr int HALF_NOF_SEQUENCES_IDENTIFIERS = NOF_SEQUENCES_IDENTIFIERS / 2; + + bounded_bitset initialized; + circular_map counters; + +public: + /// Default constructor. + sequence_id_checker_impl() : initialized(MAX_SUPPORTED_EAXC_ID_VALUE) + { + for (unsigned K = 0; K != MAX_SUPPORTED_EAXC_ID_VALUE; ++K) { + counters.insert(K, 0); + } + } + + // See interface for documentation. + int update_and_compare_seq_id(unsigned eaxc, uint8_t seq_id) override + { + srsran_assert(eaxc < MAX_SUPPORTED_EAXC_ID_VALUE, + "Invalid eAxC value '{}'. Maximum eAxC value is '{}'", + eaxc, + MAX_SUPPORTED_EAXC_ID_VALUE); + + // First packet is always valid. + if (!initialized.test(eaxc)) { + initialized.set(eaxc); + counters[eaxc] = seq_id; + + return 0; + } + + // Get the expected sequence identifier and update its value. + uint8_t expected_seq_id = counters[eaxc] + 1; + + if (seq_id == expected_seq_id) { + ++counters[eaxc]; + + return 0; + } + + int nof_skipped_seq_id = get_nof_skipped_sequence_id(seq_id, expected_seq_id); + + // Update the expected sequence identifier when the sequence identifier is from the future. + if (nof_skipped_seq_id > 0) { + counters[eaxc] = seq_id; + } + + return nof_skipped_seq_id; + } + +private: + /// \brief Returns the number of skipped sequence identifiers using the given sequence identifier and expected + /// sequence identifier. + /// + /// A negative difference means that the sequence identifier received is from the past. + /// No difference means that the sequence identifier matches the expected. + /// A positive difference means that the sequence identifier is from the future. + static int get_nof_skipped_sequence_id(uint8_t seq_id, uint8_t expected_seq_id) + { + int a = static_cast(seq_id) - static_cast(expected_seq_id); + if (a >= HALF_NOF_SEQUENCES_IDENTIFIERS) { + return a - NOF_SEQUENCES_IDENTIFIERS; + } + if (a < -HALF_NOF_SEQUENCES_IDENTIFIERS) { + return a + NOF_SEQUENCES_IDENTIFIERS; + } + return a; + } +}; + +} // namespace ofh +} // namespace srsran diff --git a/lib/ru/ofh/ru_ofh_factory.cpp b/lib/ru/ofh/ru_ofh_factory.cpp index 623f763e73..fbe53ba305 100644 --- a/lib/ru/ofh/ru_ofh_factory.cpp +++ b/lib/ru/ofh/ru_ofh_factory.cpp @@ -42,6 +42,7 @@ static ofh::sector_configuration generate_sector_configuration(const ru_ofh_conf ofh_sector_config.is_prach_control_plane_enabled = sector_cfg.is_prach_control_plane_enabled; ofh_sector_config.is_downlink_broadcast_enabled = sector_cfg.is_downlink_broadcast_enabled; ofh_sector_config.ignore_ecpri_payload_size_field = sector_cfg.ignore_ecpri_payload_size_field; + ofh_sector_config.ignore_ecpri_seq_id_field = sector_cfg.ignore_ecpri_seq_id_field; ofh_sector_config.ul_compression_params = sector_cfg.ul_compression_params; ofh_sector_config.dl_compression_params = sector_cfg.dl_compression_params; ofh_sector_config.prach_compression_params = sector_cfg.prach_compression_params; diff --git a/tests/unittests/ofh/receiver/CMakeLists.txt b/tests/unittests/ofh/receiver/CMakeLists.txt index 4a50680703..823ea8faba 100644 --- a/tests/unittests/ofh/receiver/CMakeLists.txt +++ b/tests/unittests/ofh/receiver/CMakeLists.txt @@ -40,7 +40,7 @@ add_executable(ofh_uplane_rx_symbol_data_flow_writer_test ofh_uplane_rx_symbol_d target_link_libraries(ofh_uplane_rx_symbol_data_flow_writer_test srsran_ofh_receiver srsran_support gtest gtest_main) gtest_discover_tests(ofh_uplane_rx_symbol_data_flow_writer_test) -add_executable(ofh_sequence_id_checker_test ofh_sequence_id_checker_test.cpp) +add_executable(ofh_sequence_id_checker_test ofh_sequence_id_checker_impl_test.cpp) target_link_libraries(ofh_sequence_id_checker_test srsran_support gtest gtest_main) gtest_discover_tests(ofh_sequence_id_checker_test) diff --git a/tests/unittests/ofh/receiver/ofh_message_receiver_test.cpp b/tests/unittests/ofh/receiver/ofh_message_receiver_test.cpp index add80b2537..563813c49b 100644 --- a/tests/unittests/ofh/receiver/ofh_message_receiver_test.cpp +++ b/tests/unittests/ofh/receiver/ofh_message_receiver_test.cpp @@ -10,6 +10,7 @@ #include "../../../../lib/ofh/receiver/ofh_message_receiver.h" #include "../../../../lib/ofh/receiver/ofh_rx_window_checker.h" +#include "../../../../lib/ofh/receiver/ofh_sequence_id_checker_dummy_impl.h" #include "../compression/ofh_iq_decompressor_test_doubles.h" #include "srsran/ofh/ofh_factories.h" #include @@ -167,6 +168,8 @@ class ofh_message_receiver_fixture : public ::testing::Test ecpri_decoder = temp.get(); dependencies.ecpri_decoder = std::move(temp); } + dependencies.seq_id_checker = std::make_unique(); + return dependencies; } }; diff --git a/tests/unittests/ofh/receiver/ofh_sequence_id_checker_test.cpp b/tests/unittests/ofh/receiver/ofh_sequence_id_checker_impl_test.cpp similarity index 56% rename from tests/unittests/ofh/receiver/ofh_sequence_id_checker_test.cpp rename to tests/unittests/ofh/receiver/ofh_sequence_id_checker_impl_test.cpp index ac96933969..8ef2dea357 100644 --- a/tests/unittests/ofh/receiver/ofh_sequence_id_checker_test.cpp +++ b/tests/unittests/ofh/receiver/ofh_sequence_id_checker_impl_test.cpp @@ -8,26 +8,26 @@ * */ -#include "../../../../lib/ofh/receiver/ofh_sequence_id_checker.h" +#include "../../../../lib/ofh/receiver/ofh_sequence_id_checker_impl.h" #include using namespace srsran; using namespace ofh; -TEST(ofh_sequence_id_checker, first_message_is_always_ok) +TEST(ofh_sequence_id_checker_impl, first_message_is_always_ok) { - sequence_id_checker checker; - unsigned eaxc = 0; - unsigned seq_id = 1; + sequence_id_checker_impl checker; + unsigned eaxc = 0; + unsigned seq_id = 1; ASSERT_EQ(0, checker.update_and_compare_seq_id(eaxc, seq_id)); } -TEST(ofh_sequence_id_checker, consecutive_messages_is_ok) +TEST(ofh_sequence_id_checker_impl, consecutive_messages_is_ok) { - sequence_id_checker checker; - unsigned eaxc = 0; - unsigned seq_id = 1; + sequence_id_checker_impl checker; + unsigned eaxc = 0; + unsigned seq_id = 1; ASSERT_EQ(0, checker.update_and_compare_seq_id(eaxc, seq_id)); @@ -38,11 +38,11 @@ TEST(ofh_sequence_id_checker, consecutive_messages_is_ok) ASSERT_EQ(0, checker.update_and_compare_seq_id(eaxc, seq_id)); } -TEST(ofh_sequence_id_checker, message_from_the_past_is_detected) +TEST(ofh_sequence_id_checker_impl, message_from_the_past_is_detected) { - sequence_id_checker checker; - unsigned eaxc = 0; - unsigned seq_id = 1; + sequence_id_checker_impl checker; + unsigned eaxc = 0; + unsigned seq_id = 1; ASSERT_EQ(0, checker.update_and_compare_seq_id(eaxc, seq_id)); @@ -51,11 +51,11 @@ TEST(ofh_sequence_id_checker, message_from_the_past_is_detected) ASSERT_EQ(-2, checker.update_and_compare_seq_id(eaxc, seq_id)); } -TEST(ofh_sequence_id_checker, message_from_the_past_is_detected_with_big_difference) +TEST(ofh_sequence_id_checker_impl, message_from_the_past_is_detected_with_big_difference) { - sequence_id_checker checker; - unsigned eaxc = 0; - unsigned seq_id = 14; + sequence_id_checker_impl checker; + unsigned eaxc = 0; + unsigned seq_id = 14; ASSERT_EQ(0, checker.update_and_compare_seq_id(eaxc, seq_id)); @@ -64,21 +64,21 @@ TEST(ofh_sequence_id_checker, message_from_the_past_is_detected_with_big_differe ASSERT_EQ(-36, checker.update_and_compare_seq_id(eaxc, seq_id)); } -TEST(ofh_sequence_id_checker, message_from_the_past_in_the_edge_is_detected) +TEST(ofh_sequence_id_checker_impl, message_from_the_past_in_the_edge_is_detected) { - sequence_id_checker checker; - unsigned eaxc = 0; - uint8_t seq_id = 255; + sequence_id_checker_impl checker; + unsigned eaxc = 0; + uint8_t seq_id = 255; ASSERT_EQ(0, checker.update_and_compare_seq_id(eaxc, seq_id)); ASSERT_EQ(-1, checker.update_and_compare_seq_id(eaxc, seq_id)); } -TEST(ofh_sequence_id_checker, message_from_the_future_is_detected) +TEST(ofh_sequence_id_checker_impl, message_from_the_future_is_detected) { - sequence_id_checker checker; - unsigned eaxc = 0; - unsigned seq_id = 1; + sequence_id_checker_impl checker; + unsigned eaxc = 0; + unsigned seq_id = 1; ASSERT_EQ(0, checker.update_and_compare_seq_id(eaxc, seq_id)); @@ -87,11 +87,11 @@ TEST(ofh_sequence_id_checker, message_from_the_future_is_detected) ASSERT_EQ(3, checker.update_and_compare_seq_id(eaxc, seq_id)); } -TEST(ofh_sequence_id_checker, message_from_the_future_in_the_edge_is_detected) +TEST(ofh_sequence_id_checker_impl, message_from_the_future_in_the_edge_is_detected) { - sequence_id_checker checker; - unsigned eaxc = 0; - unsigned seq_id = 254; + sequence_id_checker_impl checker; + unsigned eaxc = 0; + unsigned seq_id = 254; ASSERT_EQ(0, checker.update_and_compare_seq_id(eaxc, seq_id)); @@ -100,11 +100,11 @@ TEST(ofh_sequence_id_checker, message_from_the_future_in_the_edge_is_detected) ASSERT_EQ(1, checker.update_and_compare_seq_id(eaxc, seq_id)); } -TEST(ofh_sequence_id_checker, message_from_the_future_is_detected_with_big_difference) +TEST(ofh_sequence_id_checker_impl, message_from_the_future_is_detected_with_big_difference) { - sequence_id_checker checker; - unsigned eaxc = 0; - unsigned seq_id = 234; + sequence_id_checker_impl checker; + unsigned eaxc = 0; + unsigned seq_id = 234; ASSERT_EQ(0, checker.update_and_compare_seq_id(eaxc, seq_id)); @@ -113,13 +113,13 @@ TEST(ofh_sequence_id_checker, message_from_the_future_is_detected_with_big_diffe ASSERT_EQ(51, checker.update_and_compare_seq_id(eaxc, seq_id)); } -TEST(ofh_sequence_id_checker, two_eaxc_with_different_seq_id_is_ok) +TEST(ofh_sequence_id_checker_impl, two_eaxc_with_different_seq_id_is_ok) { - sequence_id_checker checker; - unsigned eaxc_1 = 0; - unsigned seq_id_1 = 1; - unsigned eaxc_2 = 2; - unsigned seq_id_2 = 200; + sequence_id_checker_impl checker; + unsigned eaxc_1 = 0; + unsigned seq_id_1 = 1; + unsigned eaxc_2 = 2; + unsigned seq_id_2 = 200; ASSERT_EQ(0, checker.update_and_compare_seq_id(eaxc_1, seq_id_1)); ASSERT_EQ(0, checker.update_and_compare_seq_id(eaxc_2, seq_id_2)); @@ -133,13 +133,13 @@ TEST(ofh_sequence_id_checker, two_eaxc_with_different_seq_id_is_ok) } } -TEST(ofh_sequence_id_checker, two_eaxc_with_different_seq_id_detects_past_message) +TEST(ofh_sequence_id_checker_impl, two_eaxc_with_different_seq_id_detects_past_message) { - sequence_id_checker checker; - unsigned eaxc_1 = 0; - unsigned seq_id_1 = 1; - unsigned eaxc_2 = 2; - unsigned seq_id_2 = 200; + sequence_id_checker_impl checker; + unsigned eaxc_1 = 0; + unsigned seq_id_1 = 1; + unsigned eaxc_2 = 2; + unsigned seq_id_2 = 200; ASSERT_EQ(0, checker.update_and_compare_seq_id(eaxc_1, seq_id_1)); ASSERT_EQ(0, checker.update_and_compare_seq_id(eaxc_2, seq_id_2)); @@ -151,13 +151,13 @@ TEST(ofh_sequence_id_checker, two_eaxc_with_different_seq_id_detects_past_messag ASSERT_EQ(-101, checker.update_and_compare_seq_id(eaxc_2, seq_id_2)); } -TEST(ofh_sequence_id_checker, two_eaxc_with_different_seq_id_detects_future_message) +TEST(ofh_sequence_id_checker_impl, two_eaxc_with_different_seq_id_detects_future_message) { - sequence_id_checker checker; - unsigned eaxc_1 = 0; - unsigned seq_id_1 = 1; - unsigned eaxc_2 = 2; - unsigned seq_id_2 = 200; + sequence_id_checker_impl checker; + unsigned eaxc_1 = 0; + unsigned seq_id_1 = 1; + unsigned eaxc_2 = 2; + unsigned seq_id_2 = 200; ASSERT_EQ(0, checker.update_and_compare_seq_id(eaxc_1, seq_id_1)); ASSERT_EQ(0, checker.update_and_compare_seq_id(eaxc_2, seq_id_2)); @@ -169,11 +169,11 @@ TEST(ofh_sequence_id_checker, two_eaxc_with_different_seq_id_detects_future_mess ASSERT_EQ(70, checker.update_and_compare_seq_id(eaxc_2, seq_id_2)); } -TEST(ofh_sequence_id_checker, message_from_the_past_does_not_modify_internal_seq_id) +TEST(ofh_sequence_id_checker_impl, message_from_the_past_does_not_modify_internal_seq_id) { - sequence_id_checker checker; - unsigned eaxc = 0; - unsigned seq_id = 1; + sequence_id_checker_impl checker; + unsigned eaxc = 0; + unsigned seq_id = 1; ASSERT_EQ(0, checker.update_and_compare_seq_id(eaxc, seq_id)); @@ -186,12 +186,12 @@ TEST(ofh_sequence_id_checker, message_from_the_past_does_not_modify_internal_seq ASSERT_EQ(-1, checker.update_and_compare_seq_id(eaxc, seq_id)); } -TEST(ofh_sequence_id_checker, +TEST(ofh_sequence_id_checker_impl, message_from_the_past_does_not_modify_internal_seq_id_and_will_resume_if_gets_to_the_expected_seq_id) { - sequence_id_checker checker; - unsigned eaxc = 0; - unsigned seq_id = 1; + sequence_id_checker_impl checker; + unsigned eaxc = 0; + unsigned seq_id = 1; ASSERT_EQ(0, checker.update_and_compare_seq_id(eaxc, seq_id)); From ce51eaf78e4e980f56e679bab61a42362dfc077a Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Mon, 8 Jan 2024 18:09:15 +0100 Subject: [PATCH 093/134] f1ap-cu: remove unused f1u-cu file --- include/srsran/f1ap/cu_cp/f1u_cu.h | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 include/srsran/f1ap/cu_cp/f1u_cu.h diff --git a/include/srsran/f1ap/cu_cp/f1u_cu.h b/include/srsran/f1ap/cu_cp/f1u_cu.h deleted file mode 100644 index d3d45eea44..0000000000 --- a/include/srsran/f1ap/cu_cp/f1u_cu.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "srsran/ran/nr_up_protocol.h" - -namespace srsran { - -/// This interface represents a single F1-U bearer in the CU used to transmit NR user plane messages. -class f1u_cu_message_handler -{ -public: - virtual ~f1u_cu_message_handler() = default; - - /// Handle the incoming NR user plane message. - virtual void handle_message(nr_up_dl_message msg) = 0; -}; - -/// This interface notifies the reception of new messages over a single F1-U bearer in the CU. -class f1u_cu_message_notifier -{ -public: - virtual ~f1u_cu_message_notifier() = default; - - /// This callback is invoked on each received NR user plane message. - virtual void on_new_message(nr_up_ul_message msg) = 0; -}; - -} // namespace srsran From 7a354449b6154785e474544fe0fa044a8bf42fb0 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 9 Jan 2024 16:17:09 +0100 Subject: [PATCH 094/134] cu-cp: removal of asn1 from the ue rrc srb config in the CU-CP --- include/srsran/pdcp/pdcp_config.h | 96 +-------------- include/srsran/pdcp/pdcp_t_reordering.h | 114 ++++++++++++++++++ include/srsran/rrc/rrc_config.h | 19 +-- include/srsran/rrc/rrc_ue.h | 30 +++-- .../inter_cu_handover_target_routine.cpp | 2 +- .../mobility/inter_du_handover_routine.cpp | 2 +- .../rrc_reestablishment_procedure.cpp | 2 +- lib/rrc/ue/procedures/rrc_setup_procedure.cpp | 2 +- lib/rrc/ue/procedures/rrc_setup_procedure.h | 1 - lib/rrc/ue/rrc_ue_impl.cpp | 2 +- .../cu_cp/du_processor/du_processor_test.cpp | 2 +- 11 files changed, 155 insertions(+), 117 deletions(-) create mode 100644 include/srsran/pdcp/pdcp_t_reordering.h diff --git a/include/srsran/pdcp/pdcp_config.h b/include/srsran/pdcp/pdcp_config.h index 3916c8c616..582545b101 100644 --- a/include/srsran/pdcp/pdcp_config.h +++ b/include/srsran/pdcp/pdcp_config.h @@ -11,6 +11,7 @@ #pragma once #include "srsran/adt/optional.h" +#include "srsran/pdcp/pdcp_t_reordering.h" #include "fmt/format.h" #include #include @@ -68,101 +69,6 @@ constexpr uint16_t pdcp_max_sdu_size = 9000; /// PDCP security direction enum class pdcp_security_direction { uplink, downlink }; -/// PDCP NR t-Reordering timer values. -/// This timer is used to detect loss of PDCP Data PDUs. -/// See TS 38.322 for timer description and TS 38.331 for valid timer durations. -enum class pdcp_t_reordering { - ms0 = 0, - ms1 = 1, - ms2 = 2, - ms4 = 4, - ms5 = 5, - ms8 = 8, - ms10 = 10, - ms15 = 15, - ms20 = 20, - ms30 = 30, - ms40 = 40, - ms50 = 50, - ms60 = 60, - ms80 = 80, - ms100 = 100, - ms120 = 120, - ms140 = 140, - ms160 = 160, - ms180 = 180, - ms200 = 200, - ms220 = 220, - ms240 = 240, - ms260 = 260, - ms280 = 280, - ms300 = 300, - ms500 = 500, - ms750 = 750, - ms1000 = 1000, - ms1250 = 1250, - ms1500 = 1500, - ms1750 = 1750, - ms2000 = 2000, - ms2250 = 2250, - ms2500 = 2500, - ms2750 = 2750, - ms3000 = 3000, - infinity = -1 -}; -inline bool pdcp_t_reordering_from_int(pdcp_t_reordering& t_reord, int num) -{ - switch (num) { - case 0: - case 1: - case 2: - case 4: - case 5: - case 8: - case 10: - case 15: - case 20: - case 30: - case 40: - case 50: - case 60: - case 80: - case 100: - case 120: - case 140: - case 160: - case 180: - case 200: - case 220: - case 240: - case 260: - case 280: - case 300: - case 500: - case 750: - case 1000: - case 1250: - case 1500: - case 1750: - case 2000: - case 2250: - case 2500: - case 2750: - case 3000: - case -1: - t_reord = static_cast(num); - return true; - default: - return false; - } -} - -/// \brief Convert PDCP NR t-Reordering from enum to integer. -constexpr int16_t pdcp_t_reordering_to_int(pdcp_t_reordering t_reordering) -{ - return static_cast(t_reordering); -} - /// PDCP NR discard timer values. /// This timer is configured only for DRBs. In the transmitter, /// a new timer is started upon reception of an SDU from upper layer. diff --git a/include/srsran/pdcp/pdcp_t_reordering.h b/include/srsran/pdcp/pdcp_t_reordering.h new file mode 100644 index 0000000000..ea8ae2832e --- /dev/null +++ b/include/srsran/pdcp/pdcp_t_reordering.h @@ -0,0 +1,114 @@ +/* + * + * 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 + +namespace srsran { + +/// \brief PDCP NR t-Reordering timer values. +/// This timer is used to detect loss of PDCP Data PDUs. +/// See TS 38.322 for timer description and TS 38.331 for valid timer durations. +enum class pdcp_t_reordering { + ms0 = 0, + ms1 = 1, + ms2 = 2, + ms4 = 4, + ms5 = 5, + ms8 = 8, + ms10 = 10, + ms15 = 15, + ms20 = 20, + ms30 = 30, + ms40 = 40, + ms50 = 50, + ms60 = 60, + ms80 = 80, + ms100 = 100, + ms120 = 120, + ms140 = 140, + ms160 = 160, + ms180 = 180, + ms200 = 200, + ms220 = 220, + ms240 = 240, + ms260 = 260, + ms280 = 280, + ms300 = 300, + ms500 = 500, + ms750 = 750, + ms1000 = 1000, + ms1250 = 1250, + ms1500 = 1500, + ms1750 = 1750, + ms2000 = 2000, + ms2250 = 2250, + ms2500 = 2500, + ms2750 = 2750, + ms3000 = 3000, + infinity = -1 +}; + +/// Conversion of t-Reordering from integer to enum. +inline bool pdcp_t_reordering_from_int(pdcp_t_reordering& t_reord, int num) +{ + switch (num) { + case 0: + case 1: + case 2: + case 4: + case 5: + case 8: + case 10: + case 15: + case 20: + case 30: + case 40: + case 50: + case 60: + case 80: + case 100: + case 120: + case 140: + case 160: + case 180: + case 200: + case 220: + case 240: + case 260: + case 280: + case 300: + case 500: + case 750: + case 1000: + case 1250: + case 1500: + case 1750: + case 2000: + case 2250: + case 2500: + case 2750: + case 3000: + case -1: + t_reord = static_cast(num); + return true; + default: + return false; + } +} + +/// \brief Convert PDCP NR t-Reordering from enum to integer. +constexpr int16_t pdcp_t_reordering_to_int(pdcp_t_reordering t_reordering) +{ + return static_cast(t_reordering); +} + +} // namespace srsran \ No newline at end of file diff --git a/include/srsran/rrc/rrc_config.h b/include/srsran/rrc/rrc_config.h index 407dc6c110..fbf0eeea7e 100644 --- a/include/srsran/rrc/rrc_config.h +++ b/include/srsran/rrc/rrc_config.h @@ -27,13 +27,18 @@ struct rb_cfg_t { }; struct rrc_cfg_t { - asn1::rrc_nr::pdcp_cfg_s srb1_pdcp_cfg; ///< PDCP configuration for SRB1. - optional srb2_cfg; ///< Optional SRB2 config. SRB1 is configured by DU - std::map drb_config; ///< Configuration for available 5QI. - security::preferred_integrity_algorithms int_algo_pref_list; ///< Integrity protection algorithms preference list - security::preferred_ciphering_algorithms enc_algo_pref_list; ///< Encryption algorithms preference list - bool force_reestablishment_fallback = false; ///< Force re-establishment fallback. - unsigned rrc_procedure_timeout_ms = 360; ///< Timeout for RRC procedures. + /// Optional SRB2 config. SRB1 is configured by DU + optional srb2_cfg; + /// Configuration for available 5QI. + std::map drb_config; + /// Integrity protection algorithms preference list + security::preferred_integrity_algorithms int_algo_pref_list{security::integrity_algorithm::nia0}; + /// Encryption algorithms preference list + security::preferred_ciphering_algorithms enc_algo_pref_list{security::ciphering_algorithm::nea0}; + /// Force re-establishment fallback. + bool force_reestablishment_fallback = false; + /// Timeout for RRC procedures. + unsigned rrc_procedure_timeout_ms = 360; }; } // namespace srs_cu_cp diff --git a/include/srsran/rrc/rrc_ue.h b/include/srsran/rrc/rrc_ue.h index 8e9e0a078b..d3e21fd0d3 100644 --- a/include/srsran/rrc/rrc_ue.h +++ b/include/srsran/rrc/rrc_ue.h @@ -14,19 +14,27 @@ #include "rrc_types.h" #include "srsran/adt/byte_buffer.h" #include "srsran/adt/static_vector.h" -#include "srsran/asn1/rrc_nr/dl_dcch_msg.h" -#include "srsran/asn1/rrc_nr/msg_common.h" #include "srsran/asn1/rrc_nr/ue_cap.h" #include "srsran/cu_cp/cu_cp_types.h" #include "srsran/cu_cp/cu_cp_ue_messages.h" #include "srsran/cu_cp/up_resource_manager.h" +#include "srsran/pdcp/pdcp_t_reordering.h" #include "srsran/rrc/rrc.h" #include "srsran/security/security.h" #include "srsran/support/async/async_task.h" #include "srsran/support/timers.h" -namespace srsran { +namespace asn1 { +namespace rrc_nr { + +// ASN.1 forward declarations +struct dl_ccch_msg_s; +struct dl_dcch_msg_s; + +} // namespace rrc_nr +} // namespace asn1 +namespace srsran { namespace srs_cu_cp { /// Interface to notify F1AP about a new SRB PDU. @@ -56,12 +64,18 @@ class rrc_ue_setup_proc_notifier virtual void on_ue_release_required(const cause_t& cause) = 0; }; +/// PDCP configuration for a SRB. +struct srb_pdcp_config { + /// Value in ms of t-Reordering specified in TS 38.323. + pdcp_t_reordering t_reordering = pdcp_t_reordering::infinity; +}; + struct srb_creation_message { - ue_index_t ue_index = ue_index_t::invalid; - ue_index_t old_ue_index = ue_index_t::invalid; - srb_id_t srb_id = srb_id_t::nulltype; - bool enable_security = false; // Activate security upon SRB creation. - asn1::rrc_nr::pdcp_cfg_s pdcp_cfg; + ue_index_t ue_index = ue_index_t::invalid; + ue_index_t old_ue_index = ue_index_t::invalid; + srb_id_t srb_id = srb_id_t::nulltype; + bool enable_security = false; // Activate security upon SRB creation. + srb_pdcp_config pdcp_cfg; }; /// Interface to handle the creation of SRBs. 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 1a76ac88d2..6baaa8f157 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 @@ -282,7 +282,7 @@ void inter_cu_handover_target_routine::create_srb1() srb_creation_message srb1_msg{}; srb1_msg.ue_index = request.ue_index; srb1_msg.srb_id = srb_id_t::srb1; - srb1_msg.pdcp_cfg = asn1::rrc_nr::pdcp_cfg_s{}; + srb1_msg.pdcp_cfg = {}; srb1_msg.enable_security = true; ue_manager.find_du_ue(request.ue_index)->get_rrc_ue_srb_notifier().create_srb(srb1_msg); } diff --git a/lib/cu_cp/routines/mobility/inter_du_handover_routine.cpp b/lib/cu_cp/routines/mobility/inter_du_handover_routine.cpp index f697eee5b6..d2dd075f9c 100644 --- a/lib/cu_cp/routines/mobility/inter_du_handover_routine.cpp +++ b/lib/cu_cp/routines/mobility/inter_du_handover_routine.cpp @@ -268,6 +268,6 @@ void inter_du_handover_routine::create_srb(du_ue* ue, srb_id_t srb_id) srb_msg.ue_index = ue->get_ue_index(); srb_msg.srb_id = srb_id; srb_msg.enable_security = true; - srb_msg.pdcp_cfg = asn1::rrc_nr::pdcp_cfg_s{}; // TODO: add support for non-default config. + // TODO: add support for non-default PDCP config. ue->get_rrc_ue_srb_notifier().create_srb(srb_msg); } \ No newline at end of file diff --git a/lib/rrc/ue/procedures/rrc_reestablishment_procedure.cpp b/lib/rrc/ue/procedures/rrc_reestablishment_procedure.cpp index f3a56fd722..12d8794ecc 100644 --- a/lib/rrc/ue/procedures/rrc_reestablishment_procedure.cpp +++ b/lib/rrc/ue/procedures/rrc_reestablishment_procedure.cpp @@ -242,7 +242,7 @@ void rrc_reestablishment_procedure::create_srb1() srb1_msg.ue_index = context.ue_index; srb1_msg.old_ue_index = reestablishment_context.ue_index; srb1_msg.srb_id = srb_id_t::srb1; - srb1_msg.pdcp_cfg = srb1_pdcp_cfg; + srb1_msg.pdcp_cfg = {}; // TODO: Get SRB1 PDCP config of the old UE context. srb_notifier.create_srb(srb1_msg); // activate SRB1 PDCP security diff --git a/lib/rrc/ue/procedures/rrc_setup_procedure.cpp b/lib/rrc/ue/procedures/rrc_setup_procedure.cpp index 710fca73dd..c52e9b7ebd 100644 --- a/lib/rrc/ue/procedures/rrc_setup_procedure.cpp +++ b/lib/rrc/ue/procedures/rrc_setup_procedure.cpp @@ -69,7 +69,7 @@ void rrc_setup_procedure::create_srb1() srb_creation_message srb1_msg{}; srb1_msg.ue_index = context.ue_index; srb1_msg.srb_id = srb_id_t::srb1; - srb1_msg.pdcp_cfg = srb1_pdcp_cfg; + srb1_msg.pdcp_cfg = {}; srb_notifier.create_srb(srb1_msg); } diff --git a/lib/rrc/ue/procedures/rrc_setup_procedure.h b/lib/rrc/ue/procedures/rrc_setup_procedure.h index c6f8fe2985..9e8e5da077 100644 --- a/lib/rrc/ue/procedures/rrc_setup_procedure.h +++ b/lib/rrc/ue/procedures/rrc_setup_procedure.h @@ -83,7 +83,6 @@ class rrc_setup_procedure rrc_ue_context_t& context; const asn1::rrc_nr::establishment_cause_e cause; const byte_buffer& du_to_cu_container; - const asn1::rrc_nr::pdcp_cfg_s srb1_pdcp_cfg; rrc_ue_setup_proc_notifier& rrc_ue; // handler to the parent RRC UE object rrc_ue_srb_handler& srb_notifier; // for creation of SRBs diff --git a/lib/rrc/ue/rrc_ue_impl.cpp b/lib/rrc/ue/rrc_ue_impl.cpp index 638c08ede6..2b8ec7fefe 100644 --- a/lib/rrc/ue/rrc_ue_impl.cpp +++ b/lib/rrc/ue/rrc_ue_impl.cpp @@ -59,7 +59,7 @@ rrc_ue_impl::rrc_ue_impl(up_resource_manager& up_resource_mng_, srb_msg.ue_index = ue_index_; srb_msg.srb_id = srb; srb_msg.enable_security = true; - srb_msg.pdcp_cfg = asn1::rrc_nr::pdcp_cfg_s{}; // TODO: add support for non-default config. + srb_msg.pdcp_cfg = {}; // TODO: add support for non-default config. create_srb(srb_msg); } } diff --git a/tests/unittests/cu_cp/du_processor/du_processor_test.cpp b/tests/unittests/cu_cp/du_processor/du_processor_test.cpp index 8863020562..250f998c29 100644 --- a/tests/unittests/cu_cp/du_processor/du_processor_test.cpp +++ b/tests/unittests/cu_cp/du_processor/du_processor_test.cpp @@ -259,7 +259,7 @@ TEST_F(du_processor_test, when_valid_ue_creation_request_received_after_ue_was_r srb_creation_message srb1_msg{}; srb1_msg.ue_index = ue_index; srb1_msg.srb_id = srb_id_t::srb1; - srb1_msg.pdcp_cfg = asn1::rrc_nr::pdcp_cfg_s{}; + srb1_msg.pdcp_cfg = {}; ue_mng.find_du_ue(ue_index)->get_rrc_ue_srb_notifier().create_srb(srb1_msg); } From 0d80a074d647769fb1616887d312a305f190e107 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 9 Jan 2024 16:18:58 +0100 Subject: [PATCH 095/134] cu-cp: remove asn1 from du_processor_context --- include/srsran/cu_cp/du_processor_context.h | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/include/srsran/cu_cp/du_processor_context.h b/include/srsran/cu_cp/du_processor_context.h index a4e51480b6..56a612895f 100644 --- a/include/srsran/cu_cp/du_processor_context.h +++ b/include/srsran/cu_cp/du_processor_context.h @@ -11,7 +11,6 @@ #pragma once #include "srsran/adt/slotted_array.h" -#include "srsran/asn1/rrc_nr/rrc_nr.h" #include "srsran/cu_cp/cu_cp_types.h" #include "srsran/ran/band_helper.h" #include "srsran/ran/nr_cgi.h" @@ -22,16 +21,8 @@ namespace srs_cu_cp { /// Basic cell system information provided by DU struct du_sys_info { - asn1::rrc_nr::mib_s mib; - byte_buffer packed_mib; - - asn1::rrc_nr::sib1_s sib1; - byte_buffer packed_sib1; - - const asn1::rrc_nr::serving_cell_cfg_common_sib_s& serv_cell_cfg_common() const - { - return sib1.serving_cell_cfg_common; - } + byte_buffer packed_mib; + byte_buffer packed_sib1; }; struct du_cell_context { From 64fd39a5b20a5230c5af7831fbda79a7d9e25b1e Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 9 Jan 2024 16:40:27 +0100 Subject: [PATCH 096/134] rrc: remove rlc config from the ue rrc_cfg_t --- include/srsran/rrc/rrc_config.h | 11 +++-------- include/srsran/rrc/rrc_ue.h | 8 +------- include/srsran/rrc/rrc_ue_config.h | 15 +++++++++++---- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/include/srsran/rrc/rrc_config.h b/include/srsran/rrc/rrc_config.h index fbf0eeea7e..ded7eb8e8c 100644 --- a/include/srsran/rrc/rrc_config.h +++ b/include/srsran/rrc/rrc_config.h @@ -13,6 +13,7 @@ #include "rrc_ue_config.h" #include "srsran/adt/optional.h" #include "srsran/asn1/rrc_nr/rrc_nr.h" +#include "srsran/rrc/rrc_ue_config.h" #include #include @@ -20,15 +21,9 @@ namespace srsran { namespace srs_cu_cp { -/// RLC and PDCP configuration of a radio bearer. -struct rb_cfg_t { - asn1::rrc_nr::pdcp_cfg_s pdcp_cfg; - asn1::rrc_nr::rlc_cfg_c rlc_cfg; -}; - struct rrc_cfg_t { - /// Optional SRB2 config. SRB1 is configured by DU - optional srb2_cfg; + /// PDCP config to use when UE SRB2 are configured. + srb_pdcp_config srb2_cfg; /// Configuration for available 5QI. std::map drb_config; /// Integrity protection algorithms preference list diff --git a/include/srsran/rrc/rrc_ue.h b/include/srsran/rrc/rrc_ue.h index d3e21fd0d3..95b42f0289 100644 --- a/include/srsran/rrc/rrc_ue.h +++ b/include/srsran/rrc/rrc_ue.h @@ -18,8 +18,8 @@ #include "srsran/cu_cp/cu_cp_types.h" #include "srsran/cu_cp/cu_cp_ue_messages.h" #include "srsran/cu_cp/up_resource_manager.h" -#include "srsran/pdcp/pdcp_t_reordering.h" #include "srsran/rrc/rrc.h" +#include "srsran/rrc/rrc_ue_config.h" #include "srsran/security/security.h" #include "srsran/support/async/async_task.h" #include "srsran/support/timers.h" @@ -64,12 +64,6 @@ class rrc_ue_setup_proc_notifier virtual void on_ue_release_required(const cause_t& cause) = 0; }; -/// PDCP configuration for a SRB. -struct srb_pdcp_config { - /// Value in ms of t-Reordering specified in TS 38.323. - pdcp_t_reordering t_reordering = pdcp_t_reordering::infinity; -}; - struct srb_creation_message { ue_index_t ue_index = ue_index_t::invalid; ue_index_t old_ue_index = ue_index_t::invalid; diff --git a/include/srsran/rrc/rrc_ue_config.h b/include/srsran/rrc/rrc_ue_config.h index afcb65bb3b..0a8cef045c 100644 --- a/include/srsran/rrc/rrc_ue_config.h +++ b/include/srsran/rrc/rrc_ue_config.h @@ -11,15 +11,23 @@ #pragma once #include "rrc_types.h" -#include "srsran/asn1/rrc_nr/rrc_nr.h" #include "srsran/cu_cp/up_resource_manager.h" +#include "srsran/pdcp/pdcp_t_reordering.h" #include "srsran/srslog/srslog.h" namespace srsran { - namespace srs_cu_cp { + +/// PDCP configuration for a SRB. +struct srb_pdcp_config { + /// Value in ms of t-Reordering specified in TS 38.323. + pdcp_t_reordering t_reordering = pdcp_t_reordering::infinity; +}; + +/// RRC UE configuration. struct rrc_ue_cfg_t { - asn1::rrc_nr::pdcp_cfg_s srb1_pdcp_cfg; ///< PDCP configuration for SRB1. + /// PDCP configuration for SRB1. + srb_pdcp_config srb1_pdcp_cfg; std::vector meas_timings; bool force_reestablishment_fallback = false; unsigned rrc_procedure_timeout_ms; ///< Timeout used for RRC message exchange with UE. It needs to suit the expected @@ -30,5 +38,4 @@ struct rrc_ue_cfg_t { }; } // namespace srs_cu_cp - } // namespace srsran From 68b079a414622ebb37c0c6e619042ba3b9a8c3f7 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 9 Jan 2024 17:00:07 +0100 Subject: [PATCH 097/134] rrc: remove asn1 rrc include in the rrc_config.h --- include/srsran/rrc/rrc_config.h | 1 - include/srsran/rrc/rrc_du_factory.h | 1 - 2 files changed, 2 deletions(-) diff --git a/include/srsran/rrc/rrc_config.h b/include/srsran/rrc/rrc_config.h index ded7eb8e8c..ad407e9031 100644 --- a/include/srsran/rrc/rrc_config.h +++ b/include/srsran/rrc/rrc_config.h @@ -12,7 +12,6 @@ #include "rrc_ue_config.h" #include "srsran/adt/optional.h" -#include "srsran/asn1/rrc_nr/rrc_nr.h" #include "srsran/rrc/rrc_ue_config.h" #include #include diff --git a/include/srsran/rrc/rrc_du_factory.h b/include/srsran/rrc/rrc_du_factory.h index 1890fac0c1..5c1ef556ba 100644 --- a/include/srsran/rrc/rrc_du_factory.h +++ b/include/srsran/rrc/rrc_du_factory.h @@ -12,7 +12,6 @@ #include "rrc_config.h" #include "rrc_ue_config.h" -#include "srsran/asn1/rrc_nr/rrc_nr.h" #include "srsran/cu_cp/cell_meas_manager.h" #include "srsran/ngap/ngap.h" #include "srsran/rrc/rrc.h" From b2a20600b4e68f3796ffe338bf20c5b01d20a181 Mon Sep 17 00:00:00 2001 From: qarlosalberto Date: Thu, 11 Jan 2024 10:30:41 +0100 Subject: [PATCH 098/134] ci: warning as errors in Viavi test --- .gitlab/ci/e2e/.env | 2 +- tests/e2e/tests/viavi.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab/ci/e2e/.env b/.gitlab/ci/e2e/.env index 94bdd7fdcc..5e54a4ce24 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.38.0 +RETINA_VERSION=0.38.2 AMARISOFT_VERSION=2023-03-17 SRSUE_VERSION=23.11 OPEN5GS_VERSION=2.5.6 diff --git a/tests/e2e/tests/viavi.py b/tests/e2e/tests/viavi.py index a5de7bfa04..1943fc2b19 100644 --- a/tests/e2e/tests/viavi.py +++ b/tests/e2e/tests/viavi.py @@ -56,7 +56,7 @@ def test_viavi( gnb_startup_timeout: int = GNB_STARTUP_TIMEOUT, gnb_stop_timeout: int = 0, log_search: bool = True, - warning_as_errors: bool = False, + warning_as_errors: bool = True, ): """ Runs a test using Viavi From 73c7cd876a2c69803e8a5f711505f6801e25bc6b Mon Sep 17 00:00:00 2001 From: asaezper Date: Thu, 11 Jan 2024 11:41:20 +0100 Subject: [PATCH 099/134] format: add headers in missing files --- cmake/modules/FindZeroMQ.cmake | 7 +++++++ .../provisioning/dashboards/dashboardReference.yml | 8 ++++++++ docker/grafana/provisioning/datasources/InfluxDB.yml | 8 ++++++++ lib/phy/upper/channel_coding/short/CMakeLists.txt | 8 ++++++++ tests/unittests/cu_cp/CMakeLists.txt | 1 + tests/unittests/cu_up/CMakeLists.txt | 1 + .../unittests/phy/upper/channel_processors/CMakeLists.txt | 1 + 7 files changed, 34 insertions(+) diff --git a/cmake/modules/FindZeroMQ.cmake b/cmake/modules/FindZeroMQ.cmake index 681c53830a..2de48f22a9 100644 --- a/cmake/modules/FindZeroMQ.cmake +++ b/cmake/modules/FindZeroMQ.cmake @@ -1,3 +1,10 @@ +# +# 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. +# message(STATUS "FINDING ZEROMQ.") if(NOT ZEROMQ_FOUND) diff --git a/docker/grafana/provisioning/dashboards/dashboardReference.yml b/docker/grafana/provisioning/dashboards/dashboardReference.yml index 4ea970b97a..b3ba9a41be 100644 --- a/docker/grafana/provisioning/dashboards/dashboardReference.yml +++ b/docker/grafana/provisioning/dashboards/dashboardReference.yml @@ -1,3 +1,11 @@ +# +# Copyright 2013-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. +# + apiVersion: 1 providers: diff --git a/docker/grafana/provisioning/datasources/InfluxDB.yml b/docker/grafana/provisioning/datasources/InfluxDB.yml index c7eb96103a..0c361f60e0 100644 --- a/docker/grafana/provisioning/datasources/InfluxDB.yml +++ b/docker/grafana/provisioning/datasources/InfluxDB.yml @@ -1,3 +1,11 @@ +# +# Copyright 2013-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. +# + apiVersion: 1 datasources: diff --git a/lib/phy/upper/channel_coding/short/CMakeLists.txt b/lib/phy/upper/channel_coding/short/CMakeLists.txt index bc3d922645..185c544f7b 100644 --- a/lib/phy/upper/channel_coding/short/CMakeLists.txt +++ b/lib/phy/upper/channel_coding/short/CMakeLists.txt @@ -1,2 +1,10 @@ +# +# Copyright 2013-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. +# + add_library(srsran_short_block STATIC short_block_encoder_impl.cpp short_block_detector_impl.cpp) target_link_libraries(srsran_short_block srsran_support log_likelihood_ratio srsvec) \ No newline at end of file diff --git a/tests/unittests/cu_cp/CMakeLists.txt b/tests/unittests/cu_cp/CMakeLists.txt index a199c05bd2..f617aff374 100644 --- a/tests/unittests/cu_cp/CMakeLists.txt +++ b/tests/unittests/cu_cp/CMakeLists.txt @@ -5,6 +5,7 @@ # forth in the LICENSE file which can be found at the top level of # the distribution. # + set_directory_properties(PROPERTIES LABELS "cu_cp") include_directories(../../..) diff --git a/tests/unittests/cu_up/CMakeLists.txt b/tests/unittests/cu_up/CMakeLists.txt index 907b513862..8bef3d3716 100644 --- a/tests/unittests/cu_up/CMakeLists.txt +++ b/tests/unittests/cu_up/CMakeLists.txt @@ -5,6 +5,7 @@ # forth in the LICENSE file which can be found at the top level of # the distribution. # + set_directory_properties(PROPERTIES LABELS "cu_up") add_executable(cu_up_test cu_up_test.cpp) diff --git a/tests/unittests/phy/upper/channel_processors/CMakeLists.txt b/tests/unittests/phy/upper/channel_processors/CMakeLists.txt index fa21524589..3baabe4fca 100644 --- a/tests/unittests/phy/upper/channel_processors/CMakeLists.txt +++ b/tests/unittests/phy/upper/channel_processors/CMakeLists.txt @@ -5,6 +5,7 @@ # forth in the LICENSE file which can be found at the top level of # the distribution. # + add_subdirectory(pusch) add_subdirectory(uci) From 339066ebf4e2ef67b2ae676db71cfb57a5b41e46 Mon Sep 17 00:00:00 2001 From: asaezper Date: Thu, 11 Jan 2024 11:34:38 +0100 Subject: [PATCH 100/134] ci,release: check header format --- .gitlab/ci/release/auto_merge.sh | 52 +---------------- .gitlab/ci/release/update_headers.sh | 83 ++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 51 deletions(-) create mode 100755 .gitlab/ci/release/update_headers.sh diff --git a/.gitlab/ci/release/auto_merge.sh b/.gitlab/ci/release/auto_merge.sh index 28e03013a7..8826acfbf3 100755 --- a/.gitlab/ci/release/auto_merge.sh +++ b/.gitlab/ci/release/auto_merge.sh @@ -97,56 +97,6 @@ remove_lfs_files() { done < <(git lfs ls-files | sed -r 's/^.{13}//') } -update_headers() { - echo "==================" - echo "= Update headers =" - echo "==================" - - # for actual source and header files - find . -type f \( -name "*.cpp" -o -name "*.h" -o -name "*.h.in" \) ! -path "*/external/*" ! -name "rfnoc_test.cc" -exec perl -0777 -pi -e "s{/\*.*?\*/}{/* - * - * Copyright 2021-$(date +%Y) Software Radio Systems Limited - * - * This file is part of srsRAN. - * - * srsRAN is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * - * srsRAN is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * A copy of the GNU Affero General Public License can be found in - * the LICENSE file in the top-level directory of this distribution - * and at http://www.gnu.org/licenses/. - * - */}s" {} \; - - # for CMake/YML files - find . -type f -\( -name "CMakeLists.txt" -o -name "*.cmake" -o -name "*.yml" -o -name "*.sh" -o -name "Dockerfile" \) ! -path "*/configs/*" ! -path "*/.github/*" ! -path "*/.gitlab/*" ! -path "*/docker/open5gs/*" ! -name "FindBackward.cmake" ! -name "FindRapidJSON.cmake" ! -name "CheckCSourceRuns.cmake" ! -name "CheckFunctionExistsMath.cmake" -exec perl -0777 -pi -e "s/#[^!][\s\S]*?(?=\n.*?=|\n\n)/# -# Copyright 2021-$(date +%Y) Software Radio Systems Limited -# -# This file is part of srsRAN -# -# srsRAN is free software: you can redistribute it and\/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of -# the License, or (at your option) any later version. -# -# srsRAN is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# A copy of the GNU Affero General Public License can be found in -# the LICENSE file in the top-level directory of this distribution -# and at http:\/\/www.gnu.org\/licenses\/. -#/" {} \; -} - main() { # Check number of args if [ $# != 2 ] && [ $# != 3 ]; then @@ -181,7 +131,7 @@ main() { git commit --no-edit fi remove_lfs_files - update_headers + "$(dirname "$0")/update_headers.sh" git commit -a --amend --no-edit # Push diff --git a/.gitlab/ci/release/update_headers.sh b/.gitlab/ci/release/update_headers.sh new file mode 100755 index 0000000000..65b4305cba --- /dev/null +++ b/.gitlab/ci/release/update_headers.sh @@ -0,0 +1,83 @@ +#!/bin/bash +# +# 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. +# + +set -e + +echo "==================" +echo "= Update headers =" +echo "==================" + +# for CMake/YML files +find . -type f -\( -name "CMakeLists.txt" -o -name "*.cmake" -o -name "*.yml" -o -name "*.sh" -o -name "Dockerfile" \) \ + ! -path "*/configs/*" ! -path "*/.github/*" ! -path "*/.gitlab/*" ! -path "*/docker/open5gs/*" ! -name "FindBackward.cmake" \ + -print0 | while IFS= read -r -d '' file; do + + # Check header format + found_header=false + while IFS= read -r line; do + if [ -z "$line" ] && [ "$found_header" = false ]; then + continue # Ignore empty lines before first comment block + elif [[ "$line" =~ ^#.*$ ]]; then + found_header=true + continue # This line start with #. Keep reading + elif [[ -z "$line" ]]; then + break # Empty line after the header block. The format is valid and exit. + else + echo "$file: Header (or empty line after it) is missing." + exit 1 + fi + done <"$file" + + # Replace header + perl -0777 -pi -e "s/#[^!][\s\S]*?(?=\n.*?=|\n\n)/# +# Copyright 2021-$(date +%Y) Software Radio Systems Limited +# +# This file is part of srsRAN +# +# srsRAN is free software: you can redistribute it and\/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# srsRAN is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# A copy of the GNU Affero General Public License can be found in +# the LICENSE file in the top-level directory of this distribution +# and at http:\/\/www.gnu.org\/licenses\/. +#/" "$file" + +done + +# for actual source and header files +find . -type f \( -name "*.cpp" -o -name "*.h" -o -name "*.h.in" \) \ + ! -path "*/external/*" ! -name "rfnoc_test.cc" \ + -exec perl -0777 -pi -e "s{/\*.*?\*/}{/* + * + * Copyright 2021-$(date +%Y) Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */}s" {} \; From cd9cd3fdc688c9171c53c24410e16b0909a6a57f Mon Sep 17 00:00:00 2001 From: asaezper Date: Thu, 11 Jan 2024 11:35:07 +0100 Subject: [PATCH 101/134] ci: check header format on changed files --- .gitlab-ci.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d86813b017..06eaaa8e5b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -84,6 +84,21 @@ trigger docker: ################################################################################ ## Static ################################################################################ +headers: + image: ubuntu + stage: static + rules: + - if: $ON_MR + exists: + - "**/CMakeLists.txt" + - "**/Dockerfile" + - "**/*.cmake" + - "**/*.yml" + - "**/*.sh" + script: + - .gitlab/ci/release/update_headers.sh + needs: [] + include-guards: extends: .include-guards parallel: From 47738707112408c1f9a5d89c6083315cafe65085 Mon Sep 17 00:00:00 2001 From: asaezper Date: Thu, 11 Jan 2024 13:11:56 +0100 Subject: [PATCH 102/134] ci,e2e: b200 setup working again --- .gitlab/ci/e2e.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitlab/ci/e2e.yml b/.gitlab/ci/e2e.yml index 3229fa6efb..dcc9a2c774 100644 --- a/.gitlab/ci/e2e.yml +++ b/.gitlab/ci/e2e.yml @@ -301,13 +301,11 @@ rf-asan: - job: "basic asan" artifacts: true - *retina-needs - allow_failure: true rf-b200-config: extends: .rf variables: MARKERS: "rf_b200" - allow_failure: true rf-n300-config: extends: .rf From d7f7f3c04098fee1d9235281653df424cd956213 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 2 Jan 2024 19:03:34 +0100 Subject: [PATCH 103/134] trx: add AWGN trx: remove unused parameter and review README trx: fix noise generator --- utils/trx_srsran/README.md | 20 +++++++++++-- utils/trx_srsran/trx_srsran.cpp | 43 ++++++++++++++++++++++------ utils/trx_srsran/trx_srsran_test.cpp | 10 ++++++- 3 files changed, 61 insertions(+), 12 deletions(-) diff --git a/utils/trx_srsran/README.md b/utils/trx_srsran/README.md index dd4fa59b4b..e7e9f91bc0 100644 --- a/utils/trx_srsran/README.md +++ b/utils/trx_srsran/README.md @@ -25,10 +25,24 @@ ln -s /utils/trx_srsran/libtrx_srsran.so trx_srs And finally, the UE's RF configuration shall be: ``` rf_driver: { - name: "srsran", - args: "", + // Select srsran TRX driver. + name: "srsran", + + // TCP transmit and receive ports. tx_port0: "tcp://*:6000", rx_port0: "tcp://localhost:5000", - log_level: "info" + tx_port1: "tcp://*:6001", + rx_port1: "tcp://localhost:5001", + tx_port2: "tcp://*:6002", + rx_port2: "tcp://localhost:5002", + tx_port3: "tcp://*:6003", + rx_port3: "tcp://localhost:5003", + + // srsran logging level. + log_level: "info", + + // Enables a noise generator in the uplink path. Determines the noise power spectral density in dBm/Hz for each gNb + // receive channel. + noise_spd: -174, }, ``` \ No newline at end of file diff --git a/utils/trx_srsran/trx_srsran.cpp b/utils/trx_srsran/trx_srsran.cpp index 2db98b8787..8bddec38a7 100644 --- a/utils/trx_srsran/trx_srsran.cpp +++ b/utils/trx_srsran/trx_srsran.cpp @@ -12,8 +12,13 @@ #include "srsran/gateways/baseband/baseband_gateway_transmitter.h" #include "srsran/gateways/baseband/buffer/baseband_gateway_buffer_dynamic.h" #include "srsran/radio/radio_factory.h" +#include "srsran/support/complex_normal_random.h" #include "srsran/support/executors/task_worker.h" +#include "srsran/support/math_utils.h" #include "srsran/support/srsran_assert.h" +#include +#include +#include #include extern "C" { @@ -132,7 +137,6 @@ struct trx_srsran_session_context { std::array tx_port_args; std::array rx_port_args; std::string factory_str; - std::string radio_args; std::string log_level; // Radio factory. std::unique_ptr factory; @@ -148,6 +152,12 @@ struct trx_srsran_session_context { std::array tx_port_channel_gain; std::array rx_port_channel_gain; unsigned tx_samples_per_packet; + // Transmit noise spectral density in dB/Hz if present. Otherwise, noise generator is disabled. + optional noise_spd = nullopt; + // Random generator. + std::mt19937 rgen; + // Random distribution for AWGN. + complex_normal_distribution<> dist; }; // Keeps persistent trx_srsran sessions. @@ -237,6 +247,17 @@ static void trx_srsran_write2(TRXState* s1, // Prepare buffer. baseband_gateway_buffer_trx buffer(psamples, count, context.tx_port_channel_count[tx_port_index]); + // Add noise if enabled. + if (context.noise_spd.has_value()) { + for (unsigned i_chan = 0, nof_channels = context.tx_port_channel_count[tx_port_index]; i_chan != nof_channels; + ++i_chan) { + span chan_buffer = buffer.get_channel_buffer(i_chan); + std::transform(chan_buffer.begin(), chan_buffer.end(), chan_buffer.begin(), [&context](cf_t sample) { + return sample + context.dist(context.rgen); + }); + } + } + // Transmit baseband. transmitter.transmit(buffer, metadata); } @@ -352,6 +373,13 @@ static int trx_srsran_start(TRXState* s1, const TRXDriverParams* p) p->sample_rate[0].den); double sample_rate_Hz = static_cast(p->sample_rate->num) / static_cast(p->sample_rate[0].den); + // Prepare noise generator. + if (context.noise_spd.has_value()) { + // Convert to standard deviation and initialize noise generator. + float noise_std = std::sqrt(convert_dB_to_power(context.noise_spd.value()) * sample_rate_Hz); + context.dist = complex_normal_distribution<>(0.0, noise_std); + } + // Check that all sampling rates for all channels are the same. span sampling_rates_frac = span(p->sample_rate, context.rf_port_count).last(context.rf_port_count - 1); @@ -542,13 +570,6 @@ int trx_driver_init(TRXState* s1) srsran_terminate("Invalid OTW format {}. Supported formats are: default, sc16.", otw_format_str); } - // Parse radio arguments. - char* radio_args_char = trx_get_param_string(s1, "args"); - if (radio_args_char != nullptr) { - context.radio_args = std::string(radio_args_char); - free(radio_args_char); - } - // Parse transmit ports arguments. for (unsigned port = 0; port < RADIO_MAX_NOF_PORTS; ++port) { // Create port field name. @@ -590,6 +611,12 @@ int trx_driver_init(TRXState* s1) context.log_level = "info"; } + // Parse noise spectral density. + double noise_spd_double; + if (trx_get_param_double(s1, &noise_spd_double, "noise_spd") == 0) { + context.noise_spd.emplace(static_cast(noise_spd_double)); + } + s1->opaque = &context; s1->trx_end_func = trx_srsran_end; s1->trx_start_func = trx_srsran_start; diff --git a/utils/trx_srsran/trx_srsran_test.cpp b/utils/trx_srsran/trx_srsran_test.cpp index 25dc2cc989..91aded66e8 100644 --- a/utils/trx_srsran/trx_srsran_test.cpp +++ b/utils/trx_srsran/trx_srsran_test.cpp @@ -35,6 +35,13 @@ static char* trx_get_param_string(void* app_opaque, const char* return nullptr; } +static int trx_get_param_double(void* app_opaque, double* param, const char* prop_name) +{ + TESTASSERT(&trx_app_opaque == app_opaque); + trx_param_names.insert(prop_name); + return -1; +} + int main(int argc, char** argv) { void* handle; @@ -70,16 +77,17 @@ int main(int argc, char** argv) state.trx_api_version = TRX_API_VERSION; state.app_opaque = static_cast(&trx_app_opaque); state.trx_get_param_string = &trx_get_param_string; + state.trx_get_param_double = &trx_get_param_double; driver_init(&state); std::cout << "Driver initialised successfully." << std::endl; // Make sure parameters are parsed. - TESTASSERT(trx_param_names.count("args")); TESTASSERT(trx_param_names.count("factory")); TESTASSERT(trx_param_names.count("log_level")); TESTASSERT(trx_param_names.count("otw_format")); TESTASSERT(trx_param_names.count("rx_port0")); TESTASSERT(trx_param_names.count("tx_port0")); + TESTASSERT(trx_param_names.count("noise_spd")); std::cout << "Driver parsed parameters." << std::endl; // Make sure the init function set the methods. From e6f960a33b5353e4d5ff876a3da758912bb79c54 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 3 Jan 2024 13:47:00 +0000 Subject: [PATCH 104/134] cu-up,pdcp: start deriving custom PDCP parameters from 5QI --- apps/gnb/gnb.cpp | 2 +- lib/cu_up/cu_up_impl.cpp | 1 + lib/cu_up/pdu_session_manager_impl.cpp | 110 ++++++++++++------ lib/cu_up/pdu_session_manager_impl.h | 26 +++-- lib/cu_up/ue_context.h | 8 +- .../cu_up/pdu_session_manager_test.cpp | 4 +- .../cu_up/pdu_session_manager_test.h | 8 +- 7 files changed, 102 insertions(+), 57 deletions(-) diff --git a/apps/gnb/gnb.cpp b/apps/gnb/gnb.cpp index 3d768674c2..a2ad69709f 100644 --- a/apps/gnb/gnb.cpp +++ b/apps/gnb/gnb.cpp @@ -465,7 +465,7 @@ int main(int argc, char** argv) cu_up_cfg.cu_up_e2_exec = workers.cu_up_e2_exec; cu_up_cfg.dl_executor = workers.cu_up_dl_exec; cu_up_cfg.ul_executor = workers.cu_up_ul_exec; - cu_up_cfg.io_ul_executor = workers.cu_up_ul_exec; // Optinally select separate exec for UL IO + 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(); diff --git a/lib/cu_up/cu_up_impl.cpp b/lib/cu_up/cu_up_impl.cpp index 3f92585858..ab06e308af 100644 --- a/lib/cu_up/cu_up_impl.cpp +++ b/lib/cu_up/cu_up_impl.cpp @@ -304,6 +304,7 @@ cu_up::handle_bearer_context_setup_request(const e1ap_bearer_context_setup_reque fill_sec_as_config(ue_cfg.security_info, msg.security_info); ue_cfg.activity_level = msg.activity_notif_level; ue_cfg.ue_inactivity_timeout = msg.ue_inactivity_timer; + ue_cfg.qos = cfg.qos; ue_context* ue_ctxt = ue_mng->add_ue(ue_cfg); if (ue_ctxt == nullptr) { logger.error("Could not create UE context"); diff --git a/lib/cu_up/pdu_session_manager_impl.cpp b/lib/cu_up/pdu_session_manager_impl.cpp index 30fb78c71b..24597103d9 100644 --- a/lib/cu_up/pdu_session_manager_impl.cpp +++ b/lib/cu_up/pdu_session_manager_impl.cpp @@ -10,6 +10,8 @@ #include "pdu_session_manager_impl.h" +#include + #include "srsran/e1ap/common/e1ap_types.h" #include "srsran/e1ap/cu_up/e1ap_config_converters.h" #include "srsran/gtpu/gtpu_tunnel_ngu_factory.h" @@ -19,11 +21,12 @@ using namespace srsran; using namespace srs_cu_up; -pdu_session_manager_impl::pdu_session_manager_impl(ue_index_t ue_index_, - const security::sec_as_config& security_info_, - network_interface_config& net_config_, - n3_interface_config& n3_config_, - cu_up_ue_logger& logger_, +pdu_session_manager_impl::pdu_session_manager_impl(ue_index_t ue_index_, + std::map qos_cfg_, + const security::sec_as_config& security_info_, + network_interface_config& net_config_, + n3_interface_config& n3_config_, + cu_up_ue_logger& logger_, unique_timer& ue_inactivity_timer_, timer_factory timers_, f1u_cu_up_gateway& f1u_gw_, @@ -32,6 +35,7 @@ pdu_session_manager_impl::pdu_session_manager_impl(ue_index_t gtpu_demux_ctrl& gtpu_rx_demux_, dlt_pcap& gtpu_pcap_) : ue_index(ue_index_), + qos_cfg(std::move(qos_cfg_)), security_info(security_info_), net_config(net_config_), n3_config(n3_config_), @@ -59,11 +63,71 @@ drb_setup_result pdu_session_manager_impl::handle_drb_to_setup_item(pdu_session& new_session.drbs.emplace(drb_to_setup.drb_id, std::make_unique(drb_to_setup.drb_id)); auto& new_drb = new_session.drbs.at(drb_to_setup.drb_id); + // Create QoS flows + if (drb_to_setup.qos_flow_info_to_be_setup.empty()) { + return drb_result; + } + five_qi_t five_qi = + drb_to_setup.qos_flow_info_to_be_setup.begin()->qos_flow_level_qos_params.qos_characteristics.get_five_qi(); + uint32_t nof_flow_success = 0; + for (const auto& qos_flow_info : drb_to_setup.qos_flow_info_to_be_setup) { + // prepare QoS flow creation result + qos_flow_setup_result flow_result = {}; + flow_result.success = false; + flow_result.cause = cause_radio_network_t::unspecified; + flow_result.qos_flow_id = qos_flow_info.qos_flow_id; + + if (!new_session.sdap->is_mapped(qos_flow_info.qos_flow_id) && + qos_flow_info.qos_flow_level_qos_params.qos_characteristics.get_five_qi() == five_qi) { + // create QoS flow context + const auto& qos_flow = qos_flow_info; + new_drb->qos_flows[qos_flow.qos_flow_id] = std::make_unique(qos_flow); + auto& new_qos_flow = new_drb->qos_flows[qos_flow.qos_flow_id]; + logger.log_debug("Created QoS flow with {} and {}", new_qos_flow->qos_flow_id, new_qos_flow->five_qi); + sdap_config sdap_cfg = make_sdap_drb_config(drb_to_setup.sdap_cfg); + new_session.sdap->add_mapping( + qos_flow.qos_flow_id, drb_to_setup.drb_id, sdap_cfg, new_qos_flow->sdap_to_pdcp_adapter); + flow_result.success = true; + nof_flow_success++; + } else { + // fail if mapping already exists + flow_result.success = false; + flow_result.cause = cause_radio_network_t::multiple_qos_flow_id_instances; + logger.log_error("Cannot overwrite existing mapping for {}", qos_flow_info.qos_flow_id); + } + + // Add QoS flow creation result + drb_result.qos_flow_results.push_back(flow_result); + } + + // If no flow could be created, we remove the rest of the dangling DRB again + if (nof_flow_success == 0) { + logger.log_error( + "Failed to create {} for psi={}: Could not map any QoS flow", drb_to_setup.drb_id, new_session.pdu_session_id); + new_session.drbs.erase(drb_to_setup.drb_id); + drb_result.cause = cause_radio_network_t::multiple_qos_flow_id_instances; + drb_result.success = false; + return drb_result; + } + + // If 5QI is not configured in CU-UP, we remove the rest of the dangling DRB again + if (qos_cfg.find(five_qi) == qos_cfg.end()) { + logger.log_error("Failed to create {} for psi={}: Could not find 5QI. {}", + drb_to_setup.drb_id, + new_session.pdu_session_id, + five_qi); + new_session.drbs.erase(drb_to_setup.drb_id); + drb_result.cause = cause_radio_network_t::not_supported_5qi_value; + drb_result.success = false; + return drb_result; + } + // Create PDCP entity srsran::pdcp_entity_creation_message pdcp_msg = {}; pdcp_msg.ue_index = ue_index; pdcp_msg.rb_id = drb_to_setup.drb_id; pdcp_msg.config = make_pdcp_drb_config(drb_to_setup.pdcp_cfg, new_session.security_ind); + pdcp_msg.config.custom = qos_cfg.at(five_qi).pdcp_custom; pdcp_msg.tx_lower = &new_drb->pdcp_to_f1u_adapter; pdcp_msg.tx_upper_cn = &new_drb->pdcp_tx_to_e1ap_adapter; pdcp_msg.rx_upper_dn = &new_drb->pdcp_to_sdap_adapter; @@ -124,38 +188,10 @@ drb_setup_result pdu_session_manager_impl::handle_drb_to_setup_item(pdu_session& new_drb->pdcp->get_tx_lower_interface()); new_drb->pdcp_to_f1u_adapter.connect_f1u(new_drb->f1u->get_tx_sdu_handler()); - // Create QoS flows - uint32_t nof_flow_success = 0; - for (const auto& qos_flow_info : drb_to_setup.qos_flow_info_to_be_setup) { - // prepare QoS flow creation result - qos_flow_setup_result flow_result = {}; - flow_result.success = false; - flow_result.cause = cause_radio_network_t::unspecified; - flow_result.qos_flow_id = qos_flow_info.qos_flow_id; - - if (!new_session.sdap->is_mapped(qos_flow_info.qos_flow_id)) { - // create QoS flow context - const auto& qos_flow = qos_flow_info; - new_drb->qos_flows[qos_flow.qos_flow_id] = std::make_unique(qos_flow); - auto& new_qos_flow = new_drb->qos_flows[qos_flow.qos_flow_id]; - logger.log_debug("Created QoS flow with {} and {}", new_qos_flow->qos_flow_id, new_qos_flow->five_qi); - - sdap_config sdap_cfg = make_sdap_drb_config(drb_to_setup.sdap_cfg); - new_session.sdap->add_mapping( - qos_flow.qos_flow_id, drb_to_setup.drb_id, sdap_cfg, new_qos_flow->sdap_to_pdcp_adapter); - new_qos_flow->sdap_to_pdcp_adapter.connect_pdcp(new_drb->pdcp->get_tx_upper_data_interface()); - new_drb->pdcp_to_sdap_adapter.connect_sdap(new_session.sdap->get_sdap_rx_pdu_handler(drb_to_setup.drb_id)); - flow_result.success = true; - nof_flow_success++; - } else { - // fail if mapping already exists - flow_result.success = false; - flow_result.cause = cause_radio_network_t::multiple_qos_flow_id_instances; - logger.log_error("Cannot overwrite existing mapping for {}", qos_flow_info.qos_flow_id); - } - - // Add QoS flow creation result - drb_result.qos_flow_results.push_back(flow_result); + // Connect QoS flows to DRB + for (auto& new_qos_flow : new_drb->qos_flows) { + new_qos_flow.second->sdap_to_pdcp_adapter.connect_pdcp(new_drb->pdcp->get_tx_upper_data_interface()); + new_drb->pdcp_to_sdap_adapter.connect_sdap(new_session.sdap->get_sdap_rx_pdu_handler(drb_to_setup.drb_id)); } // If no flow could be created, we remove the rest of the dangling DRB again diff --git a/lib/cu_up/pdu_session_manager_impl.h b/lib/cu_up/pdu_session_manager_impl.h index 4565d9723b..eebbef37ce 100644 --- a/lib/cu_up/pdu_session_manager_impl.h +++ b/lib/cu_up/pdu_session_manager_impl.h @@ -30,18 +30,19 @@ namespace srs_cu_up { class pdu_session_manager_impl final : public pdu_session_manager_ctrl { public: - pdu_session_manager_impl(ue_index_t ue_index_, - const security::sec_as_config& security_info_, - network_interface_config& net_config_, - n3_interface_config& n3_config_, - cu_up_ue_logger& logger_, - unique_timer& ue_inactivity_timer, - timer_factory timers_, - 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_); + pdu_session_manager_impl(ue_index_t ue_index_, + std::map qos_cfg_, + const security::sec_as_config& security_info_, + network_interface_config& net_config_, + n3_interface_config& n3_config_, + cu_up_ue_logger& logger_, + unique_timer& ue_inactivity_timer, + timer_factory timers_, + 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_); pdu_session_setup_result setup_pdu_session(const e1ap_pdu_session_res_to_setup_item& session) override; pdu_session_modification_result modify_pdu_session(const e1ap_pdu_session_res_to_modify_item& session, @@ -62,6 +63,7 @@ class pdu_session_manager_impl final : public pdu_session_manager_ctrl const e1ap_drb_to_setup_item_ng_ran& drb_to_setup); ue_index_t ue_index; + const std::map qos_cfg; const security::sec_as_config& security_info; network_interface_config& net_config; n3_interface_config& n3_config; diff --git a/lib/cu_up/ue_context.h b/lib/cu_up/ue_context.h index 04935d9d16..975823761e 100644 --- a/lib/cu_up/ue_context.h +++ b/lib/cu_up/ue_context.h @@ -24,9 +24,10 @@ namespace srs_cu_up { /// \brief UE context setup configuration struct ue_context_cfg { - security::sec_as_config security_info; - activity_notification_level_t activity_level; - optional ue_inactivity_timeout; + security::sec_as_config security_info; + activity_notification_level_t activity_level; + optional ue_inactivity_timeout; + std::map qos; }; /// \brief Context for a UE within the CU-UP with storage for all active PDU sessions. @@ -49,6 +50,7 @@ class ue_context : public pdu_session_manager_ctrl logger("CU-UP", {index_}), e1ap(e1ap_), pdu_session_manager(index, + cfg.qos, cfg.security_info, net_config_, n3_config_, diff --git a/tests/unittests/cu_up/pdu_session_manager_test.cpp b/tests/unittests/cu_up/pdu_session_manager_test.cpp index 0cec802ff7..bfbf1a630b 100644 --- a/tests/unittests/cu_up/pdu_session_manager_test.cpp +++ b/tests/unittests/cu_up/pdu_session_manager_test.cpp @@ -208,8 +208,8 @@ TEST_F(pdu_session_manager_test, drb_create_with_one_qfi_which_is_already_mapped EXPECT_EQ(pdu_session_mng->get_nof_pdu_sessions(), 1); EXPECT_TRUE(gtpu_rx_demux->removed_teid_list.empty()); - // validate the dangling bearer was removed from F1-U gateway - EXPECT_EQ(f1u_gw->removed_ul_teid_list.size(), 1); + // validate the dangling bearer was not created and removed from F1-U gateway + EXPECT_EQ(f1u_gw->removed_ul_teid_list.size(), 0); } /// Create a DRB with two QFIs, of which one QFI is already mapped diff --git a/tests/unittests/cu_up/pdu_session_manager_test.h b/tests/unittests/cu_up/pdu_session_manager_test.h index f5a4d16aee..3d407ed9a7 100644 --- a/tests/unittests/cu_up/pdu_session_manager_test.h +++ b/tests/unittests/cu_up/pdu_session_manager_test.h @@ -37,7 +37,11 @@ class pdu_session_manager_test : public ::testing::Test // create DUT object ue_inactivity_timer = timers_factory.create_timer(); ue_inactivity_timer.set(std::chrono::milliseconds(10000), [](timer_id_t) {}); + std::map qos; + qos[uint_to_five_qi(9)] = {}; + pdu_session_mng = std::make_unique(MIN_UE_INDEX, + qos, security_info, net_config, n3_config, @@ -109,7 +113,7 @@ generate_pdu_session_res_to_setup_item(pdu_session_id_t psi, drb_id_t drb_id, qo e1ap_qos_flow_qos_param_item qos_flow_info; qos_flow_info.qos_flow_id = qfi; non_dyn_5qi_descriptor_t non_dyn_5qi; - non_dyn_5qi.five_qi = uint_to_five_qi(8); + non_dyn_5qi.five_qi = uint_to_five_qi(9); qos_flow_info.qos_flow_level_qos_params.qos_characteristics.non_dyn_5qi = non_dyn_5qi; qos_flow_info.qos_flow_level_qos_params.ng_ran_alloc_retention_prio.prio_level = 1; qos_flow_info.qos_flow_level_qos_params.ng_ran_alloc_retention_prio.pre_emption_cap = "shall-not-trigger-pre-emption"; @@ -174,7 +178,7 @@ generate_pdu_session_res_to_modify_item_to_setup_drb(pdu_session_id_t e1ap_qos_flow_qos_param_item qos_flow_info; qos_flow_info.qos_flow_id = qfi; non_dyn_5qi_descriptor_t non_dyn_5qi; - non_dyn_5qi.five_qi = uint_to_five_qi(8); + non_dyn_5qi.five_qi = uint_to_five_qi(9); qos_flow_info.qos_flow_level_qos_params.qos_characteristics.non_dyn_5qi = non_dyn_5qi; qos_flow_info.qos_flow_level_qos_params.ng_ran_alloc_retention_prio.prio_level = 1; qos_flow_info.qos_flow_level_qos_params.ng_ran_alloc_retention_prio.pre_emption_cap = From 039b9198a7c3a8ec1d1965ccb7efc5cbf7940d60 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 9 Jan 2024 13:29:32 +0000 Subject: [PATCH 105/134] cu-up: adding unit test for missing 5QI --- lib/cu_up/pdu_session_manager_impl.cpp | 21 ++++---- tests/unittests/cu_up/cu_up_test.cpp | 1 + .../cu_up/pdu_session_manager_test.cpp | 53 +++++++++++++++---- .../cu_up/pdu_session_manager_test.h | 9 ++-- 4 files changed, 58 insertions(+), 26 deletions(-) diff --git a/lib/cu_up/pdu_session_manager_impl.cpp b/lib/cu_up/pdu_session_manager_impl.cpp index 24597103d9..6a7b30d3ce 100644 --- a/lib/cu_up/pdu_session_manager_impl.cpp +++ b/lib/cu_up/pdu_session_manager_impl.cpp @@ -69,6 +69,11 @@ drb_setup_result pdu_session_manager_impl::handle_drb_to_setup_item(pdu_session& } five_qi_t five_qi = drb_to_setup.qos_flow_info_to_be_setup.begin()->qos_flow_level_qos_params.qos_characteristics.get_five_qi(); + if (qos_cfg.find(five_qi) == qos_cfg.end()) { + drb_result.cause = cause_radio_network_t::not_supported_5qi_value; + return drb_result; + } + uint32_t nof_flow_success = 0; for (const auto& qos_flow_info : drb_to_setup.qos_flow_info_to_be_setup) { // prepare QoS flow creation result @@ -92,7 +97,9 @@ drb_setup_result pdu_session_manager_impl::handle_drb_to_setup_item(pdu_session& } else { // fail if mapping already exists flow_result.success = false; - flow_result.cause = cause_radio_network_t::multiple_qos_flow_id_instances; + flow_result.cause = new_session.sdap->is_mapped(qos_flow_info.qos_flow_id) + ? cause_radio_network_t::multiple_qos_flow_id_instances + : cause_radio_network_t::not_supported_5qi_value; logger.log_error("Cannot overwrite existing mapping for {}", qos_flow_info.qos_flow_id); } @@ -105,7 +112,7 @@ drb_setup_result pdu_session_manager_impl::handle_drb_to_setup_item(pdu_session& logger.log_error( "Failed to create {} for psi={}: Could not map any QoS flow", drb_to_setup.drb_id, new_session.pdu_session_id); new_session.drbs.erase(drb_to_setup.drb_id); - drb_result.cause = cause_radio_network_t::multiple_qos_flow_id_instances; + drb_result.cause = cause_radio_network_t::unspecified; drb_result.success = false; return drb_result; } @@ -194,16 +201,6 @@ drb_setup_result pdu_session_manager_impl::handle_drb_to_setup_item(pdu_session& new_drb->pdcp_to_sdap_adapter.connect_sdap(new_session.sdap->get_sdap_rx_pdu_handler(drb_to_setup.drb_id)); } - // If no flow could be created, we remove the rest of the dangling DRB again - if (nof_flow_success == 0) { - logger.log_error( - "Failed to create {} for psi={}: Could not map any QoS flow", drb_to_setup.drb_id, new_session.pdu_session_id); - new_session.drbs.erase(drb_to_setup.drb_id); - drb_result.cause = cause_radio_network_t::multiple_qos_flow_id_instances; - drb_result.success = false; - return drb_result; - } - // Add result drb_result.success = true; diff --git a/tests/unittests/cu_up/cu_up_test.cpp b/tests/unittests/cu_up/cu_up_test.cpp index 4932727526..fb529caaa8 100644 --- a/tests/unittests/cu_up/cu_up_test.cpp +++ b/tests/unittests/cu_up/cu_up_test.cpp @@ -113,6 +113,7 @@ class cu_up_test : public ::testing::Test cfg.f1u_gateway = f1u_gw.get(); cfg.epoll_broker = broker.get(); cfg.timers = app_timers.get(); + cfg.qos[uint_to_five_qi(9)] = {}; cfg.gtpu_pcap = &dummy_pcap; cfg.net_cfg.n3_bind_port = 0; // Random free port selected by the OS. cfg.n3_cfg.gtpu_reordering_timer = std::chrono::milliseconds(0); diff --git a/tests/unittests/cu_up/pdu_session_manager_test.cpp b/tests/unittests/cu_up/pdu_session_manager_test.cpp index bfbf1a630b..15853ef4db 100644 --- a/tests/unittests/cu_up/pdu_session_manager_test.cpp +++ b/tests/unittests/cu_up/pdu_session_manager_test.cpp @@ -26,7 +26,8 @@ TEST_F(pdu_session_manager_test, when_valid_pdu_session_setup_item_session_can_b drb_id_t drb_id = uint_to_drb_id(1); qos_flow_id_t qfi = uint_to_qos_flow_id(8); - e1ap_pdu_session_res_to_setup_item pdu_session_setup_item = generate_pdu_session_res_to_setup_item(psi, drb_id, qfi); + e1ap_pdu_session_res_to_setup_item pdu_session_setup_item = + generate_pdu_session_res_to_setup_item(psi, drb_id, qfi, uint_to_five_qi(9)); // attempt to add session pdu_session_setup_result setup_result = pdu_session_mng->setup_pdu_session(pdu_session_setup_item); @@ -60,7 +61,8 @@ TEST_F(pdu_session_manager_test, when_pdu_session_with_same_id_is_setup_session_ drb_id_t drb_id = uint_to_drb_id(1); qos_flow_id_t qfi = uint_to_qos_flow_id(8); - e1ap_pdu_session_res_to_setup_item pdu_session_setup_item = generate_pdu_session_res_to_setup_item(psi, drb_id, qfi); + e1ap_pdu_session_res_to_setup_item pdu_session_setup_item = + generate_pdu_session_res_to_setup_item(psi, drb_id, qfi, uint_to_five_qi(9)); // attempt to add session pdu_session_setup_result setup_result = pdu_session_mng->setup_pdu_session(pdu_session_setup_item); @@ -104,7 +106,8 @@ TEST_F(pdu_session_manager_test, drb_create_modify_remove) drb_id_t drb_id = uint_to_drb_id(1); qos_flow_id_t qfi = uint_to_qos_flow_id(8); - e1ap_pdu_session_res_to_setup_item pdu_session_setup_item = generate_pdu_session_res_to_setup_item(psi, drb_id, qfi); + e1ap_pdu_session_res_to_setup_item pdu_session_setup_item = + generate_pdu_session_res_to_setup_item(psi, drb_id, qfi, uint_to_five_qi(9)); // attempt to add session pdu_session_setup_result setup_result = pdu_session_mng->setup_pdu_session(pdu_session_setup_item); @@ -165,7 +168,8 @@ TEST_F(pdu_session_manager_test, drb_create_with_one_qfi_which_is_already_mapped drb_id_t drb_id2 = uint_to_drb_id(2); qos_flow_id_t qfi = uint_to_qos_flow_id(8); - e1ap_pdu_session_res_to_setup_item pdu_session_setup_item = generate_pdu_session_res_to_setup_item(psi, drb_id1, qfi); + e1ap_pdu_session_res_to_setup_item pdu_session_setup_item = + generate_pdu_session_res_to_setup_item(psi, drb_id1, qfi, uint_to_five_qi(9)); // attempt to add session pdu_session_setup_result setup_result = pdu_session_mng->setup_pdu_session(pdu_session_setup_item); @@ -189,7 +193,7 @@ TEST_F(pdu_session_manager_test, drb_create_with_one_qfi_which_is_already_mapped // prepare modification request adding a new DRB and map it to a QFI that is already mapped e1ap_pdu_session_res_to_modify_item pdu_session_modify_item = - generate_pdu_session_res_to_modify_item_to_setup_drb(psi, drb_id2, {qfi}); + generate_pdu_session_res_to_modify_item_to_setup_drb(psi, drb_id2, {qfi}, uint_to_five_qi(9)); // attempt to perform the modification pdu_session_modification_result mod_result = pdu_session_mng->modify_pdu_session(pdu_session_modify_item, false); @@ -198,7 +202,7 @@ TEST_F(pdu_session_manager_test, drb_create_with_one_qfi_which_is_already_mapped EXPECT_TRUE(mod_result.success); ASSERT_EQ(mod_result.drb_setup_results.size(), 1); EXPECT_FALSE(mod_result.drb_setup_results[0].success); - EXPECT_EQ(mod_result.drb_setup_results[0].cause, cause_t{cause_radio_network_t::multiple_qos_flow_id_instances}); + EXPECT_EQ(mod_result.drb_setup_results[0].cause, cause_t{cause_radio_network_t::unspecified}); ASSERT_EQ(mod_result.drb_setup_results[0].qos_flow_results.size(), 1); EXPECT_FALSE(mod_result.drb_setup_results[0].qos_flow_results[0].success); EXPECT_EQ(mod_result.drb_setup_results[0].qos_flow_results[0].cause, @@ -212,6 +216,33 @@ TEST_F(pdu_session_manager_test, drb_create_with_one_qfi_which_is_already_mapped EXPECT_EQ(f1u_gw->removed_ul_teid_list.size(), 0); } +/// Create a DRB with only one QFI, but the QFI is already mapped +TEST_F(pdu_session_manager_test, drb_create_with_unknown_five_qi) +{ + // no sessions added yet + ASSERT_EQ(pdu_session_mng->get_nof_pdu_sessions(), 0); + + // prepare request + pdu_session_id_t psi = uint_to_pdu_session_id(1); + drb_id_t drb_id1 = uint_to_drb_id(1); + qos_flow_id_t qfi = uint_to_qos_flow_id(8); + + e1ap_pdu_session_res_to_setup_item pdu_session_setup_item = + generate_pdu_session_res_to_setup_item(psi, drb_id1, qfi, uint_to_five_qi(8)); + + // attempt to add session adding a new DRB and map it to a 5QI that is unknown + pdu_session_setup_result setup_result = pdu_session_mng->setup_pdu_session(pdu_session_setup_item); + + // check successful outcome + ASSERT_TRUE(setup_result.success); + ASSERT_EQ(setup_result.pdu_session_id, psi); + ASSERT_EQ(setup_result.drb_setup_results.size(), 1); + + EXPECT_FALSE(setup_result.drb_setup_results[0].success); + EXPECT_EQ(setup_result.drb_setup_results[0].cause, cause_t{cause_radio_network_t::not_supported_5qi_value}); + ASSERT_EQ(setup_result.drb_setup_results[0].qos_flow_results.size(), 0); +} + /// Create a DRB with two QFIs, of which one QFI is already mapped TEST_F(pdu_session_manager_test, drb_create_with_two_qfi_of_which_one_is_already_mapped) { @@ -226,7 +257,7 @@ TEST_F(pdu_session_manager_test, drb_create_with_two_qfi_of_which_one_is_already qos_flow_id_t qfi2 = uint_to_qos_flow_id(9); e1ap_pdu_session_res_to_setup_item pdu_session_setup_item = - generate_pdu_session_res_to_setup_item(psi, drb_id1, qfi1); + generate_pdu_session_res_to_setup_item(psi, drb_id1, qfi1, uint_to_five_qi(9)); // attempt to add session pdu_session_setup_result setup_result = pdu_session_mng->setup_pdu_session(pdu_session_setup_item); @@ -250,7 +281,7 @@ TEST_F(pdu_session_manager_test, drb_create_with_two_qfi_of_which_one_is_already // prepare modification request adding a new DRB and map it to a QFI that is already mapped e1ap_pdu_session_res_to_modify_item pdu_session_modify_item = - generate_pdu_session_res_to_modify_item_to_setup_drb(psi, drb_id2, {qfi1, qfi2}); + generate_pdu_session_res_to_modify_item_to_setup_drb(psi, drb_id2, {qfi1, qfi2}, uint_to_five_qi(9)); // attempt to perform the modification pdu_session_modification_result mod_result = pdu_session_mng->modify_pdu_session(pdu_session_modify_item, false); @@ -285,7 +316,8 @@ TEST_F(pdu_session_manager_test, dtor_rm_all_sessions_and_bearers) drb_id_t drb_id = uint_to_drb_id(1); qos_flow_id_t qfi = uint_to_qos_flow_id(8); - e1ap_pdu_session_res_to_setup_item pdu_session_setup_item = generate_pdu_session_res_to_setup_item(psi, drb_id, qfi); + e1ap_pdu_session_res_to_setup_item pdu_session_setup_item = + generate_pdu_session_res_to_setup_item(psi, drb_id, qfi, uint_to_five_qi(9)); // attempt to add session pdu_session_setup_result setup_result = pdu_session_mng->setup_pdu_session(pdu_session_setup_item); @@ -335,7 +367,8 @@ TEST_F(pdu_session_manager_test, when_new_ul_info_is_requested_f1u_is_disconnect drb_id_t drb_id = uint_to_drb_id(1); qos_flow_id_t qfi = uint_to_qos_flow_id(8); - e1ap_pdu_session_res_to_setup_item pdu_session_setup_item = generate_pdu_session_res_to_setup_item(psi, drb_id, qfi); + e1ap_pdu_session_res_to_setup_item pdu_session_setup_item = + generate_pdu_session_res_to_setup_item(psi, drb_id, qfi, uint_to_five_qi(9)); pdu_session_setup_result set_result = pdu_session_mng->setup_pdu_session(pdu_session_setup_item); ASSERT_EQ(pdu_session_mng->get_nof_pdu_sessions(), 1); diff --git a/tests/unittests/cu_up/pdu_session_manager_test.h b/tests/unittests/cu_up/pdu_session_manager_test.h index 3d407ed9a7..7b94160f1d 100644 --- a/tests/unittests/cu_up/pdu_session_manager_test.h +++ b/tests/unittests/cu_up/pdu_session_manager_test.h @@ -79,7 +79,7 @@ class pdu_session_manager_test : public ::testing::Test }; inline e1ap_pdu_session_res_to_setup_item -generate_pdu_session_res_to_setup_item(pdu_session_id_t psi, drb_id_t drb_id, qos_flow_id_t qfi) +generate_pdu_session_res_to_setup_item(pdu_session_id_t psi, drb_id_t drb_id, qos_flow_id_t qfi, five_qi_t five_qi) { // prepare request e1ap_pdu_session_res_to_setup_item pdu_session_setup_item; @@ -113,7 +113,7 @@ generate_pdu_session_res_to_setup_item(pdu_session_id_t psi, drb_id_t drb_id, qo e1ap_qos_flow_qos_param_item qos_flow_info; qos_flow_info.qos_flow_id = qfi; non_dyn_5qi_descriptor_t non_dyn_5qi; - non_dyn_5qi.five_qi = uint_to_five_qi(9); + non_dyn_5qi.five_qi = five_qi; qos_flow_info.qos_flow_level_qos_params.qos_characteristics.non_dyn_5qi = non_dyn_5qi; qos_flow_info.qos_flow_level_qos_params.ng_ran_alloc_retention_prio.prio_level = 1; qos_flow_info.qos_flow_level_qos_params.ng_ran_alloc_retention_prio.pre_emption_cap = "shall-not-trigger-pre-emption"; @@ -153,7 +153,8 @@ inline e1ap_pdu_session_res_to_modify_item generate_pdu_session_res_to_modify_it inline e1ap_pdu_session_res_to_modify_item generate_pdu_session_res_to_modify_item_to_setup_drb(pdu_session_id_t psi, drb_id_t drb_id, - std::vector qfi_list) + std::vector qfi_list, + five_qi_t five_qi) { // prepare modification request (to add further bearers) e1ap_pdu_session_res_to_modify_item pdu_session_modify_item; @@ -178,7 +179,7 @@ generate_pdu_session_res_to_modify_item_to_setup_drb(pdu_session_id_t e1ap_qos_flow_qos_param_item qos_flow_info; qos_flow_info.qos_flow_id = qfi; non_dyn_5qi_descriptor_t non_dyn_5qi; - non_dyn_5qi.five_qi = uint_to_five_qi(9); + non_dyn_5qi.five_qi = five_qi; qos_flow_info.qos_flow_level_qos_params.qos_characteristics.non_dyn_5qi = non_dyn_5qi; qos_flow_info.qos_flow_level_qos_params.ng_ran_alloc_retention_prio.prio_level = 1; qos_flow_info.qos_flow_level_qos_params.ng_ran_alloc_retention_prio.pre_emption_cap = From 9f370522ee8421df68c729a73014460d4b4245c4 Mon Sep 17 00:00:00 2001 From: asaezper Date: Thu, 11 Jan 2024 16:24:12 +0100 Subject: [PATCH 106/134] ci: set LD_LIBRARY_PATH on custom libs --- .gitlab/ci/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab/ci/build.yml b/.gitlab/ci/build.yml index f06728d08a..687c9f01a5 100644 --- a/.gitlab/ci/build.yml +++ b/.gitlab/ci/build.yml @@ -183,9 +183,11 @@ variables: if [ -n "${DPDK_VERSION}" ]; then BUILD_CMD="-d ${DPDK_VERSION} ${BUILD_CMD}" + LD_LIBRARY_PATH=/opt/dpdk/${DPDK_VERSION}/lib/x86_64-linux-gnu/ fi if [ -n "${UHD_VERSION}" ]; then BUILD_CMD="-u ${UHD_VERSION} ${BUILD_CMD}" + LD_LIBRARY_PATH=/opt/uhd/${UHD_VERSION}/lib:${LD_LIBRARY_PATH} fi if [ -n "${CLEAN_BUILD}" ]; then BUILD_CMD="-r ${CLEAN_BUILD} ${BUILD_CMD}" From 2a7618f8155238babe6671658cb1454d6a53e709 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 10 Jan 2024 14:45:18 +0100 Subject: [PATCH 107/134] support: change memory ordering for fail path of lockfree stack --- .../memory_pool/lockfree_object_pool.h | 5 +-- lib/support/byte_buffer.cpp | 31 ++++++++++++------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/include/srsran/support/memory_pool/lockfree_object_pool.h b/include/srsran/support/memory_pool/lockfree_object_pool.h index c64b2fd768..8eafea08cd 100644 --- a/include/srsran/support/memory_pool/lockfree_object_pool.h +++ b/include/srsran/support/memory_pool/lockfree_object_pool.h @@ -54,8 +54,9 @@ class lockfree_index_stack // We use memory ordering "acquire" to form a "synchronizes-with" relationship with the release in push(). // The "acquire" ordering also ensures that the next_idx[old_top.index] read is not reordered to happen before the // atomic operation. - // In case of failure, "top" remains unchanged, so the operation can have "relaxed" ordering. - while (not top.compare_exchange_weak(old_top, new_top, std::memory_order_acquire, std::memory_order_relaxed)) { + // In case of failure, "top" remains unchanged, but we need to re-read the next_idx[] which could have changed due + // to a concurrent push(). So, the operation can have "acquired" ordering. + while (not top.compare_exchange_weak(old_top, new_top, std::memory_order_acquire, std::memory_order_acquire)) { if (old_top.index == npos()) { return npos(); } diff --git a/lib/support/byte_buffer.cpp b/lib/support/byte_buffer.cpp index 723de10726..20741987c8 100644 --- a/lib/support/byte_buffer.cpp +++ b/lib/support/byte_buffer.cpp @@ -45,14 +45,13 @@ namespace { struct memory_arena_linear_allocator { /// Pointer to the memory block obtained from byte_buffer_segment_pool. void* mem_block = nullptr; + /// Size of the memory block in bytes. + size_t mem_block_size; /// Offset in bytes from the beginning of the memory block, determining where the next allocation will be made. size_t offset = 0; - memory_arena_linear_allocator() noexcept : - mem_block([]() { - static auto& pool = detail::get_default_byte_buffer_segment_pool(); - return pool.allocate_node(pool.memory_block_size()); - }()) + memory_arena_linear_allocator(void* mem_block_, size_t mem_block_size_) noexcept : + mem_block(mem_block_), mem_block_size(mem_block_size_) { } @@ -65,7 +64,7 @@ struct memory_arena_linear_allocator { bool empty() const { return mem_block == nullptr; } - size_t space_left() const { return detail::get_default_byte_buffer_segment_pool().memory_block_size() - offset; } + size_t space_left() const { return mem_block_size - offset; } }; /// Allocator for byte_buffer control_block that will leverage the \c memory_arena_linear_allocator. @@ -235,14 +234,20 @@ byte_buffer::node_t* byte_buffer::create_head_segment(size_t headroom) static auto& pool = detail::get_default_byte_buffer_segment_pool(); static const size_t block_size = pool.memory_block_size(); - // Create control block using allocator. - memory_arena_linear_allocator arena; - if (arena.empty()) { + // Allocate new node. + void* mem_block = pool.allocate_node(block_size); + if (mem_block == nullptr) { + // Pool is depleted. byte_buffer::warn_alloc_failure(); return nullptr; } + + // Create control block using allocator. + memory_arena_linear_allocator arena{mem_block, block_size}; ctrl_blk_ptr = std::allocate_shared(control_block_allocator{arena}); if (ctrl_blk_ptr == nullptr) { + byte_buffer::warn_alloc_failure(); + pool.deallocate_node(mem_block); return nullptr; } @@ -266,12 +271,14 @@ byte_buffer::node_t* byte_buffer::create_segment(size_t headroom) static const size_t block_size = pool.memory_block_size(); // Allocate memory block. - memory_arena_linear_allocator arena; - if (arena.empty()) { + void* mem_block = pool.allocate_node(block_size); + if (mem_block == nullptr) { byte_buffer::warn_alloc_failure(); return nullptr; } - void* segment_start = arena.allocate(sizeof(node_t), alignof(node_t)); + + memory_arena_linear_allocator arena{mem_block, block_size}; + void* segment_start = arena.allocate(sizeof(node_t), alignof(node_t)); srsran_assert(block_size > arena.offset, "The memory block provided by the pool is too small"); size_t segment_size = block_size - arena.offset; void* payload_start = arena.allocate(segment_size, 1); From 3d4dc9b71b9e920a5a72de563981731e5d83f80e Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 10 Jan 2024 17:09:27 +0100 Subject: [PATCH 108/134] support: implement unit test for lockfree stack --- .../support/lockfree_object_pool_test.cpp | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/tests/unittests/support/lockfree_object_pool_test.cpp b/tests/unittests/support/lockfree_object_pool_test.cpp index fc1f0f4d0f..e645e0ac1b 100644 --- a/tests/unittests/support/lockfree_object_pool_test.cpp +++ b/tests/unittests/support/lockfree_object_pool_test.cpp @@ -9,6 +9,8 @@ */ #include "srsran/support/memory_pool/lockfree_object_pool.h" +#include "srsran/support/test_utils.h" +#include "srsran/support/unique_thread.h" #include using namespace srsran; @@ -80,3 +82,67 @@ TEST(lockfree_bounded_stack_test, test_pop_empty) ASSERT_EQ(val, 3); ASSERT_FALSE(stack.pop(val)); } + +TEST(lockfree_bounded_stack_test, concurrent_push_pop) +{ + std::vector> workers; + unsigned nof_workers = 10; + unsigned nof_oper = 100; + + unsigned stack_cap = 10; + lockfree_bounded_stack stack{stack_cap}; + for (unsigned i = 0; i != stack_cap; ++i) { + stack.push(i); + } + + std::atomic start{false}; + + for (unsigned i = 0; i != nof_workers; ++i) { + workers.emplace_back(std::make_unique(fmt::format("worker{}", i), [&]() { + std::vector vals; + vals.reserve(stack_cap); + + while (not start) { + } + for (unsigned j = 0; j != nof_oper; ++j) { + if (test_rgen::uniform_int(0, 1) == 0) { + if (not vals.empty()) { + EXPECT_TRUE(stack.push(vals.back())); + fmt::print("pushed {}\n", vals.back()); + vals.pop_back(); + } + } else { + int8_t val; + if (stack.pop(val)) { + fmt::print("popped {}\n", val); + EXPECT_TRUE(vals.size() <= stack_cap); + vals.push_back(val); + } + } + } + + while (not vals.empty()) { + EXPECT_TRUE(stack.push(vals.back())); + fmt::print("pushed {}\n", vals.back()); + vals.pop_back(); + } + })); + } + + start = true; + + for (auto& w : workers) { + w->join(); + } + + std::vector vals; + std::vector expected; + for (unsigned i = 0; i != stack_cap; ++i) { + int8_t val; + EXPECT_TRUE(stack.pop(val)); + vals.push_back(val); + expected.push_back(i); + } + std::sort(vals.begin(), vals.end()); + ASSERT_EQ(vals, expected); +} \ No newline at end of file From 898b8b846e89bd4f0d60f58cc3803d6ed6775ea2 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 11 Jan 2024 10:12:05 +0100 Subject: [PATCH 109/134] support: add test for lockfree_index_stack --- .../support/lockfree_object_pool_test.cpp | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tests/unittests/support/lockfree_object_pool_test.cpp b/tests/unittests/support/lockfree_object_pool_test.cpp index e645e0ac1b..a4ef21761c 100644 --- a/tests/unittests/support/lockfree_object_pool_test.cpp +++ b/tests/unittests/support/lockfree_object_pool_test.cpp @@ -15,6 +15,68 @@ using namespace srsran; +TEST(lockfree_index_stack_test, concurrent_push_pop) +{ + std::vector> workers; + unsigned nof_workers = 2; + unsigned nof_oper = 1000; + + unsigned stack_cap = 10; + detail::lockfree_index_stack stack{stack_cap, true}; + + std::atomic start{false}; + + for (unsigned i = 0; i != nof_workers; ++i) { + workers.emplace_back(std::make_unique([&]() { + std::vector vals; + vals.reserve(stack_cap); + + while (not start) { + } + + for (unsigned j = 0; j != nof_oper; ++j) { + if (test_rgen::uniform_int(0, 1) == 0) { + if (not vals.empty()) { + stack.push(vals.back()); + fmt::print("pushed {}\n", vals.back()); + vals.pop_back(); + } + } else { + uint32_t val = stack.try_pop(); + if (val != detail::lockfree_index_stack::npos()) { + fmt::print("popped {}\n", val); + EXPECT_TRUE(vals.size() < stack_cap); + vals.push_back(val); + } + } + } + + while (not vals.empty()) { + stack.push(vals.back()); + fmt::print("pushed {}\n", vals.back()); + vals.pop_back(); + } + })); + } + + start = true; + + for (auto& w : workers) { + w->join(); + } + + std::vector vals; + std::vector expected; + for (unsigned i = 0; i != stack_cap; ++i) { + uint32_t val = stack.try_pop(); + EXPECT_NE(val, detail::lockfree_index_stack::npos()); + vals.push_back(val); + expected.push_back(i); + } + std::sort(vals.begin(), vals.end()); + ASSERT_EQ(vals, expected); +} + TEST(lockfree_object_pool_test, pool_created_with_requested_capacity) { unsigned nof_objs = 10; From 73925d136742bfbdefa8e791748ce573bc7ad243 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 11 Jan 2024 18:35:49 +0100 Subject: [PATCH 110/134] support: use atomic for next_idx[] array in the lockfree_index_stack --- .../memory_pool/lockfree_object_pool.h | 26 +++++++++++-------- .../support/lockfree_object_pool_test.cpp | 4 +-- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/include/srsran/support/memory_pool/lockfree_object_pool.h b/include/srsran/support/memory_pool/lockfree_object_pool.h index 8eafea08cd..dafb8f51a1 100644 --- a/include/srsran/support/memory_pool/lockfree_object_pool.h +++ b/include/srsran/support/memory_pool/lockfree_object_pool.h @@ -30,17 +30,18 @@ class lockfree_index_stack static constexpr index_type npos() { return std::numeric_limits::max(); } lockfree_index_stack(uint32_t nof_indexes, bool start_full) : - top(node{start_full ? 0 : npos(), 0}), next_idx(nof_indexes, npos()) + top(node{start_full ? 0 : npos(), 0}), next_idx(new std::atomic[nof_indexes]), sz(nof_indexes) { srsran_assert(nof_indexes > 0 and nof_indexes < npos(), "Invalid stack size={}", nof_indexes); // Initialize the stack of next indexes like [1, 2, 3, ..., nof_indexes - 1, npos] for (index_type i = 1; i < nof_indexes; ++i) { - next_idx[i - 1] = i; + next_idx[i - 1].store(i, std::memory_order_relaxed); } + next_idx[nof_indexes - 1].store(npos(), std::memory_order_relaxed); } - index_type capacity() const { return next_idx.size(); } + index_type capacity() const { return sz; } index_type try_pop() { @@ -50,7 +51,7 @@ class lockfree_index_stack if (old_top.index == npos()) { return npos(); } - node new_top{next_idx[old_top.index], old_top.epoch + 1}; + node new_top{next_idx[old_top.index].load(std::memory_order_relaxed), old_top.epoch + 1}; // We use memory ordering "acquire" to form a "synchronizes-with" relationship with the release in push(). // The "acquire" ordering also ensures that the next_idx[old_top.index] read is not reordered to happen before the // atomic operation. @@ -60,7 +61,7 @@ class lockfree_index_stack if (old_top.index == npos()) { return npos(); } - new_top = node{next_idx[old_top.index], old_top.epoch + 1}; + new_top = node{next_idx[old_top.index].load(std::memory_order_relaxed), old_top.epoch + 1}; } return old_top.index; } @@ -68,14 +69,14 @@ class lockfree_index_stack void push(index_type index) { node old_top{top.load(std::memory_order_relaxed)}; - next_idx[index] = old_top.index; - node new_top{index, old_top.epoch + 1}; + next_idx[index].store(old_top.index, std::memory_order_relaxed); + node new_top{index, old_top.epoch}; // We use memory ordering "release" for success path to form a "synchronizes-with" relationship with the acquire in // pop(). The "release" ordering also ensures that the next_idx[index] write is visible to other threads. // In case of failure, "top" remains unchanged, so the operation can have "relaxed" ordering. while (not top.compare_exchange_weak(old_top, new_top, std::memory_order_release, std::memory_order_relaxed)) { - new_top.epoch = old_top.epoch + 1; - next_idx[index] = old_top.index; + new_top.epoch = old_top.epoch; + next_idx[index].store(old_top.index, std::memory_order_relaxed); } } @@ -87,8 +88,11 @@ class lockfree_index_stack static_assert(sizeof(node) <= sizeof(uint64_t), "node sizeof should not go above 64-bits, otherwise we lose is_lock_free guarantees in most platforms"); - std::atomic top; - std::vector next_idx; + std::atomic top; + + std::unique_ptr[]> next_idx; + + const size_t sz; }; } // namespace detail diff --git a/tests/unittests/support/lockfree_object_pool_test.cpp b/tests/unittests/support/lockfree_object_pool_test.cpp index a4ef21761c..51d643c18c 100644 --- a/tests/unittests/support/lockfree_object_pool_test.cpp +++ b/tests/unittests/support/lockfree_object_pool_test.cpp @@ -18,7 +18,7 @@ using namespace srsran; TEST(lockfree_index_stack_test, concurrent_push_pop) { std::vector> workers; - unsigned nof_workers = 2; + unsigned nof_workers = 8; unsigned nof_oper = 1000; unsigned stack_cap = 10; @@ -207,4 +207,4 @@ TEST(lockfree_bounded_stack_test, concurrent_push_pop) } std::sort(vals.begin(), vals.end()); ASSERT_EQ(vals, expected); -} \ No newline at end of file +} From da5fc6183c352512e9d76c3de305669d2bc9d858 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 11 Jan 2024 18:58:36 +0100 Subject: [PATCH 111/134] support: do not depend on libatomic because tsan triggers false alarms for it --- .../memory_pool/lockfree_object_pool.h | 34 ++++++++++--------- lib/support/CMakeLists.txt | 2 +- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/include/srsran/support/memory_pool/lockfree_object_pool.h b/include/srsran/support/memory_pool/lockfree_object_pool.h index dafb8f51a1..237b0ee04f 100644 --- a/include/srsran/support/memory_pool/lockfree_object_pool.h +++ b/include/srsran/support/memory_pool/lockfree_object_pool.h @@ -30,7 +30,7 @@ class lockfree_index_stack static constexpr index_type npos() { return std::numeric_limits::max(); } lockfree_index_stack(uint32_t nof_indexes, bool start_full) : - top(node{start_full ? 0 : npos(), 0}), next_idx(new std::atomic[nof_indexes]), sz(nof_indexes) + top(make_node(start_full ? 0 : npos(), 0)), next_idx(new std::atomic[nof_indexes]), sz(nof_indexes) { srsran_assert(nof_indexes > 0 and nof_indexes < npos(), "Invalid stack size={}", nof_indexes); @@ -48,45 +48,47 @@ class lockfree_index_stack // We use memory ordering "acquire" to form a "synchronizes-with" relationship with the release of the last push(), // otherwise the write to next_idx[] during the push() is not visible in this thread. node old_top{top.load(std::memory_order_acquire)}; - if (old_top.index == npos()) { + if (get_index(old_top) == npos()) { return npos(); } - node new_top{next_idx[old_top.index].load(std::memory_order_relaxed), old_top.epoch + 1}; + node new_top = make_node(next_idx[get_index(old_top)].load(std::memory_order_relaxed), get_next_aba(old_top)); // We use memory ordering "acquire" to form a "synchronizes-with" relationship with the release in push(). // The "acquire" ordering also ensures that the next_idx[old_top.index] read is not reordered to happen before the // atomic operation. // In case of failure, "top" remains unchanged, but we need to re-read the next_idx[] which could have changed due // to a concurrent push(). So, the operation can have "acquired" ordering. while (not top.compare_exchange_weak(old_top, new_top, std::memory_order_acquire, std::memory_order_acquire)) { - if (old_top.index == npos()) { + if (get_index(old_top) == npos()) { return npos(); } - new_top = node{next_idx[old_top.index].load(std::memory_order_relaxed), old_top.epoch + 1}; + new_top = make_node(next_idx[get_index(old_top)].load(std::memory_order_relaxed), get_next_aba(old_top)); } - return old_top.index; + return get_index(old_top); } void push(index_type index) { node old_top{top.load(std::memory_order_relaxed)}; - next_idx[index].store(old_top.index, std::memory_order_relaxed); - node new_top{index, old_top.epoch}; + next_idx[index].store(get_index(old_top), std::memory_order_relaxed); + node new_top = make_node(index, get_aba(old_top)); // We use memory ordering "release" for success path to form a "synchronizes-with" relationship with the acquire in // pop(). The "release" ordering also ensures that the next_idx[index] write is visible to other threads. // In case of failure, "top" remains unchanged, so the operation can have "relaxed" ordering. while (not top.compare_exchange_weak(old_top, new_top, std::memory_order_release, std::memory_order_relaxed)) { - new_top.epoch = old_top.epoch; - next_idx[index].store(old_top.index, std::memory_order_relaxed); + set_aba(new_top, get_aba(old_top)); + next_idx[index].store(get_index(old_top), std::memory_order_relaxed); } } private: - struct node { - index_type index; - index_type epoch; - }; - static_assert(sizeof(node) <= sizeof(uint64_t), - "node sizeof should not go above 64-bits, otherwise we lose is_lock_free guarantees in most platforms"); + using node = uint64_t; + + node make_node(index_type index, index_type aba) { return (static_cast(aba) << 32U) | index; } + uint32_t get_index(node n) const { return n & 0xFFFFFFFF; } + void set_index(node& n, index_type index) { n = (n & 0xFFFFFFFF00000000) | index; } + void set_aba(node& n, index_type aba) { n = (n & 0xFFFFFFFF) | (static_cast(aba) << 32U); } + uint32_t get_aba(node n) const { return static_cast((n & 0xFFFFFFFF00000000) >> 32U); } + uint32_t get_next_aba(node n) const { return static_cast((n & 0xFFFFFFFF00000000) >> 32U) + 1; } std::atomic top; diff --git a/lib/support/CMakeLists.txt b/lib/support/CMakeLists.txt index 01b3f8208d..2c08cc2761 100644 --- a/lib/support/CMakeLists.txt +++ b/lib/support/CMakeLists.txt @@ -27,7 +27,7 @@ set(SOURCES byte_buffer_chain.cpp) add_library(srsran_support STATIC ${SOURCES}) -target_link_libraries(srsran_support srsran_network ${CMAKE_THREAD_LIBS_INIT} ${YAMLCPP_LIBRARY} srslog atomic) +target_link_libraries(srsran_support srsran_network ${CMAKE_THREAD_LIBS_INIT} ${YAMLCPP_LIBRARY} srslog) add_backward(srsran_support) if (Backward_FOUND AND BACKWARD_HAS_EXTERNAL_LIBRARIES) From 4140712099012a2fe78c8407397a124740c9b32e Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 11 Jan 2024 19:30:29 +0100 Subject: [PATCH 112/134] support: improve the explanation on why lockfree stack index members need to be atomic --- .../memory_pool/lockfree_object_pool.h | 19 +++++++++++-------- .../support/lockfree_object_pool_test.cpp | 10 ++-------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/include/srsran/support/memory_pool/lockfree_object_pool.h b/include/srsran/support/memory_pool/lockfree_object_pool.h index 237b0ee04f..f4b3a7d356 100644 --- a/include/srsran/support/memory_pool/lockfree_object_pool.h +++ b/include/srsran/support/memory_pool/lockfree_object_pool.h @@ -55,9 +55,8 @@ class lockfree_index_stack // We use memory ordering "acquire" to form a "synchronizes-with" relationship with the release in push(). // The "acquire" ordering also ensures that the next_idx[old_top.index] read is not reordered to happen before the // atomic operation. - // In case of failure, "top" remains unchanged, but we need to re-read the next_idx[] which could have changed due - // to a concurrent push(). So, the operation can have "acquired" ordering. - while (not top.compare_exchange_weak(old_top, new_top, std::memory_order_acquire, std::memory_order_acquire)) { + // In case of failure, "top" remains unchanged, so we can use memory_order_relaxed. + while (not top.compare_exchange_weak(old_top, new_top, std::memory_order_acquire, std::memory_order_relaxed)) { if (get_index(old_top) == npos()) { return npos(); } @@ -84,14 +83,18 @@ class lockfree_index_stack using node = uint64_t; node make_node(index_type index, index_type aba) { return (static_cast(aba) << 32U) | index; } - uint32_t get_index(node n) const { return n & 0xFFFFFFFF; } - void set_index(node& n, index_type index) { n = (n & 0xFFFFFFFF00000000) | index; } - void set_aba(node& n, index_type aba) { n = (n & 0xFFFFFFFF) | (static_cast(aba) << 32U); } - uint32_t get_aba(node n) const { return static_cast((n & 0xFFFFFFFF00000000) >> 32U); } - uint32_t get_next_aba(node n) const { return static_cast((n & 0xFFFFFFFF00000000) >> 32U) + 1; } + uint32_t get_index(node n) const { return n & 0xffffffff; } + void set_index(node& n, index_type index) { n = (n & 0xffffffff00000000) | index; } + void set_aba(node& n, index_type aba) { n = (n & 0xffffffff) | (static_cast(aba) << 32U); } + uint32_t get_aba(node n) const { return static_cast((n & 0xffffffff00000000) >> 32U); } + uint32_t get_next_aba(node n) const { return static_cast((n & 0xffffffff00000000) >> 32U) + 1; } std::atomic top; + // List of unique indexes stored in the stack. Elements need to be atomic. Consider the scenario, where one thread + // starts a pop by reading next_idx[i], where "i" corresponds to the top node, and then another thread comes along, + // pops "i" and pushes it again, reading and modifying next_idx[i]. The first thread will fail the CAS; however, + // this is still considered a data race if next_idx[i] is not atomic (e.g. TSAN detects it for instance). std::unique_ptr[]> next_idx; const size_t sz; diff --git a/tests/unittests/support/lockfree_object_pool_test.cpp b/tests/unittests/support/lockfree_object_pool_test.cpp index 51d643c18c..3994f5feb4 100644 --- a/tests/unittests/support/lockfree_object_pool_test.cpp +++ b/tests/unittests/support/lockfree_object_pool_test.cpp @@ -38,13 +38,11 @@ TEST(lockfree_index_stack_test, concurrent_push_pop) if (test_rgen::uniform_int(0, 1) == 0) { if (not vals.empty()) { stack.push(vals.back()); - fmt::print("pushed {}\n", vals.back()); vals.pop_back(); } } else { uint32_t val = stack.try_pop(); if (val != detail::lockfree_index_stack::npos()) { - fmt::print("popped {}\n", val); EXPECT_TRUE(vals.size() < stack_cap); vals.push_back(val); } @@ -53,7 +51,6 @@ TEST(lockfree_index_stack_test, concurrent_push_pop) while (not vals.empty()) { stack.push(vals.back()); - fmt::print("pushed {}\n", vals.back()); vals.pop_back(); } })); @@ -149,9 +146,9 @@ TEST(lockfree_bounded_stack_test, concurrent_push_pop) { std::vector> workers; unsigned nof_workers = 10; - unsigned nof_oper = 100; + unsigned nof_oper = 1000; - unsigned stack_cap = 10; + unsigned stack_cap = 100; lockfree_bounded_stack stack{stack_cap}; for (unsigned i = 0; i != stack_cap; ++i) { stack.push(i); @@ -170,13 +167,11 @@ TEST(lockfree_bounded_stack_test, concurrent_push_pop) if (test_rgen::uniform_int(0, 1) == 0) { if (not vals.empty()) { EXPECT_TRUE(stack.push(vals.back())); - fmt::print("pushed {}\n", vals.back()); vals.pop_back(); } } else { int8_t val; if (stack.pop(val)) { - fmt::print("popped {}\n", val); EXPECT_TRUE(vals.size() <= stack_cap); vals.push_back(val); } @@ -185,7 +180,6 @@ TEST(lockfree_bounded_stack_test, concurrent_push_pop) while (not vals.empty()) { EXPECT_TRUE(stack.push(vals.back())); - fmt::print("pushed {}\n", vals.back()); vals.pop_back(); } })); From e78b0a1e13d464567056fb747499f275926b3edd Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Mon, 8 Jan 2024 16:34:51 +0100 Subject: [PATCH 113/134] rlc: lockfree metrics --- include/srsran/rlc/rlc_rx_metrics.h | 1 - include/srsran/rlc/rlc_tx_metrics.h | 27 +- .../e2sm_kpm_du_meas_provider_impl.cpp | 47 +++- lib/rlc/rlc_base_entity.h | 31 ++- lib/rlc/rlc_tx_am_entity.cpp | 6 +- lib/rlc/rlc_tx_metrics_container.h | 251 +++++++++++++----- lib/rlc/rlc_tx_tm_entity.cpp | 2 +- lib/rlc/rlc_tx_um_entity.cpp | 6 +- .../e2/e2sm_kpm_meas_provider_test.cpp | 20 +- 9 files changed, 284 insertions(+), 107 deletions(-) diff --git a/include/srsran/rlc/rlc_rx_metrics.h b/include/srsran/rlc/rlc_rx_metrics.h index d412d44af5..d7811dc6b6 100644 --- a/include/srsran/rlc/rlc_rx_metrics.h +++ b/include/srsran/rlc/rlc_rx_metrics.h @@ -12,7 +12,6 @@ #include "srsran/rlc/rlc_config.h" #include "fmt/format.h" -#include namespace srsran { diff --git a/include/srsran/rlc/rlc_tx_metrics.h b/include/srsran/rlc/rlc_tx_metrics.h index ec963147a1..00180b8e5f 100644 --- a/include/srsran/rlc/rlc_tx_metrics.h +++ b/include/srsran/rlc/rlc_tx_metrics.h @@ -12,7 +12,6 @@ #include "srsran/rlc/rlc_config.h" #include "fmt/format.h" -#include namespace srsran { @@ -21,17 +20,17 @@ struct rlc_tm_tx_metrics { }; struct rlc_um_tx_metrics { - uint32_t num_sdu_segments; ///< Number of SDU segments TX'ed - uint32_t num_sdu_segment_bytes; ///< Number of SDU segments Bytes + uint32_t num_pdus_with_segmentation; ///< Number of transmitted PDUs with segmentation + uint32_t num_pdu_bytes_with_segmentation; ///< Number of transmitted PDU bytes with segmentation }; struct rlc_am_tx_metrics { - uint32_t num_retx_pdus; ///< Number of RETX'ed PDUs - uint32_t num_retx_pdu_bytes; ///< Number of RETX'ed PDUs bytes - uint32_t num_sdu_segments; ///< Number of SDU segments TX'ed - uint32_t num_sdu_segment_bytes; ///< Number of SDU segments bytes - uint32_t num_ctrl_pdus; ///< Number of control PDUs - uint32_t num_ctrl_pdu_bytes; ///< Number of control PDUs bytes + uint32_t num_pdus_with_segmentation; ///< Number of transmitted PDUs with segmentation + uint32_t num_pdu_bytes_with_segmentation; ///< Number of transmitted PDU bytes with segmentation + uint32_t num_retx_pdus; ///< Number of RETX'ed PDUs + uint32_t num_retx_pdu_bytes; ///< Number of RETX'ed PDUs bytes + uint32_t num_ctrl_pdus; ///< Number of control PDUs + uint32_t num_ctrl_pdu_bytes; ///< Number of control PDUs bytes }; struct rlc_tx_metrics { @@ -43,8 +42,8 @@ struct rlc_tx_metrics { uint32_t num_discard_failures; ///< Number of failed SDU discards (instructed from higher layer) // PDU metrics - uint32_t num_pdus; ///< Number of PDUs - size_t num_pdu_bytes; ///< Number of PDU bytes + uint32_t num_pdus_no_segmentation; ///< Number of transmitted PDUs without segmentation + size_t num_pdu_bytes_no_segmentation; ///< Number of transmitted PDU bytes without segmentation /// RLC mode of the entity rlc_mode mode; @@ -93,14 +92,14 @@ struct formatter { { return format_to(ctx.out(), "num_sdus={} num_sdu_bytes={} num_dropped_sdus={} num_discarded_sdus={} " - "num_discard_failures={} num_pdus={} num_pdu_bytes={}", + "num_discard_failures={} num_pdus_no_segm={} num_pdu_bytes_no_segm={}", m.num_sdus, m.num_sdu_bytes, m.num_dropped_sdus, m.num_discarded_sdus, m.num_discard_failures, - m.num_pdus, - m.num_pdu_bytes); + m.num_pdus_no_segmentation, + m.num_pdu_bytes_no_segmentation); } }; } // namespace fmt diff --git a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.cpp b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.cpp index 860cbb043a..c421c1f4e2 100644 --- a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.cpp +++ b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.cpp @@ -115,8 +115,34 @@ void e2sm_kpm_du_meas_provider_impl::report_metrics(const rlc_metrics& metrics) ue_aggr_rlc_metrics[metrics.ue_index].tx.num_dropped_sdus += metrics.tx.num_dropped_sdus; ue_aggr_rlc_metrics[metrics.ue_index].tx.num_discarded_sdus += metrics.tx.num_discarded_sdus; ue_aggr_rlc_metrics[metrics.ue_index].tx.num_discard_failures += metrics.tx.num_discard_failures; - ue_aggr_rlc_metrics[metrics.ue_index].tx.num_pdus += metrics.tx.num_pdus; - ue_aggr_rlc_metrics[metrics.ue_index].tx.num_pdu_bytes += metrics.tx.num_pdu_bytes; + ue_aggr_rlc_metrics[metrics.ue_index].tx.num_pdus_no_segmentation += metrics.tx.num_pdus_no_segmentation; + ue_aggr_rlc_metrics[metrics.ue_index].tx.num_pdu_bytes_no_segmentation += metrics.tx.num_pdu_bytes_no_segmentation; + switch (ue_aggr_rlc_metrics[metrics.ue_index].tx.mode) { + case rlc_mode::um_bidir: + case rlc_mode::um_unidir_dl: + ue_aggr_rlc_metrics[metrics.ue_index].tx.mode_specific.um.num_pdus_with_segmentation += + metrics.tx.mode_specific.um.num_pdus_with_segmentation; + ue_aggr_rlc_metrics[metrics.ue_index].tx.mode_specific.um.num_pdu_bytes_with_segmentation += + metrics.tx.mode_specific.um.num_pdu_bytes_with_segmentation; + break; + case rlc_mode::am: + ue_aggr_rlc_metrics[metrics.ue_index].tx.mode_specific.am.num_pdus_with_segmentation += + metrics.tx.mode_specific.am.num_pdus_with_segmentation; + ue_aggr_rlc_metrics[metrics.ue_index].tx.mode_specific.am.num_pdu_bytes_with_segmentation += + metrics.tx.mode_specific.am.num_pdu_bytes_with_segmentation; + ue_aggr_rlc_metrics[metrics.ue_index].tx.mode_specific.am.num_retx_pdus += + metrics.tx.mode_specific.am.num_retx_pdus; + ue_aggr_rlc_metrics[metrics.ue_index].tx.mode_specific.am.num_retx_pdu_bytes += + metrics.tx.mode_specific.am.num_retx_pdu_bytes; + ue_aggr_rlc_metrics[metrics.ue_index].tx.mode_specific.am.num_ctrl_pdus += + metrics.tx.mode_specific.am.num_ctrl_pdus; + ue_aggr_rlc_metrics[metrics.ue_index].tx.mode_specific.am.num_ctrl_pdu_bytes += + metrics.tx.mode_specific.am.num_ctrl_pdu_bytes; + break; + default: + // nothing to do here + break; + } ue_aggr_rlc_metrics[metrics.ue_index].counter++; } } @@ -275,7 +301,22 @@ bool e2sm_kpm_du_meas_provider_impl::get_drb_dl_mean_throughput( return meas_collected; } for (auto& ue : ue_aggr_rlc_metrics) { - ue_throughput[ue.first] = bytes_to_kbits(ue.second.tx.num_pdu_bytes / ue.second.counter) / seconds; // unit is kbps + size_t num_pdu_bytes_with_segmentation; + switch (ue.second.tx.mode) { + case rlc_mode::um_bidir: + case rlc_mode::um_unidir_dl: + num_pdu_bytes_with_segmentation = ue.second.tx.mode_specific.um.num_pdu_bytes_with_segmentation; + break; + case rlc_mode::am: + num_pdu_bytes_with_segmentation = ue.second.tx.mode_specific.am.num_pdu_bytes_with_segmentation; + break; + default: + num_pdu_bytes_with_segmentation = 0; + } + ue_throughput[ue.first] = + bytes_to_kbits((ue.second.tx.num_pdu_bytes_no_segmentation + num_pdu_bytes_with_segmentation) / + ue.second.counter) / + seconds; // unit is kbps } if (ues.size() == 0) { meas_record_item_c meas_record_item; diff --git a/lib/rlc/rlc_base_entity.h b/lib/rlc/rlc_base_entity.h index 7529453a58..2b656f5d17 100644 --- a/lib/rlc/rlc_base_entity.h +++ b/lib/rlc/rlc_base_entity.h @@ -90,20 +90,23 @@ class rlc_base_entity : public rlc_entity rlc_metrics_notif->report_metrics(m); } if (m.tx.mode == rlc_mode::am) { - logger.log_info("TX metrics period={}ms num_sdus={} sdu_rate={}kbps, dropped_sdus={} discarded_sdus={} " - "num_pdus={} pdu_rate={}kbps num_retx={} " - "retx_rate={}kbps ctrl_pdus={} ctrl_rate={}kbps", - metrics_period.count(), - m.tx.num_sdus, - (double)m.tx.num_sdu_bytes * 8 / (double)metrics_period.count(), - m.tx.num_dropped_sdus, - m.tx.num_discarded_sdus, - m.tx.num_pdus, - (double)m.tx.num_pdu_bytes * 8 / (double)metrics_period.count(), - m.tx.mode_specific.am.num_retx_pdus, - (double)m.tx.mode_specific.am.num_retx_pdu_bytes * 8 / (double)metrics_period.count(), - m.tx.mode_specific.am.num_ctrl_pdus, - (double)m.tx.mode_specific.am.num_ctrl_pdu_bytes * 8 / (double)metrics_period.count()); + logger.log_info( + "TX metrics period={}ms num_sdus={} sdu_rate={}kbps, dropped_sdus={} discarded_sdus={} " + "num_pdus_no_segm={} pdu_rate_no_segm={}kbps num_pdus_with_segm={} pdu_rate_with_segm={}kbps num_retx={} " + "retx_rate={}kbps ctrl_pdus={} ctrl_rate={}kbps", + metrics_period.count(), + m.tx.num_sdus, + (double)m.tx.num_sdu_bytes * 8 / (double)metrics_period.count(), + m.tx.num_dropped_sdus, + m.tx.num_discarded_sdus, + m.tx.num_pdus_no_segmentation, + (double)m.tx.mode_specific.am.num_pdus_with_segmentation * 8 / (double)metrics_period.count(), + m.tx.num_pdus_no_segmentation, + (double)m.tx.mode_specific.am.num_pdu_bytes_with_segmentation * 8 / (double)metrics_period.count(), + m.tx.mode_specific.am.num_retx_pdus, + (double)m.tx.mode_specific.am.num_retx_pdu_bytes * 8 / (double)metrics_period.count(), + m.tx.mode_specific.am.num_ctrl_pdus, + (double)m.tx.mode_specific.am.num_ctrl_pdu_bytes * 8 / (double)metrics_period.count()); logger.log_info("RX metrics period={}ms num_sdus={} sdu_rate={}kbps num_pdus={} pdu_rate={}kbps " "ctrl_pdus={}, ctrl_rate={}kbps", metrics_period.count(), diff --git a/lib/rlc/rlc_tx_am_entity.cpp b/lib/rlc/rlc_tx_am_entity.cpp index be0fa29c26..62d552915d 100644 --- a/lib/rlc/rlc_tx_am_entity.cpp +++ b/lib/rlc/rlc_tx_am_entity.cpp @@ -233,7 +233,7 @@ size_t rlc_tx_am_entity::build_new_pdu(span rlc_pdu_buf) st.tx_next = (st.tx_next + 1) % mod; // Update metrics - metrics.metrics_add_pdus(1, pdu_len); + metrics.metrics_add_pdus_no_segmentation(1, pdu_len); // Log state log_state(srslog::basic_levels::debug); @@ -297,7 +297,7 @@ size_t rlc_tx_am_entity::build_first_sdu_segment(span rlc_pdu_buf, rlc_ sdu_info.next_so += segment_payload_len; // Update metrics - metrics.metrics_add_pdus(1, pdu_len); + metrics.metrics_add_pdus_with_segmentation_am(1, pdu_len); // Log state log_state(srslog::basic_levels::debug); @@ -392,7 +392,7 @@ size_t rlc_tx_am_entity::build_continued_sdu_segment(span rlc_pdu_buf, } // Update metrics - metrics.metrics_add_pdus(1, pdu_len); + metrics.metrics_add_pdus_with_segmentation_am(1, pdu_len); // Log state log_state(srslog::basic_levels::debug); diff --git a/lib/rlc/rlc_tx_metrics_container.h b/lib/rlc/rlc_tx_metrics_container.h index 0296034f1c..3f61f253d8 100644 --- a/lib/rlc/rlc_tx_metrics_container.h +++ b/lib/rlc/rlc_tx_metrics_container.h @@ -11,16 +11,108 @@ #pragma once #include "srsran/rlc/rlc_tx_metrics.h" -#include "srsran/srslog/srslog.h" -#include namespace srsran { +struct rlc_tx_metrics_atomic_higher { + std::atomic num_sdus; ///< Number of SDUs + std::atomic num_sdu_bytes; ///< Number of SDU bytes + std::atomic num_dropped_sdus; ///< Number of dropped SDUs (due to full queue) + std::atomic num_discarded_sdus; ///< Number of discarded SDUs (instructed from higher layer) + std::atomic num_discard_failures; ///< Number of failed SDU discards (instructed from higher layer) + + void reset() + { + num_sdus.store(0, std::memory_order_relaxed); + num_sdu_bytes.store(0, std::memory_order_relaxed); + num_dropped_sdus.store(0, std::memory_order_relaxed); + num_discarded_sdus.store(0, std::memory_order_relaxed); + num_discard_failures.store(0, std::memory_order_relaxed); + } +}; + +struct rlc_tm_tx_metrics_atomic_lower { + std::atomic num_small_allocs; ///< Number of allocations that are too small to TX PDU + + void reset() { num_small_allocs.store(0, std::memory_order_relaxed); } +}; + +struct rlc_um_tx_metrics_atomic_lower { + std::atomic num_pdus_with_segmentation; ///< Number of transmitted PDUs with segmentation + std::atomic num_pdu_bytes_with_segmentation; ///< Number of transmitted PDU bytes with segmentation + + void reset() + { + num_pdus_with_segmentation.store(0, std::memory_order_relaxed); + num_pdu_bytes_with_segmentation.store(0, std::memory_order_relaxed); + } +}; + +struct rlc_am_tx_metrics_atomic_lower { + std::atomic num_pdus_with_segmentation; ///< Number of transmitted PDUs with segmentation + std::atomic num_pdu_bytes_with_segmentation; ///< Number of transmitted PDU bytes with segmentation + std::atomic num_retx_pdus; ///< Number of retransmitted PDUs + std::atomic num_retx_pdu_bytes; ///< Number of retransmitted PDU bytes + std::atomic num_ctrl_pdus; ///< Number of control PDUs + std::atomic num_ctrl_pdu_bytes; ///< Number of control PDUs bytes + + void reset() + { + num_pdus_with_segmentation.store(0, std::memory_order_relaxed); + num_pdu_bytes_with_segmentation.store(0, std::memory_order_relaxed); + num_retx_pdus.store(0, std::memory_order_relaxed); + num_retx_pdu_bytes.store(0, std::memory_order_relaxed); + num_ctrl_pdus.store(0, std::memory_order_relaxed); + num_ctrl_pdu_bytes.store(0, std::memory_order_relaxed); + } +}; + +struct rlc_tx_metrics_atomic_lower { + std::atomic num_pdus_no_segmentation; ///< Number of transmitted PDUs without segmentation + std::atomic num_pdu_bytes_no_segmentation; ///< Number of transmitted PDU bytes without segmentation + + /// RLC mode of the entity + std::atomic mode; + + /// Mode-specific metrics + /// + /// The associated union member is indicated by \c mode. + /// Contents of the other fields are undefined. + union { + rlc_tm_tx_metrics_atomic_lower tm; + rlc_um_tx_metrics_atomic_lower um; + rlc_am_tx_metrics_atomic_lower am; + } mode_specific; + + void reset() + { + num_pdus_no_segmentation.store(0, std::memory_order_relaxed); + num_pdu_bytes_no_segmentation.store(0, std::memory_order_relaxed); + + // reset mode-specific values + switch (mode.load(std::memory_order_relaxed)) { + case rlc_mode::tm: + mode_specific.tm.reset(); + break; + case rlc_mode::um_bidir: + case rlc_mode::um_unidir_dl: + mode_specific.um.reset(); + break; + case rlc_mode::am: + mode_specific.am.reset(); + break; + default: + // nothing to do here + break; + } + } +}; + class rlc_tx_metrics_container { - rlc_tx_metrics metrics = {}; - std::mutex metrics_mutex; - bool enabled = false; + rlc_tx_metrics_atomic_higher metrics_hi = {}; + rlc_tx_metrics_atomic_lower metrics_lo = {}; + bool enabled = false; public: rlc_tx_metrics_container(bool enabled_) : enabled(enabled_) {} @@ -30,127 +122,153 @@ class rlc_tx_metrics_container if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); - metrics.mode = mode; + metrics_lo.mode.store(mode, std::memory_order_relaxed); } - void metrics_add_sdus(uint32_t num_sdus_, size_t num_sdu_bytes_) + void metrics_add_sdus(uint32_t num_sdus, size_t num_sdu_bytes) { if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); - metrics.num_sdus += num_sdus_; - metrics.num_sdu_bytes += num_sdu_bytes_; + metrics_hi.num_sdus.fetch_add(num_sdus, std::memory_order_relaxed); + metrics_hi.num_sdu_bytes.fetch_add(num_sdu_bytes, std::memory_order_relaxed); } - void metrics_add_lost_sdus(uint32_t num_sdus_) + void metrics_add_lost_sdus(uint32_t num_sdus) { if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); - metrics.num_dropped_sdus += num_sdus_; + metrics_hi.num_dropped_sdus.fetch_add(num_sdus, std::memory_order_relaxed); } - void metrics_add_pdus(uint32_t num_pdus_, size_t num_pdu_bytes_) + void metrics_add_discard(uint32_t num_discarded_sdus) { if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); - metrics.num_pdus += num_pdus_; - metrics.num_pdu_bytes += num_pdu_bytes_; + metrics_hi.num_discarded_sdus.fetch_add(num_discarded_sdus, std::memory_order_relaxed); } - void metrics_add_discard(uint32_t num_discarded_sdus_) + void metrics_add_discard_failure(uint32_t num_discard_failures) { if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); - metrics.num_discarded_sdus += num_discarded_sdus_; + metrics_hi.num_discard_failures.fetch_add(num_discard_failures, std::memory_order_relaxed); } - void metrics_add_discard_failure(uint32_t num_discard_failures_) + void metrics_add_pdus_no_segmentation(uint32_t num_pdus, size_t num_pdu_bytes) { if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); - metrics.num_discard_failures += num_discard_failures_; + metrics_lo.num_pdus_no_segmentation.fetch_add(num_pdus, std::memory_order_relaxed); + metrics_lo.num_pdu_bytes_no_segmentation.fetch_add(num_pdu_bytes, std::memory_order_relaxed); } // TM specific metrics - void metrics_add_small_alloc(uint32_t num_allocs_) + void metrics_add_small_alloc(uint32_t num_allocs) { if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); - srsran_assert(metrics.mode == rlc_mode::tm, "Wrong mode for TM metrics."); - metrics.mode_specific.tm.num_small_allocs += num_allocs_; + srsran_assert(metrics_lo.mode.load(std::memory_order_relaxed) == rlc_mode::tm, "Wrong mode for TM metrics."); + metrics_lo.mode_specific.tm.num_small_allocs.fetch_add(num_allocs, std::memory_order_relaxed); } + // UM specific metrics - void metrics_add_segment(uint32_t num_segments_) + void metrics_add_pdus_with_segmentation_um(uint32_t num_pdus, size_t num_pdu_bytes) { if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); - srsran_assert(metrics.mode == rlc_mode::um_bidir || metrics.mode == rlc_mode::um_unidir_dl, - "Wrong mode for UM metrics."); - metrics.mode_specific.um.num_sdu_segments += num_segments_; + rlc_mode mode = metrics_lo.mode.load(std::memory_order_relaxed); + srsran_assert(mode == rlc_mode::um_bidir || mode == rlc_mode::um_unidir_dl, "Wrong mode for UM metrics."); + metrics_lo.mode_specific.um.num_pdus_with_segmentation.fetch_add(num_pdus, std::memory_order_relaxed); + metrics_lo.mode_specific.um.num_pdu_bytes_with_segmentation.fetch_add(num_pdu_bytes, std::memory_order_relaxed); } // AM specific metrics - void metrics_add_retx_pdus(uint32_t num_retx_, uint32_t num_retx_pdu_bytes_) + void metrics_add_pdus_with_segmentation_am(uint32_t num_pdus, size_t num_pdu_bytes) { if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); - srsran_assert(metrics.mode == rlc_mode::am, "Wrong mode for AM metrics."); - metrics.mode_specific.am.num_retx_pdus += num_retx_; - metrics.mode_specific.am.num_retx_pdu_bytes += num_retx_pdu_bytes_; - metrics.num_pdus += num_retx_; - metrics.num_pdu_bytes += num_retx_pdu_bytes_; + srsran_assert(metrics_lo.mode.load(std::memory_order_relaxed) == rlc_mode::am, "Wrong mode for AM metrics."); + metrics_lo.mode_specific.am.num_pdus_with_segmentation.fetch_add(num_pdus, std::memory_order_relaxed); + metrics_lo.mode_specific.am.num_pdu_bytes_with_segmentation.fetch_add(num_pdu_bytes, std::memory_order_relaxed); } - void metrics_add_ctrl_pdus(uint32_t num_ctrl_, uint32_t num_ctrl_pdu_bytes_) + void metrics_add_retx_pdus(uint32_t num_pdus, size_t num_pdu_bytes) { if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); - srsran_assert(metrics.mode == rlc_mode::am, "Wrong mode for AM metrics."); - metrics.mode_specific.am.num_ctrl_pdus += num_ctrl_; - metrics.mode_specific.am.num_ctrl_pdu_bytes += num_ctrl_pdu_bytes_; - metrics.num_pdus += num_ctrl_; - metrics.num_pdu_bytes += num_ctrl_pdu_bytes_; + srsran_assert(metrics_lo.mode.load(std::memory_order_relaxed) == rlc_mode::am, "Wrong mode for AM metrics."); + metrics_lo.mode_specific.am.num_retx_pdus.fetch_add(num_pdus, std::memory_order_relaxed); + metrics_lo.mode_specific.am.num_retx_pdu_bytes.fetch_add(num_pdu_bytes, std::memory_order_relaxed); } - // Metrics getters and setters - rlc_tx_metrics get_metrics() + void metrics_add_ctrl_pdus(uint32_t num_pdus, size_t num_pdu_bytes) { - srsran_assert(enabled, "Trying to get metrics, but metrics are disabled."); if (not enabled) { - return {}; + return; } - std::lock_guard lock(metrics_mutex); - return metrics; + srsran_assert(metrics_lo.mode.load(std::memory_order_relaxed) == rlc_mode::am, "Wrong mode for AM metrics."); + metrics_lo.mode_specific.am.num_ctrl_pdus.fetch_add(num_pdus, std::memory_order_relaxed); + metrics_lo.mode_specific.am.num_ctrl_pdu_bytes.fetch_add(num_pdu_bytes, std::memory_order_relaxed); } - rlc_tx_metrics get_and_reset_metrics() + // Metrics getters and setters + rlc_tx_metrics get_metrics() { srsran_assert(enabled, "Trying to get metrics, but metrics are disabled."); if (not enabled) { return {}; } - std::lock_guard lock(metrics_mutex); - rlc_tx_metrics ret = metrics; - metrics = {}; - metrics.mode = ret.mode; + rlc_tx_metrics ret; + + // Metrics accessed from higher layer + ret.num_sdus = metrics_hi.num_sdus.load(std::memory_order_relaxed); + ret.num_sdu_bytes = metrics_hi.num_sdu_bytes.load(std::memory_order_relaxed); + ret.num_dropped_sdus = metrics_hi.num_dropped_sdus.load(std::memory_order_relaxed); + ret.num_discarded_sdus = metrics_hi.num_discarded_sdus.load(std::memory_order_relaxed); + ret.num_discard_failures = metrics_hi.num_discard_failures.load(std::memory_order_relaxed); + + // Metrics accessed from lower layer + ret.num_pdus_no_segmentation = metrics_lo.num_pdus_no_segmentation.load(std::memory_order_relaxed); + ret.num_pdu_bytes_no_segmentation = metrics_lo.num_pdu_bytes_no_segmentation.load(std::memory_order_relaxed); + ret.mode = metrics_lo.mode.load(std::memory_order_relaxed); + switch (ret.mode) { + case rlc_mode::tm: + ret.mode_specific.tm.num_small_allocs = + metrics_lo.mode_specific.tm.num_small_allocs.load(std::memory_order_relaxed); + break; + case rlc_mode::um_bidir: + case rlc_mode::um_unidir_dl: + ret.mode_specific.um.num_pdus_with_segmentation = + metrics_lo.mode_specific.um.num_pdus_with_segmentation.load(std::memory_order_relaxed); + ret.mode_specific.um.num_pdu_bytes_with_segmentation = + metrics_lo.mode_specific.um.num_pdu_bytes_with_segmentation.load(std::memory_order_relaxed); + break; + case rlc_mode::am: + ret.mode_specific.am.num_pdus_with_segmentation = + metrics_lo.mode_specific.am.num_pdus_with_segmentation.load(std::memory_order_relaxed); + ret.mode_specific.am.num_pdu_bytes_with_segmentation = + metrics_lo.mode_specific.am.num_pdu_bytes_with_segmentation.load(std::memory_order_relaxed); + ret.mode_specific.am.num_retx_pdus = metrics_lo.mode_specific.am.num_retx_pdus.load(std::memory_order_relaxed); + ret.mode_specific.am.num_retx_pdu_bytes = + metrics_lo.mode_specific.am.num_retx_pdu_bytes.load(std::memory_order_relaxed); + ret.mode_specific.am.num_ctrl_pdus = metrics_lo.mode_specific.am.num_ctrl_pdus.load(std::memory_order_relaxed); + ret.mode_specific.am.num_ctrl_pdu_bytes = + metrics_lo.mode_specific.am.num_ctrl_pdu_bytes.load(std::memory_order_relaxed); + break; + default: + // nothing to do here + break; + } + return ret; } @@ -160,10 +278,19 @@ class rlc_tx_metrics_container if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); - rlc_mode tmp_mode = metrics.mode; - metrics = {}; - metrics.mode = tmp_mode; + metrics_hi.reset(); + metrics_lo.reset(); + } + + rlc_tx_metrics get_and_reset_metrics() + { + srsran_assert(enabled, "Trying to get metrics, but metrics are disabled."); + if (not enabled) { + return {}; + } + rlc_tx_metrics ret = get_metrics(); + reset_metrics(); + return ret; } }; } // namespace srsran diff --git a/lib/rlc/rlc_tx_tm_entity.cpp b/lib/rlc/rlc_tx_tm_entity.cpp index db4553a1ec..6ebdc46037 100644 --- a/lib/rlc/rlc_tx_tm_entity.cpp +++ b/lib/rlc/rlc_tx_tm_entity.cpp @@ -90,7 +90,7 @@ size_t rlc_tx_tm_entity::pull_pdu(span rlc_pdu_buf) logger.log_info(sdu.buf.begin(), sdu.buf.end(), "TX PDU. pdu_len={} grant_len={}", sdu_len, rlc_pdu_buf.size()); // Update metrics - metrics.metrics_add_pdus(1, sdu_len); + metrics.metrics_add_pdus_no_segmentation(1, sdu_len); // Push PDU into PCAP. pcap.push_pdu(pcap_context, sdu.buf); diff --git a/lib/rlc/rlc_tx_um_entity.cpp b/lib/rlc/rlc_tx_um_entity.cpp index 7d57705b88..2662870aae 100644 --- a/lib/rlc/rlc_tx_um_entity.cpp +++ b/lib/rlc/rlc_tx_um_entity.cpp @@ -161,7 +161,11 @@ size_t rlc_tx_um_entity::pull_pdu(span mac_sdu_buf) } // Update metrics - metrics.metrics_add_pdus(1, pdu_size); + if (header.si == rlc_si_field::full_sdu) { + metrics.metrics_add_pdus_no_segmentation(1, pdu_size); + } else { + metrics.metrics_add_pdus_with_segmentation_um(1, pdu_size); + } // Log state log_state(srslog::basic_levels::debug); diff --git a/tests/unittests/e2/e2sm_kpm_meas_provider_test.cpp b/tests/unittests/e2/e2sm_kpm_meas_provider_test.cpp index e4a1971a2a..bbb40399d8 100644 --- a/tests/unittests/e2/e2sm_kpm_meas_provider_test.cpp +++ b/tests/unittests/e2/e2sm_kpm_meas_provider_test.cpp @@ -127,13 +127,17 @@ rlc_metrics generate_rlc_metrics(uint32_t ue_idx, uint32_t bearer_id) rlc_metric.rx.num_lost_pdus = 1; rlc_metric.rx.num_malformed_pdus = 0; - rlc_metric.tx.num_sdus = 10; - rlc_metric.tx.num_sdu_bytes = rlc_metric.tx.num_sdus * 1000; - rlc_metric.tx.num_dropped_sdus = 1; - rlc_metric.tx.num_discarded_sdus = 0; - rlc_metric.tx.num_discard_failures = 0; - rlc_metric.tx.num_pdus = 10; - rlc_metric.tx.num_pdu_bytes = rlc_metric.tx.num_pdus * 1000; + rlc_metric.tx.mode = rlc_mode::am; + rlc_metric.tx.num_sdus = 10; + rlc_metric.tx.num_sdu_bytes = rlc_metric.tx.num_sdus * 1000; + rlc_metric.tx.num_dropped_sdus = 1; + rlc_metric.tx.num_discarded_sdus = 0; + rlc_metric.tx.num_discard_failures = 0; + rlc_metric.tx.num_pdus_no_segmentation = 8; + rlc_metric.tx.num_pdu_bytes_no_segmentation = rlc_metric.tx.num_pdus_no_segmentation * 1000; + rlc_metric.tx.mode_specific.am.num_pdus_with_segmentation = 2; + rlc_metric.tx.mode_specific.am.num_pdu_bytes_with_segmentation = + rlc_metric.tx.mode_specific.am.num_pdus_with_segmentation * 1000; return rlc_metric; } @@ -382,4 +386,4 @@ TEST_F(e2sm_kpm_meas_provider_test, e2sm_kpm_ind_e2_level_rlc_metrics) packer->handle_message(e2_msg); save_msg_pcap(gw->last_pdu); #endif -} \ No newline at end of file +} From 66b39bd37f8987c6fb1a9da84161f6d182a60b4b Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Tue, 9 Jan 2024 09:28:57 +0100 Subject: [PATCH 114/134] rlc_tx_um: configure metrics mode upon construction --- lib/rlc/rlc_tx_um_entity.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/rlc/rlc_tx_um_entity.cpp b/lib/rlc/rlc_tx_um_entity.cpp index 2662870aae..eed36a3d76 100644 --- a/lib/rlc/rlc_tx_um_entity.cpp +++ b/lib/rlc/rlc_tx_um_entity.cpp @@ -34,6 +34,8 @@ rlc_tx_um_entity::rlc_tx_um_entity(uint32_t du_index pcell_executor(pcell_executor_), pcap_context(ue_index, rb_id, config) { + metrics.metrics_set_mode(rlc_mode::um_bidir); + logger.log_info("RLC UM configured. {}", cfg); } From 1cd7c8bea462f1f472f7c9e0b4d4ef94c84aa567 Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Thu, 11 Jan 2024 16:53:40 +0100 Subject: [PATCH 115/134] rlc: update values of printed metrics --- lib/rlc/rlc_base_entity.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rlc/rlc_base_entity.h b/lib/rlc/rlc_base_entity.h index 2b656f5d17..d567295f9a 100644 --- a/lib/rlc/rlc_base_entity.h +++ b/lib/rlc/rlc_base_entity.h @@ -100,8 +100,8 @@ class rlc_base_entity : public rlc_entity m.tx.num_dropped_sdus, m.tx.num_discarded_sdus, m.tx.num_pdus_no_segmentation, - (double)m.tx.mode_specific.am.num_pdus_with_segmentation * 8 / (double)metrics_period.count(), - m.tx.num_pdus_no_segmentation, + (double)m.tx.num_pdu_bytes_no_segmentation * 8 / (double)metrics_period.count(), + m.tx.mode_specific.am.num_pdus_with_segmentation, (double)m.tx.mode_specific.am.num_pdu_bytes_with_segmentation * 8 / (double)metrics_period.count(), m.tx.mode_specific.am.num_retx_pdus, (double)m.tx.mode_specific.am.num_retx_pdu_bytes * 8 / (double)metrics_period.count(), From 722a479951d824861f36ce3f61759c3ac2c74b61 Mon Sep 17 00:00:00 2001 From: asaezper Date: Wed, 10 Jan 2024 11:53:06 +0100 Subject: [PATCH 116/134] ci: rebaser cron changed --- .gitlab/ci/schedules.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab/ci/schedules.yml b/.gitlab/ci/schedules.yml index a87f9a1d0d..2c085e23f5 100644 --- a/.gitlab/ci/schedules.yml +++ b/.gitlab/ci/schedules.yml @@ -6,7 +6,7 @@ # the distribution. # Rebaser: - cron: "*/10 6-23 * * 1-5" + cron: "*/10 6-22 * * 1-5" cron_timezone: "Europe/Madrid" ref: dev active: true From 99cd64c6385af0b74b065f80af0f4cefbc171296 Mon Sep 17 00:00:00 2001 From: asaezper Date: Wed, 10 Jan 2024 11:52:52 +0100 Subject: [PATCH 117/134] ci,e2e: new viavi config --- .gitlab/ci/e2e/.env | 2 +- tests/e2e/tests/validate_configuration.py | 19 +++++--- tests/e2e/tests/viavi.py | 21 +++++---- tests/e2e/tests/viavi/config.yml | 54 +++++++++++++++++++++++ 4 files changed, 81 insertions(+), 15 deletions(-) create mode 100644 tests/e2e/tests/viavi/config.yml diff --git a/.gitlab/ci/e2e/.env b/.gitlab/ci/e2e/.env index 5e54a4ce24..72a8ea09cc 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.38.2 +RETINA_VERSION=0.40.0 AMARISOFT_VERSION=2023-03-17 SRSUE_VERSION=23.11 OPEN5GS_VERSION=2.5.6 diff --git a/tests/e2e/tests/validate_configuration.py b/tests/e2e/tests/validate_configuration.py index 06c021e122..eeb2960326 100644 --- a/tests/e2e/tests/validate_configuration.py +++ b/tests/e2e/tests/validate_configuration.py @@ -10,6 +10,7 @@ Validate Configuration Examples """ import logging +import tempfile from pathlib import Path from pprint import pformat @@ -79,11 +80,19 @@ def run_config( Run gnb with B200 example config and validate it doesn't crash. """ - retina_data.test_config = { - "gnb": {"templates": {"main": str(Path(__file__).joinpath(f"../../../../{config_file}").resolve())}} - } - retina_manager.parse_configuration(retina_data.test_config) - retina_manager.push_all_config() + with tempfile.NamedTemporaryFile() as tmp_file: + retina_data.test_config = { + "gnb": { + "templates": { + "main": str(Path(__file__).joinpath(f"../../../../{config_file}").resolve()), + "cell": tmp_file.name, + "ru": tmp_file.name, + } + } + } + retina_manager.parse_configuration(retina_data.test_config) + retina_manager.push_all_config() + logging.info("Test config: \n%s", pformat(retina_data.test_config)) configure_artifacts( diff --git a/tests/e2e/tests/viavi.py b/tests/e2e/tests/viavi.py index 1943fc2b19..dd278bee69 100644 --- a/tests/e2e/tests/viavi.py +++ b/tests/e2e/tests/viavi.py @@ -30,10 +30,16 @@ @mark.parametrize( - "campaign_filename, test_name, test_timeout", + "campaign_filename, test_name, test_timeout, post_commands", ( - param("C:\\ci\\CI 4x4 ORAN-FH.xml", "32UE static DL + UL UDP - Dell", 45 * 60, id="32UE Bidirectional UDP"), - 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, "", 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", + id="32UE Bidirectional UDP", + ), ), ) @mark.viavi @@ -51,6 +57,7 @@ def test_viavi( campaign_filename: str, test_name: str, test_timeout: int, + post_commands: str, # Test extra params always_download_artifacts: bool = True, gnb_startup_timeout: int = GNB_STARTUP_TIMEOUT, @@ -66,14 +73,10 @@ def test_viavi( "gnb": { "parameters": { "gnb_id": 1, - "band": 78, - "dl_arfcn": 625000, - "common_scs": 30, - "bandwidth": 100, - "prach_config_index": 159, "log_level": "warning", "pcap": False, }, + "templates": {"cell": str(Path(__file__).joinpath("../viavi/config.yml").resolve())}, }, } configure_metric_server_for_gnb( @@ -95,7 +98,7 @@ def test_viavi( GNBStartInfo( plmn=PLMN(mcc="001", mnc="01"), fivegc_definition=FiveGCDefinition(amf_ip=amf_ip, amf_port=amf_port), - start_info=StartInfo(timeout=gnb_startup_timeout), + start_info=StartInfo(timeout=gnb_startup_timeout, post_commands=post_commands), ) ) diff --git a/tests/e2e/tests/viavi/config.yml b/tests/e2e/tests/viavi/config.yml new file mode 100644 index 0000000000..4ac1583819 --- /dev/null +++ b/tests/e2e/tests/viavi/config.yml @@ -0,0 +1,54 @@ +# +# 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. +# + +cu_cp: + ue_context_setup_timeout_s: 5 + inactivity_timer: 5 + rrc: + force_reestablishment_fallback: true + +cell_cfg: + dl_arfcn: 625000 + band: 78 + channel_bandwidth_MHz: 100 + common_scs: 30 + plmn: "{{mcc}}{{mnc}}" + tac: 7 + pci: 1 + sib: + t301: 2000 + t311: 3000 + prach: + prach_config_index: 159 + prach_root_sequence_index: 1 + zero_correlation_zone: 0 + prach_frequency_start: 12 + pucch: + sr_period_ms: 10 + f1_nof_cell_res_sr: 30 + min_k1: 2 + csi: + csi_rs_period: 40 + pdsch: + mcs_table: qam256 + max_alloc_attempts: 8 + max_pdschs_per_slot: 8 + # max_rb_size: 45 # <-- enable this only for 32UE + ul_common: + max_ul_grants_per_slot: 16 + max_pucchs_per_slot: 14 + pusch: + 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 + nof_ul_slots: 2 From dbf1910954b76596d056fa879d0d69365986eaa0 Mon Sep 17 00:00:00 2001 From: asaezper Date: Thu, 11 Jan 2024 13:05:52 +0100 Subject: [PATCH 118/134] license: year update --- .gdbinit | 2 +- .gitlab/ci/e2e/.env | 2 +- .gitlab/ci/release/auto_merge.sh | 2 +- .gitlab/ci/release/update_headers.sh | 2 +- CMakeLists.txt | 2 +- COPYRIGHT | 4 ++-- apps/CMakeLists.txt | 2 +- apps/examples/CMakeLists.txt | 2 +- apps/examples/du/CMakeLists.txt | 2 +- apps/examples/du/du_example.cpp | 2 +- apps/examples/du/fapi_factory.cpp | 2 +- apps/examples/du/fapi_factory.h | 2 +- apps/examples/du/phy_factory.cpp | 2 +- apps/examples/du/phy_factory.h | 2 +- apps/examples/du/radio_notifier_sample.h | 2 +- apps/examples/phy/CMakeLists.txt | 2 +- apps/examples/phy/lower_phy_example_factory.cpp | 2 +- apps/examples/phy/lower_phy_example_factory.h | 2 +- apps/examples/phy/radio_ssb.cpp | 2 +- apps/examples/phy/rx_symbol_handler_example.h | 2 +- apps/examples/phy/upper_phy_ssb_example.cpp | 2 +- apps/examples/phy/upper_phy_ssb_example.h | 2 +- apps/examples/radio/CMakeLists.txt | 2 +- apps/examples/radio/radio_notifier_sample.h | 2 +- apps/examples/radio/radio_util_sample.cpp | 2 +- apps/gnb/CMakeLists.txt | 2 +- apps/gnb/adapters/e1ap_gateway_local_connector.cpp | 2 +- apps/gnb/adapters/e1ap_gateway_local_connector.h | 2 +- apps/gnb/adapters/e2_gateway_remote_connector.cpp | 2 +- apps/gnb/adapters/e2_gateway_remote_connector.h | 2 +- apps/gnb/adapters/e2ap_adapter.h | 2 +- apps/gnb/adapters/f1c_gateway_local_connector.cpp | 2 +- apps/gnb/adapters/f1c_gateway_local_connector.h | 2 +- apps/gnb/adapters/ngap_adapter.h | 2 +- apps/gnb/gnb.cpp | 2 +- apps/gnb/gnb_appconfig.h | 2 +- apps/gnb/gnb_appconfig_cli11_schema.cpp | 2 +- apps/gnb/gnb_appconfig_cli11_schema.h | 2 +- apps/gnb/gnb_appconfig_translators.cpp | 2 +- apps/gnb/gnb_appconfig_translators.h | 2 +- apps/gnb/gnb_appconfig_validators.cpp | 2 +- apps/gnb/gnb_appconfig_validators.h | 2 +- apps/gnb/gnb_du_factory.cpp | 2 +- apps/gnb/gnb_du_factory.h | 2 +- apps/gnb/gnb_e2_metric_connector_manager.cpp | 2 +- apps/gnb/gnb_e2_metric_connector_manager.h | 2 +- apps/gnb/gnb_os_sched_affinity_manager.h | 2 +- apps/gnb/gnb_worker_manager.cpp | 2 +- apps/gnb/gnb_worker_manager.h | 2 +- apps/gnb/helpers/gnb_console_helper.cpp | 2 +- apps/gnb/helpers/gnb_console_helper.h | 2 +- apps/gnb/helpers/metrics_hub.cpp | 2 +- apps/gnb/helpers/metrics_hub.h | 2 +- apps/gnb/helpers/metrics_plotter_json.cpp | 2 +- apps/gnb/helpers/metrics_plotter_json.h | 2 +- apps/gnb/helpers/metrics_plotter_stdout.cpp | 2 +- apps/gnb/helpers/metrics_plotter_stdout.h | 2 +- apps/gnb/helpers/rlc_metrics_plotter_json.cpp | 2 +- apps/gnb/helpers/rlc_metrics_plotter_json.h | 2 +- apps/gnb/helpers/string_helpers.h | 2 +- apps/gnb/radio_notifier_sample.h | 2 +- cmake/modules/FindDPDK.cmake | 2 +- cmake/modules/FindFFTW3F.cmake | 2 +- cmake/modules/FindMbedTLS.cmake | 2 +- cmake/modules/FindSCTP.cmake | 2 +- cmake/modules/FindSSE.cmake | 2 +- cmake/modules/FindTRX_DRIVER.cmake | 2 +- cmake/modules/FindUHD.cmake | 2 +- cmake/modules/FindYAMLCPP.cmake | 2 +- cmake/modules/FindZeroMQ.cmake | 2 +- cmake/modules/version.cmake | 2 +- configs/CMakeLists.txt | 2 +- docker/Dockerfile | 2 +- docker/docker-compose.yml | 2 +- docker/metrics_server/Dockerfile | 2 +- docker/metrics_server/pyproject.toml | 2 +- docker/open5gs/Dockerfile | 2 +- docs/CMakeLists.txt | 2 +- docs/acronyms.dox | 2 +- docs/fail.html | 2 +- docs/header.html | 2 +- docs/index.html | 2 +- docs/main.dox | 2 +- docs/math_macros.tex | 2 +- external/CMakeLists.txt | 2 +- external/fmt/CMakeLists.txt | 2 +- include/srsran/adt/bit_buffer.h | 2 +- include/srsran/adt/bitmap_utils.h | 2 +- include/srsran/adt/blocking_queue.h | 2 +- include/srsran/adt/bounded_bitset.h | 2 +- include/srsran/adt/bounded_integer.h | 2 +- include/srsran/adt/byte_buffer.h | 2 +- include/srsran/adt/byte_buffer_chain.h | 2 +- include/srsran/adt/circular_array.h | 2 +- include/srsran/adt/complex.h | 2 +- include/srsran/adt/concurrent_queue.h | 2 +- include/srsran/adt/detail/byte_buffer_range_helpers.h | 2 +- include/srsran/adt/detail/byte_buffer_segment.h | 2 +- include/srsran/adt/detail/byte_buffer_segment_list.h | 2 +- include/srsran/adt/detail/byte_buffer_segment_pool.h | 2 +- include/srsran/adt/detail/tuple_utils.h | 2 +- include/srsran/adt/expected.h | 2 +- include/srsran/adt/filter_view.h | 2 +- include/srsran/adt/interval.h | 2 +- include/srsran/adt/intrusive_list.h | 2 +- include/srsran/adt/optional.h | 2 +- include/srsran/adt/ring_buffer.h | 2 +- include/srsran/adt/scope_exit.h | 2 +- include/srsran/adt/slotted_array.h | 2 +- include/srsran/adt/span.h | 2 +- include/srsran/adt/static_vector.h | 2 +- include/srsran/adt/strong_type.h | 2 +- include/srsran/adt/tensor.h | 2 +- include/srsran/adt/tiny_optional.h | 2 +- include/srsran/adt/unique_function.h | 2 +- include/srsran/adt/variant.h | 2 +- include/srsran/asn1/asn1_utils.h | 2 +- include/srsran/asn1/e1ap/e1ap.h | 2 +- include/srsran/asn1/e2ap/e2ap.h | 2 +- include/srsran/asn1/e2ap/e2sm_rc.h | 2 +- include/srsran/asn1/f1ap/common.h | 2 +- include/srsran/asn1/f1ap/f1ap.h | 2 +- include/srsran/asn1/f1ap/f1ap_ies.h | 2 +- include/srsran/asn1/f1ap/f1ap_pdu_contents.h | 2 +- include/srsran/asn1/f1ap/f1ap_pdu_contents_ue.h | 2 +- include/srsran/asn1/f1ap/f1ap_pdu_items.h | 2 +- include/srsran/asn1/ngap/common.h | 2 +- include/srsran/asn1/ngap/ngap.h | 2 +- include/srsran/asn1/ngap/ngap_ies.h | 2 +- include/srsran/asn1/ngap/ngap_pdu_contents.h | 2 +- include/srsran/asn1/rrc_nr/cell_group_config.h | 2 +- include/srsran/asn1/rrc_nr/common.h | 2 +- include/srsran/asn1/rrc_nr/dl_dcch_msg.h | 2 +- include/srsran/asn1/rrc_nr/msg_common.h | 2 +- include/srsran/asn1/rrc_nr/nr_sidelink_preconf.h | 2 +- include/srsran/asn1/rrc_nr/nr_ue_variables.h | 2 +- include/srsran/asn1/rrc_nr/pc5_rrc_definitions.h | 2 +- include/srsran/asn1/rrc_nr/rrc_nr.h | 2 +- include/srsran/asn1/rrc_nr/serving_cell.h | 2 +- include/srsran/asn1/rrc_nr/ue_cap.h | 2 +- include/srsran/asn1/rrc_nr/ul_dcch_msg.h | 2 +- include/srsran/cu_cp/cell_meas_manager.h | 2 +- include/srsran/cu_cp/cell_meas_manager_config.h | 2 +- include/srsran/cu_cp/cu_cp.h | 2 +- include/srsran/cu_cp/cu_cp_configuration.h | 2 +- include/srsran/cu_cp/cu_cp_configuration_helpers.h | 2 +- include/srsran/cu_cp/cu_cp_factory.h | 2 +- include/srsran/cu_cp/cu_cp_types.h | 2 +- include/srsran/cu_cp/cu_cp_ue_messages.h | 2 +- include/srsran/cu_cp/cu_up_processor.h | 2 +- include/srsran/cu_cp/cu_up_processor_config.h | 2 +- include/srsran/cu_cp/cu_up_processor_context.h | 2 +- include/srsran/cu_cp/cu_up_repository.h | 2 +- include/srsran/cu_cp/du_processor.h | 2 +- include/srsran/cu_cp/du_processor_config.h | 2 +- include/srsran/cu_cp/du_processor_context.h | 2 +- include/srsran/cu_cp/du_repository.h | 2 +- include/srsran/cu_cp/mobility_manager.h | 2 +- include/srsran/cu_cp/mobility_manager_config.h | 2 +- include/srsran/cu_cp/ue_manager.h | 2 +- include/srsran/cu_cp/up_resource_manager.h | 2 +- include/srsran/cu_up/cu_up.h | 2 +- include/srsran/cu_up/cu_up_configuration.h | 2 +- include/srsran/cu_up/cu_up_configuration_helpers.h | 2 +- include/srsran/cu_up/cu_up_executor_pool.h | 2 +- include/srsran/cu_up/cu_up_factory.h | 2 +- include/srsran/cu_up/cu_up_types.h | 2 +- include/srsran/du/du.h | 2 +- include/srsran/du/du_cell_config.h | 2 +- include/srsran/du/du_cell_config_helpers.h | 2 +- include/srsran/du/du_cell_config_validation.h | 2 +- include/srsran/du/du_config.h | 2 +- include/srsran/du/du_factory.h | 2 +- include/srsran/du/du_low_config.h | 2 +- include/srsran/du/du_qos_config.h | 2 +- include/srsran/du/du_srb_config.h | 2 +- include/srsran/du/du_test_config.h | 2 +- include/srsran/du/du_update_config_helpers.h | 2 +- include/srsran/du_high/du_high.h | 2 +- include/srsran/du_high/du_high_factory.h | 2 +- include/srsran/du_high/rnti_value_table.h | 2 +- include/srsran/du_manager/du_configurator.h | 2 +- include/srsran/du_manager/du_manager_factory.h | 2 +- include/srsran/du_manager/du_manager_params.h | 2 +- include/srsran/e1ap/common/e1_setup_messages.h | 2 +- include/srsran/e1ap/common/e1ap_common.h | 2 +- include/srsran/e1ap/common/e1ap_message.h | 2 +- include/srsran/e1ap/common/e1ap_types.h | 2 +- include/srsran/e1ap/cu_cp/e1ap_cu_cp.h | 2 +- include/srsran/e1ap/cu_cp/e1ap_cu_cp_bearer_context_update.h | 2 +- include/srsran/e1ap/cu_cp/e1ap_cu_cp_factory.h | 2 +- include/srsran/e1ap/cu_up/e1ap_config_converters.h | 2 +- include/srsran/e1ap/cu_up/e1ap_connection_client.h | 2 +- include/srsran/e1ap/cu_up/e1ap_cu_up.h | 2 +- include/srsran/e1ap/cu_up/e1ap_cu_up_bearer_context_update.h | 2 +- include/srsran/e1ap/cu_up/e1ap_cu_up_factory.h | 2 +- include/srsran/e2/e2.h | 2 +- include/srsran/e2/e2_connection_client.h | 2 +- include/srsran/e2/e2_du_metrics_connector.h | 2 +- include/srsran/e2/e2_event_manager.h | 2 +- include/srsran/e2/e2_factory.h | 2 +- include/srsran/e2/e2_messages.h | 2 +- include/srsran/e2/e2ap_configuration.h | 2 +- include/srsran/e2/e2ap_configuration_helpers.h | 2 +- include/srsran/e2/e2sm/e2sm.h | 2 +- include/srsran/e2/e2sm/e2sm_factory.h | 2 +- include/srsran/e2/e2sm/e2sm_kpm.h | 2 +- include/srsran/e2/e2sm/e2sm_manager.h | 2 +- include/srsran/e2/e2sm/e2sm_rc.h | 2 +- include/srsran/e2/subscription/e2_subscription.h | 2 +- include/srsran/f1ap/common/f1ap_common.h | 2 +- include/srsran/f1ap/common/f1ap_message.h | 2 +- include/srsran/f1ap/common/f1ap_ue_id.h | 2 +- include/srsran/f1ap/cu_cp/f1ap_cu.h | 2 +- include/srsran/f1ap/cu_cp/f1ap_cu_factory.h | 2 +- include/srsran/f1ap/cu_cp/f1ap_cu_ue_context_update.h | 2 +- include/srsran/f1ap/cu_cp/f1ap_interface_management_types.h | 2 +- include/srsran/f1ap/du/f1ap_du.h | 2 +- include/srsran/f1ap/du/f1ap_du_connection_manager.h | 2 +- include/srsran/f1ap/du/f1ap_du_ue_config.h | 2 +- include/srsran/f1ap/du/f1ap_du_ue_context_update.h | 2 +- include/srsran/f1ap/du/f1c_bearer.h | 2 +- include/srsran/f1ap/du/f1c_connection_client.h | 2 +- include/srsran/f1ap/du/f1c_rx_sdu_notifier.h | 2 +- include/srsran/f1u/common/nru_message.h | 2 +- include/srsran/f1u/cu_up/f1u_bearer.h | 2 +- include/srsran/f1u/cu_up/f1u_bearer_factory.h | 2 +- include/srsran/f1u/cu_up/f1u_bearer_logger.h | 2 +- include/srsran/f1u/cu_up/f1u_gateway.h | 2 +- include/srsran/f1u/cu_up/f1u_rx_delivery_notifier.h | 2 +- include/srsran/f1u/cu_up/f1u_rx_pdu_handler.h | 2 +- include/srsran/f1u/cu_up/f1u_rx_sdu_notifier.h | 2 +- include/srsran/f1u/cu_up/f1u_tx_pdu_notifier.h | 2 +- include/srsran/f1u/cu_up/f1u_tx_sdu_handler.h | 2 +- include/srsran/f1u/du/f1u_bearer.h | 2 +- include/srsran/f1u/du/f1u_bearer_factory.h | 2 +- include/srsran/f1u/du/f1u_bearer_logger.h | 2 +- include/srsran/f1u/du/f1u_config.h | 2 +- include/srsran/f1u/du/f1u_gateway.h | 2 +- include/srsran/f1u/du/f1u_rx_pdu_handler.h | 2 +- include/srsran/f1u/du/f1u_rx_sdu_notifier.h | 2 +- include/srsran/f1u/du/f1u_tx_delivery_handler.h | 2 +- include/srsran/f1u/du/f1u_tx_pdu_notifier.h | 2 +- include/srsran/f1u/du/f1u_tx_sdu_handler.h | 2 +- include/srsran/f1u/f1u_cu_up_entity.h | 2 +- include/srsran/f1u/f1u_cu_up_rx.h | 2 +- include/srsran/f1u/f1u_cu_up_transport.h | 2 +- include/srsran/f1u/f1u_cu_up_tx.h | 2 +- include/srsran/f1u/local_connector/f1u_local_bearer_adapter.h | 2 +- include/srsran/f1u/local_connector/f1u_local_connector.h | 2 +- include/srsran/fapi/config_message_gateway.h | 2 +- include/srsran/fapi/config_message_notifier.h | 2 +- include/srsran/fapi/logging_decorator_factories.h | 2 +- include/srsran/fapi/message_builders.h | 2 +- include/srsran/fapi/message_validators.h | 2 +- include/srsran/fapi/messages.h | 2 +- include/srsran/fapi/slot_data_message_notifier.h | 2 +- include/srsran/fapi/slot_error_message_notifier.h | 2 +- include/srsran/fapi/slot_last_message_notifier.h | 2 +- include/srsran/fapi/slot_message_gateway.h | 2 +- include/srsran/fapi/slot_time_message_notifier.h | 2 +- include/srsran/fapi/validator_report.h | 2 +- include/srsran/fapi_adaptor/mac/mac_fapi_adaptor.h | 2 +- include/srsran/fapi_adaptor/mac/mac_fapi_adaptor_factory.h | 2 +- include/srsran/fapi_adaptor/mac/messages/pdcch.h | 2 +- include/srsran/fapi_adaptor/mac/messages/pdsch.h | 2 +- include/srsran/fapi_adaptor/mac/messages/prach.h | 2 +- include/srsran/fapi_adaptor/mac/messages/pucch.h | 2 +- include/srsran/fapi_adaptor/mac/messages/pusch.h | 2 +- include/srsran/fapi_adaptor/mac/messages/ssb.h | 2 +- include/srsran/fapi_adaptor/phy/messages/csi_rs.h | 2 +- include/srsran/fapi_adaptor/phy/messages/pdcch.h | 2 +- include/srsran/fapi_adaptor/phy/messages/pdsch.h | 2 +- include/srsran/fapi_adaptor/phy/messages/prach.h | 2 +- include/srsran/fapi_adaptor/phy/messages/pucch.h | 2 +- include/srsran/fapi_adaptor/phy/messages/pusch.h | 2 +- include/srsran/fapi_adaptor/phy/messages/ssb.h | 2 +- include/srsran/fapi_adaptor/phy/phy_fapi_adaptor.h | 2 +- include/srsran/fapi_adaptor/phy/phy_fapi_adaptor_factory.h | 2 +- include/srsran/fapi_adaptor/precoding_matrix_mapper.h | 2 +- include/srsran/fapi_adaptor/precoding_matrix_repository.h | 2 +- .../srsran/fapi_adaptor/precoding_matrix_table_generator.h | 2 +- .../srsran/fapi_adaptor/uci_part2_correspondence_generator.h | 2 +- include/srsran/fapi_adaptor/uci_part2_correspondence_mapper.h | 2 +- .../srsran/fapi_adaptor/uci_part2_correspondence_repository.h | 2 +- include/srsran/gateways/addr_info.h | 2 +- include/srsran/gateways/baseband/baseband_gateway_base.h | 2 +- include/srsran/gateways/baseband/baseband_gateway_receiver.h | 2 +- include/srsran/gateways/baseband/baseband_gateway_timestamp.h | 2 +- .../srsran/gateways/baseband/baseband_gateway_transmitter.h | 2 +- .../gateways/baseband/baseband_gateway_transmitter_metadata.h | 2 +- .../baseband/buffer/baseband_gateway_buffer_dynamic.h | 2 +- .../gateways/baseband/buffer/baseband_gateway_buffer_reader.h | 2 +- .../baseband/buffer/baseband_gateway_buffer_reader_view.h | 2 +- .../gateways/baseband/buffer/baseband_gateway_buffer_writer.h | 2 +- .../baseband/buffer/baseband_gateway_buffer_writer_view.h | 2 +- include/srsran/gateways/network_gateway.h | 2 +- include/srsran/gateways/sctp_network_gateway.h | 2 +- include/srsran/gateways/sctp_network_gateway_factory.h | 2 +- include/srsran/gateways/udp_network_gateway.h | 2 +- include/srsran/gateways/udp_network_gateway_factory.h | 2 +- include/srsran/gtpu/gtpu_config.h | 2 +- include/srsran/gtpu/gtpu_demux.h | 2 +- include/srsran/gtpu/gtpu_demux_factory.h | 2 +- include/srsran/gtpu/gtpu_echo.h | 2 +- include/srsran/gtpu/gtpu_echo_factory.h | 2 +- include/srsran/gtpu/gtpu_echo_tx.h | 2 +- include/srsran/gtpu/gtpu_teid.h | 2 +- include/srsran/gtpu/gtpu_teid_pool.h | 2 +- include/srsran/gtpu/gtpu_teid_pool_factory.h | 2 +- include/srsran/gtpu/gtpu_tunnel_ngu.h | 2 +- include/srsran/gtpu/gtpu_tunnel_ngu_factory.h | 2 +- include/srsran/gtpu/gtpu_tunnel_rx.h | 2 +- include/srsran/gtpu/gtpu_tunnel_tx.h | 2 +- include/srsran/hal/dpdk/bbdev/bbdev_acc.h | 2 +- include/srsran/hal/dpdk/bbdev/bbdev_acc_factory.h | 2 +- include/srsran/hal/dpdk/bbdev/bbdev_op_pool.h | 2 +- include/srsran/hal/dpdk/bbdev/bbdev_op_pool_factory.h | 2 +- include/srsran/hal/dpdk/dpdk_eal.h | 2 +- include/srsran/hal/dpdk/dpdk_eal_factory.h | 2 +- include/srsran/hal/dpdk/mbuf_pool.h | 2 +- include/srsran/hal/dpdk/mbuf_pool_factory.h | 2 +- include/srsran/hal/hw_accelerator.h | 2 +- .../pusch/ext_harq_buffer_context_repository.h | 2 +- .../pusch/ext_harq_buffer_context_repository_factory.h | 2 +- .../hal/phy/upper/channel_processors/pusch/hal_factories.h | 2 +- .../upper/channel_processors/pusch/hw_accelerator_pusch_dec.h | 2 +- .../pusch/hw_accelerator_pusch_dec_factory.h | 2 +- include/srsran/instrumentation/traces/du_traces.h | 2 +- include/srsran/instrumentation/traces/ru_traces.h | 2 +- include/srsran/instrumentation/traces/up_traces.h | 2 +- include/srsran/mac/bsr_format.h | 2 +- include/srsran/mac/cell_configuration.h | 2 +- include/srsran/mac/config/mac_cell_group_config_factory.h | 2 +- include/srsran/mac/config/mac_config_helpers.h | 2 +- include/srsran/mac/lcid_dl_sch.h | 2 +- include/srsran/mac/mac.h | 2 +- include/srsran/mac/mac_cell_control_information_handler.h | 2 +- include/srsran/mac/mac_cell_group_config.h | 2 +- include/srsran/mac/mac_cell_rach_handler.h | 2 +- include/srsran/mac/mac_config.h | 2 +- include/srsran/mac/mac_factory.h | 2 +- include/srsran/mac/mac_lc_config.h | 2 +- include/srsran/mac/mac_paging_information_handler.h | 2 +- include/srsran/mac/mac_pdu_format.h | 2 +- include/srsran/mac/mac_ue_configurator.h | 2 +- include/srsran/mac/mac_ue_control_information_handler.h | 2 +- include/srsran/mac/phr_config.h | 2 +- include/srsran/mac/phr_report.h | 2 +- include/srsran/mac/time_alignment_group_config.h | 2 +- include/srsran/ngap/ngap.h | 2 +- include/srsran/ngap/ngap_configuration.h | 2 +- include/srsran/ngap/ngap_configuration_helpers.h | 2 +- include/srsran/ngap/ngap_factory.h | 2 +- include/srsran/ngap/ngap_handover.h | 2 +- include/srsran/ngap/ngap_init_context_setup.h | 2 +- include/srsran/ngap/ngap_setup.h | 2 +- include/srsran/ngap/ngap_types.h | 2 +- include/srsran/ofh/compression/compressed_prb.h | 2 +- include/srsran/ofh/compression/compression_factory.h | 2 +- include/srsran/ofh/compression/compression_params.h | 2 +- include/srsran/ofh/compression/iq_compressor.h | 2 +- include/srsran/ofh/compression/iq_decompressor.h | 2 +- include/srsran/ofh/ecpri/ecpri_constants.h | 2 +- include/srsran/ofh/ecpri/ecpri_factories.h | 2 +- include/srsran/ofh/ecpri/ecpri_packet_builder.h | 2 +- include/srsran/ofh/ecpri/ecpri_packet_decoder.h | 2 +- include/srsran/ofh/ecpri/ecpri_packet_properties.h | 2 +- include/srsran/ofh/ethernet/ethernet_factories.h | 2 +- include/srsran/ofh/ethernet/ethernet_frame_notifier.h | 2 +- include/srsran/ofh/ethernet/ethernet_frame_pool.h | 2 +- include/srsran/ofh/ethernet/ethernet_gateway.h | 2 +- include/srsran/ofh/ethernet/ethernet_gw_config.h | 2 +- include/srsran/ofh/ethernet/ethernet_mac_address.h | 2 +- include/srsran/ofh/ethernet/ethernet_properties.h | 2 +- include/srsran/ofh/ethernet/ethernet_receiver.h | 2 +- include/srsran/ofh/ethernet/vlan_ethernet_frame_builder.h | 2 +- include/srsran/ofh/ethernet/vlan_ethernet_frame_decoder.h | 2 +- include/srsran/ofh/ethernet/vlan_ethernet_frame_params.h | 2 +- include/srsran/ofh/ofh_constants.h | 2 +- include/srsran/ofh/ofh_controller.h | 2 +- include/srsran/ofh/ofh_factories.h | 2 +- include/srsran/ofh/ofh_sector.h | 2 +- include/srsran/ofh/ofh_sector_config.h | 2 +- include/srsran/ofh/ofh_uplane_rx_symbol_notifier.h | 2 +- include/srsran/ofh/receiver/ofh_receiver.h | 2 +- include/srsran/ofh/receiver/ofh_receiver_configuration.h | 2 +- include/srsran/ofh/receiver/ofh_receiver_timing_parameters.h | 2 +- include/srsran/ofh/serdes/ofh_cplane_message_builder.h | 2 +- include/srsran/ofh/serdes/ofh_cplane_message_properties.h | 2 +- include/srsran/ofh/serdes/ofh_message_decoder_properties.h | 2 +- include/srsran/ofh/serdes/ofh_message_properties.h | 2 +- include/srsran/ofh/serdes/ofh_serdes_factories.h | 2 +- include/srsran/ofh/serdes/ofh_uplane_message_builder.h | 2 +- include/srsran/ofh/serdes/ofh_uplane_message_decoder.h | 2 +- .../srsran/ofh/serdes/ofh_uplane_message_decoder_properties.h | 2 +- include/srsran/ofh/serdes/ofh_uplane_message_properties.h | 2 +- include/srsran/ofh/timing/ofh_ota_symbol_boundary_notifier.h | 2 +- .../ofh/timing/ofh_ota_symbol_boundary_notifier_manager.h | 2 +- include/srsran/ofh/timing/ofh_timing_manager.h | 2 +- include/srsran/ofh/timing/slot_symbol_point.h | 2 +- include/srsran/ofh/transmitter/ofh_downlink_handler.h | 2 +- include/srsran/ofh/transmitter/ofh_transmitter.h | 2 +- .../srsran/ofh/transmitter/ofh_transmitter_configuration.h | 2 +- include/srsran/ofh/transmitter/ofh_uplink_request_handler.h | 2 +- include/srsran/pcap/dlt_pcap.h | 2 +- include/srsran/pcap/mac_pcap.h | 2 +- include/srsran/pcap/rlc_pcap.h | 2 +- include/srsran/pdcp/pdcp_config.h | 2 +- include/srsran/pdcp/pdcp_entity.h | 2 +- include/srsran/pdcp/pdcp_factory.h | 2 +- include/srsran/pdcp/pdcp_rx.h | 2 +- include/srsran/pdcp/pdcp_rx_metrics.h | 2 +- include/srsran/pdcp/pdcp_tx.h | 2 +- include/srsran/pdcp/pdcp_tx_metrics.h | 2 +- include/srsran/pdcp/pdcp_tx_pdu.h | 2 +- include/srsran/phy/adapters/phy_error_adapter.h | 2 +- include/srsran/phy/adapters/phy_rg_gateway_adapter.h | 2 +- include/srsran/phy/adapters/phy_rx_symbol_adapter.h | 2 +- include/srsran/phy/adapters/phy_rx_symbol_request_adapter.h | 2 +- include/srsran/phy/adapters/phy_timing_adapter.h | 2 +- include/srsran/phy/constants.h | 2 +- include/srsran/phy/generic_functions/dft_processor.h | 2 +- .../phy/generic_functions/generic_functions_factories.h | 2 +- .../srsran/phy/generic_functions/precoding/channel_precoder.h | 2 +- .../phy/generic_functions/precoding/precoding_factories.h | 2 +- .../phy/lower/amplitude_controller/amplitude_controller.h | 2 +- .../amplitude_controller/amplitude_controller_factories.h | 2 +- include/srsran/phy/lower/lower_phy.h | 2 +- include/srsran/phy/lower/lower_phy_configuration.h | 2 +- include/srsran/phy/lower/lower_phy_controller.h | 2 +- include/srsran/phy/lower/lower_phy_error_notifier.h | 2 +- include/srsran/phy/lower/lower_phy_factory.h | 2 +- include/srsran/phy/lower/lower_phy_request_handler.h | 2 +- include/srsran/phy/lower/lower_phy_rg_handler.h | 2 +- include/srsran/phy/lower/lower_phy_rx_symbol_context.h | 2 +- include/srsran/phy/lower/lower_phy_rx_symbol_notifier.h | 2 +- include/srsran/phy/lower/lower_phy_timing_context.h | 2 +- include/srsran/phy/lower/lower_phy_timing_notifier.h | 2 +- include/srsran/phy/lower/modulation/modulation_factories.h | 2 +- include/srsran/phy/lower/modulation/ofdm_demodulator.h | 2 +- include/srsran/phy/lower/modulation/ofdm_modulator.h | 2 +- include/srsran/phy/lower/modulation/ofdm_prach_demodulator.h | 2 +- .../srsran/phy/lower/processors/downlink/downlink_processor.h | 2 +- .../lower/processors/downlink/downlink_processor_baseband.h | 2 +- .../lower/processors/downlink/downlink_processor_factories.h | 2 +- .../lower/processors/downlink/downlink_processor_notifier.h | 2 +- .../phy/lower/processors/downlink/pdxch/pdxch_processor.h | 2 +- .../processors/downlink/pdxch/pdxch_processor_baseband.h | 2 +- .../processors/downlink/pdxch/pdxch_processor_factories.h | 2 +- .../processors/downlink/pdxch/pdxch_processor_notifier.h | 2 +- .../downlink/pdxch/pdxch_processor_request_handler.h | 2 +- .../phy/lower/processors/uplink/prach/prach_processor.h | 2 +- .../lower/processors/uplink/prach/prach_processor_baseband.h | 2 +- .../lower/processors/uplink/prach/prach_processor_factories.h | 2 +- .../lower/processors/uplink/prach/prach_processor_notifier.h | 2 +- .../processors/uplink/prach/prach_processor_request_handler.h | 2 +- .../phy/lower/processors/uplink/puxch/puxch_processor.h | 2 +- .../lower/processors/uplink/puxch/puxch_processor_baseband.h | 2 +- .../lower/processors/uplink/puxch/puxch_processor_factories.h | 2 +- .../lower/processors/uplink/puxch/puxch_processor_notifier.h | 2 +- .../processors/uplink/puxch/puxch_processor_request_handler.h | 2 +- include/srsran/phy/lower/processors/uplink/uplink_processor.h | 2 +- .../phy/lower/processors/uplink/uplink_processor_baseband.h | 2 +- .../phy/lower/processors/uplink/uplink_processor_factories.h | 2 +- .../phy/lower/processors/uplink/uplink_processor_notifier.h | 2 +- include/srsran/phy/lower/sampling_rate.h | 2 +- include/srsran/phy/support/interpolator.h | 2 +- include/srsran/phy/support/mask_types.h | 2 +- include/srsran/phy/support/prach_buffer.h | 2 +- include/srsran/phy/support/prach_buffer_context.h | 2 +- include/srsran/phy/support/prach_buffer_pool.h | 2 +- include/srsran/phy/support/precoding_configuration.h | 2 +- include/srsran/phy/support/precoding_formatters.h | 2 +- include/srsran/phy/support/re_buffer.h | 2 +- include/srsran/phy/support/re_pattern.h | 2 +- include/srsran/phy/support/re_pattern_formatters.h | 2 +- include/srsran/phy/support/resource_grid.h | 2 +- include/srsran/phy/support/resource_grid_base.h | 2 +- include/srsran/phy/support/resource_grid_context.h | 2 +- include/srsran/phy/support/resource_grid_mapper.h | 2 +- include/srsran/phy/support/resource_grid_pool.h | 2 +- include/srsran/phy/support/resource_grid_reader.h | 2 +- include/srsran/phy/support/resource_grid_reader_empty.h | 2 +- include/srsran/phy/support/resource_grid_writer.h | 2 +- include/srsran/phy/support/support_factories.h | 2 +- include/srsran/phy/support/support_formatters.h | 2 +- .../phy/upper/channel_coding/channel_coding_factories.h | 2 +- include/srsran/phy/upper/channel_coding/crc_calculator.h | 2 +- include/srsran/phy/upper/channel_coding/ldpc/ldpc.h | 2 +- include/srsran/phy/upper/channel_coding/ldpc/ldpc_decoder.h | 2 +- include/srsran/phy/upper/channel_coding/ldpc/ldpc_encoder.h | 2 +- .../phy/upper/channel_coding/ldpc/ldpc_rate_dematcher.h | 2 +- .../srsran/phy/upper/channel_coding/ldpc/ldpc_rate_matcher.h | 2 +- .../srsran/phy/upper/channel_coding/ldpc/ldpc_segmenter_rx.h | 2 +- .../srsran/phy/upper/channel_coding/ldpc/ldpc_segmenter_tx.h | 2 +- .../srsran/phy/upper/channel_coding/polar/polar_allocator.h | 2 +- include/srsran/phy/upper/channel_coding/polar/polar_code.h | 2 +- .../srsran/phy/upper/channel_coding/polar/polar_deallocator.h | 2 +- include/srsran/phy/upper/channel_coding/polar/polar_decoder.h | 2 +- include/srsran/phy/upper/channel_coding/polar/polar_encoder.h | 2 +- .../srsran/phy/upper/channel_coding/polar/polar_interleaver.h | 2 +- .../phy/upper/channel_coding/polar/polar_rate_dematcher.h | 2 +- .../phy/upper/channel_coding/polar/polar_rate_matcher.h | 2 +- .../phy/upper/channel_coding/short/short_block_detector.h | 2 +- .../phy/upper/channel_coding/short/short_block_encoder.h | 2 +- include/srsran/phy/upper/channel_estimation.h | 2 +- .../upper/channel_modulation/channel_modulation_factories.h | 2 +- .../srsran/phy/upper/channel_modulation/demodulation_mapper.h | 2 +- include/srsran/phy/upper/channel_modulation/evm_calculator.h | 2 +- .../srsran/phy/upper/channel_modulation/modulation_mapper.h | 2 +- .../upper/channel_processors/channel_processor_factories.h | 2 +- .../upper/channel_processors/channel_processor_formatters.h | 2 +- include/srsran/phy/upper/channel_processors/pbch_encoder.h | 2 +- include/srsran/phy/upper/channel_processors/pbch_modulator.h | 2 +- include/srsran/phy/upper/channel_processors/pdcch_encoder.h | 2 +- include/srsran/phy/upper/channel_processors/pdcch_modulator.h | 2 +- include/srsran/phy/upper/channel_processors/pdcch_processor.h | 2 +- include/srsran/phy/upper/channel_processors/pdsch_encoder.h | 2 +- include/srsran/phy/upper/channel_processors/pdsch_modulator.h | 2 +- include/srsran/phy/upper/channel_processors/pdsch_processor.h | 2 +- .../phy/upper/channel_processors/prach_detection_result.h | 2 +- include/srsran/phy/upper/channel_processors/prach_detector.h | 2 +- .../upper/channel_processors/prach_detector_phy_validator.h | 2 +- include/srsran/phy/upper/channel_processors/prach_generator.h | 2 +- .../srsran/phy/upper/channel_processors/pucch_demodulator.h | 2 +- include/srsran/phy/upper/channel_processors/pucch_detector.h | 2 +- include/srsran/phy/upper/channel_processors/pucch_processor.h | 2 +- .../phy/upper/channel_processors/pucch_processor_result.h | 2 +- .../srsran/phy/upper/channel_processors/pucch_uci_message.h | 2 +- include/srsran/phy/upper/channel_processors/pusch/factories.h | 2 +- .../srsran/phy/upper/channel_processors/pusch/formatters.h | 2 +- .../upper/channel_processors/pusch/pusch_codeword_buffer.h | 2 +- .../srsran/phy/upper/channel_processors/pusch/pusch_decoder.h | 2 +- .../phy/upper/channel_processors/pusch/pusch_decoder_buffer.h | 2 +- .../upper/channel_processors/pusch/pusch_decoder_notifier.h | 2 +- .../phy/upper/channel_processors/pusch/pusch_decoder_result.h | 2 +- .../phy/upper/channel_processors/pusch/pusch_demodulator.h | 2 +- .../channel_processors/pusch/pusch_demodulator_notifier.h | 2 +- .../phy/upper/channel_processors/pusch/pusch_processor.h | 2 +- .../pusch/pusch_processor_result_notifier.h | 2 +- .../phy/upper/channel_processors/pusch/ulsch_demultiplex.h | 2 +- include/srsran/phy/upper/channel_processors/ssb_processor.h | 2 +- include/srsran/phy/upper/channel_processors/uci/factories.h | 2 +- include/srsran/phy/upper/channel_processors/uci/uci_decoder.h | 2 +- include/srsran/phy/upper/channel_processors/uci/uci_status.h | 2 +- include/srsran/phy/upper/channel_state_information.h | 2 +- include/srsran/phy/upper/codeblock_metadata.h | 2 +- include/srsran/phy/upper/dmrs_mapping.h | 2 +- include/srsran/phy/upper/downlink_processor.h | 2 +- include/srsran/phy/upper/equalization/channel_equalizer.h | 2 +- .../srsran/phy/upper/equalization/equalization_factories.h | 2 +- include/srsran/phy/upper/log_likelihood_ratio.h | 2 +- include/srsran/phy/upper/rb_allocation.h | 2 +- include/srsran/phy/upper/re_measurement.h | 2 +- include/srsran/phy/upper/rx_buffer.h | 2 +- include/srsran/phy/upper/rx_buffer_pool.h | 2 +- .../upper/sequence_generators/low_papr_sequence_collection.h | 2 +- .../upper/sequence_generators/low_papr_sequence_generator.h | 2 +- .../phy/upper/sequence_generators/pseudo_random_generator.h | 2 +- .../upper/sequence_generators/sequence_generator_factories.h | 2 +- .../srsran/phy/upper/signal_processors/dmrs_pbch_processor.h | 2 +- .../srsran/phy/upper/signal_processors/dmrs_pdcch_processor.h | 2 +- .../srsran/phy/upper/signal_processors/dmrs_pdsch_processor.h | 2 +- .../srsran/phy/upper/signal_processors/dmrs_pucch_processor.h | 2 +- .../srsran/phy/upper/signal_processors/dmrs_pusch_estimator.h | 2 +- .../srsran/phy/upper/signal_processors/nzp_csi_rs_generator.h | 2 +- .../phy/upper/signal_processors/port_channel_estimator.h | 2 +- .../signal_processors/port_channel_estimator_parameters.h | 2 +- include/srsran/phy/upper/signal_processors/pss_processor.h | 2 +- .../phy/upper/signal_processors/signal_processor_formatters.h | 2 +- include/srsran/phy/upper/signal_processors/sss_processor.h | 2 +- include/srsran/phy/upper/trx_buffer_identifier.h | 2 +- include/srsran/phy/upper/tx_buffer.h | 2 +- include/srsran/phy/upper/tx_buffer_pool.h | 2 +- include/srsran/phy/upper/unique_rx_buffer.h | 2 +- include/srsran/phy/upper/unique_tx_buffer.h | 2 +- include/srsran/phy/upper/uplink_processor.h | 2 +- include/srsran/phy/upper/uplink_processor_context.h | 2 +- include/srsran/phy/upper/uplink_request_processor.h | 2 +- include/srsran/phy/upper/uplink_slot_pdu_repository.h | 2 +- include/srsran/phy/upper/upper_phy.h | 2 +- include/srsran/phy/upper/upper_phy_factories.h | 2 +- include/srsran/phy/upper/upper_phy_rg_gateway.h | 2 +- include/srsran/phy/upper/upper_phy_rx_results_notifier.h | 2 +- include/srsran/phy/upper/upper_phy_rx_symbol_handler.h | 2 +- .../srsran/phy/upper/upper_phy_rx_symbol_request_notifier.h | 2 +- include/srsran/phy/upper/upper_phy_timing_handler.h | 2 +- include/srsran/phy/upper/upper_phy_timing_notifier.h | 2 +- include/srsran/phy/upper/vrb_to_prb_mapper.h | 2 +- include/srsran/psup/psup_message.h | 2 +- include/srsran/psup/psup_packing.h | 2 +- include/srsran/radio/radio_base.h | 2 +- include/srsran/radio/radio_configuration.h | 2 +- include/srsran/radio/radio_constants.h | 2 +- include/srsran/radio/radio_factory.h | 2 +- include/srsran/radio/radio_management_plane.h | 2 +- include/srsran/radio/radio_notification_handler.h | 2 +- include/srsran/radio/radio_session.h | 2 +- include/srsran/ran/alpha.h | 2 +- include/srsran/ran/band_helper.h | 2 +- include/srsran/ran/band_helper_constants.h | 2 +- include/srsran/ran/bcd_helpers.h | 2 +- include/srsran/ran/bs_channel_bandwidth.h | 2 +- include/srsran/ran/carrier_configuration.h | 2 +- include/srsran/ran/cause.h | 2 +- include/srsran/ran/crit_diagnostics.h | 2 +- include/srsran/ran/csi_report/csi_report_config_helpers.h | 2 +- include/srsran/ran/csi_report/csi_report_configuration.h | 2 +- include/srsran/ran/csi_report/csi_report_data.h | 2 +- include/srsran/ran/csi_report/csi_report_formatters.h | 2 +- include/srsran/ran/csi_report/csi_report_on_pucch_helpers.h | 2 +- include/srsran/ran/csi_report/csi_report_on_pusch_helpers.h | 2 +- include/srsran/ran/csi_report/csi_report_on_puxch_utils.h | 2 +- include/srsran/ran/csi_report/csi_report_packed.h | 2 +- include/srsran/ran/csi_report/csi_report_pusch_size.h | 2 +- include/srsran/ran/csi_rs/codebook_config.h | 2 +- include/srsran/ran/csi_rs/csi_meas_config.h | 2 +- include/srsran/ran/csi_rs/csi_report_config.h | 2 +- include/srsran/ran/csi_rs/csi_resource_config.h | 2 +- include/srsran/ran/csi_rs/csi_rs_config_helpers.h | 2 +- include/srsran/ran/csi_rs/csi_rs_constants.h | 2 +- include/srsran/ran/csi_rs/csi_rs_id.h | 2 +- include/srsran/ran/csi_rs/csi_rs_pattern.h | 2 +- include/srsran/ran/csi_rs/csi_rs_types.h | 2 +- include/srsran/ran/csi_rs/frequency_allocation_type.h | 2 +- include/srsran/ran/cu_types.h | 2 +- include/srsran/ran/cyclic_prefix.h | 2 +- include/srsran/ran/direct_current_offset.h | 2 +- include/srsran/ran/dmrs.h | 2 +- include/srsran/ran/du_types.h | 2 +- include/srsran/ran/du_ue_list.h | 2 +- include/srsran/ran/duplex_mode.h | 2 +- include/srsran/ran/five_qi.h | 2 +- include/srsran/ran/frame_types.h | 2 +- include/srsran/ran/frequency_range.h | 2 +- include/srsran/ran/lcid.h | 2 +- include/srsran/ran/ldpc_base_graph.h | 2 +- include/srsran/ran/modulation_scheme.h | 2 +- include/srsran/ran/n_ta_offset.h | 2 +- include/srsran/ran/nr_band.h | 2 +- include/srsran/ran/nr_cgi.h | 2 +- include/srsran/ran/nr_cgi_helpers.h | 2 +- include/srsran/ran/nr_up_protocol.h | 2 +- include/srsran/ran/ntn.h | 2 +- include/srsran/ran/ofdm_symbol_range.h | 2 +- include/srsran/ran/paging_information.h | 2 +- include/srsran/ran/pcch/pcch_configuration.h | 2 +- include/srsran/ran/pci.h | 2 +- include/srsran/ran/pci_helpers.h | 2 +- include/srsran/ran/pdcch/aggregation_level.h | 2 +- include/srsran/ran/pdcch/cce_to_prb_mapping.h | 2 +- include/srsran/ran/pdcch/coreset.h | 2 +- include/srsran/ran/pdcch/dci_packing.h | 2 +- include/srsran/ran/pdcch/dci_packing_formatters.h | 2 +- include/srsran/ran/pdcch/downlink_preemption.h | 2 +- include/srsran/ran/pdcch/pdcch_candidates.h | 2 +- include/srsran/ran/pdcch/pdcch_constants.h | 2 +- include/srsran/ran/pdcch/pdcch_context.h | 2 +- include/srsran/ran/pdcch/pdcch_context_formatter.h | 2 +- include/srsran/ran/pdcch/pdcch_type0_css_coreset_config.h | 2 +- include/srsran/ran/pdcch/pdcch_type0_css_occasions.h | 2 +- include/srsran/ran/pdcch/search_space.h | 2 +- include/srsran/ran/pdsch/dlsch_info.h | 2 +- include/srsran/ran/pdsch/pdsch_antenna_ports_mapping.h | 2 +- include/srsran/ran/pdsch/pdsch_constants.h | 2 +- include/srsran/ran/pdsch/pdsch_context.h | 2 +- include/srsran/ran/pdsch/pdsch_context_formatter.h | 2 +- include/srsran/ran/pdsch/pdsch_mcs.h | 2 +- include/srsran/ran/pdsch/pdsch_prb_bundling.h | 2 +- include/srsran/ran/pdsch/pdsch_rate_match_pattern.h | 2 +- include/srsran/ran/phy_time_unit.h | 2 +- include/srsran/ran/physical_cell_group.h | 2 +- include/srsran/ran/prach/prach_configuration.h | 2 +- include/srsran/ran/prach/prach_constants.h | 2 +- include/srsran/ran/prach/prach_cyclic_shifts.h | 2 +- include/srsran/ran/prach/prach_format_type.h | 2 +- include/srsran/ran/prach/prach_frequency_mapping.h | 2 +- include/srsran/ran/prach/prach_helper.h | 2 +- include/srsran/ran/prach/prach_preamble_information.h | 2 +- include/srsran/ran/prach/prach_subcarrier_spacing.h | 2 +- include/srsran/ran/prach/rach_config_common.h | 2 +- include/srsran/ran/prach/restricted_set_config.h | 2 +- include/srsran/ran/precoding/precoding_codebooks.h | 2 +- include/srsran/ran/precoding/precoding_constants.h | 2 +- include/srsran/ran/precoding/precoding_weight_matrix.h | 2 +- .../srsran/ran/precoding/precoding_weight_matrix_formatters.h | 2 +- include/srsran/ran/ptrs.h | 2 +- include/srsran/ran/pucch/pucch_configuration.h | 2 +- include/srsran/ran/pucch/pucch_constants.h | 2 +- include/srsran/ran/pucch/pucch_context.h | 2 +- include/srsran/ran/pucch/pucch_context_formatter.h | 2 +- include/srsran/ran/pucch/pucch_info.h | 2 +- include/srsran/ran/pucch/pucch_mapping.h | 2 +- include/srsran/ran/pucch/pucch_tpc.h | 2 +- include/srsran/ran/pucch/srs_configuration.h | 2 +- include/srsran/ran/pucch/srs_tpc.h | 2 +- include/srsran/ran/pusch/pusch_configuration.h | 2 +- include/srsran/ran/pusch/pusch_constants.h | 2 +- include/srsran/ran/pusch/pusch_context.h | 2 +- include/srsran/ran/pusch/pusch_context_formatter.h | 2 +- include/srsran/ran/pusch/pusch_mcs.h | 2 +- include/srsran/ran/pusch/pusch_tpc.h | 2 +- include/srsran/ran/pusch/pusch_uci_beta_offset.h | 2 +- include/srsran/ran/pusch/ulsch_info.h | 2 +- include/srsran/ran/qos_prio_level.h | 2 +- include/srsran/ran/resource_allocation/rb_interval.h | 2 +- .../ran/resource_allocation/resource_allocation_frequency.h | 2 +- include/srsran/ran/resource_block.h | 2 +- include/srsran/ran/rnti.h | 2 +- include/srsran/ran/s_nssai.h | 2 +- include/srsran/ran/sch/sch_constants.h | 2 +- include/srsran/ran/sch/sch_segmentation.h | 2 +- include/srsran/ran/sch_dmrs_power.h | 2 +- include/srsran/ran/sch_mcs.h | 2 +- include/srsran/ran/serv_cell_index.h | 2 +- include/srsran/ran/sib/sib_configuration.h | 2 +- include/srsran/ran/sib/system_info_config.h | 2 +- include/srsran/ran/slot_pdu_capacity_constants.h | 2 +- include/srsran/ran/slot_point.h | 2 +- include/srsran/ran/sr_configuration.h | 2 +- include/srsran/ran/ssb_configuration.h | 2 +- include/srsran/ran/ssb_gscn.h | 2 +- include/srsran/ran/ssb_mapping.h | 2 +- include/srsran/ran/ssb_properties.h | 2 +- include/srsran/ran/subcarrier_spacing.h | 2 +- include/srsran/ran/tci.h | 2 +- include/srsran/ran/tdd/tdd_ul_dl_config.h | 2 +- include/srsran/ran/tdd/tdd_ul_dl_config_formatters.h | 2 +- include/srsran/ran/uci/uci_configuration.h | 2 +- include/srsran/ran/uci/uci_constants.h | 2 +- include/srsran/ran/uci/uci_formatters.h | 2 +- include/srsran/ran/uci/uci_info.h | 2 +- include/srsran/ran/uci/uci_mapping.h | 2 +- include/srsran/ran/uci/uci_payload_type.h | 2 +- include/srsran/ran/up_transport_layer_info.h | 2 +- include/srsran/rlc/rlc_config.h | 2 +- include/srsran/rlc/rlc_entity.h | 2 +- include/srsran/rlc/rlc_factory.h | 2 +- include/srsran/rlc/rlc_metrics.h | 2 +- include/srsran/rlc/rlc_rx.h | 2 +- include/srsran/rlc/rlc_rx_metrics.h | 2 +- include/srsran/rlc/rlc_srb_config_factory.h | 2 +- include/srsran/rlc/rlc_tx.h | 2 +- include/srsran/rlc/rlc_tx_metrics.h | 2 +- include/srsran/rrc/meas_types.h | 2 +- include/srsran/rrc/meas_types_validators.h | 2 +- include/srsran/rrc/rrc.h | 2 +- include/srsran/rrc/rrc_cell_context.h | 2 +- include/srsran/rrc/rrc_config.h | 2 +- include/srsran/rrc/rrc_du.h | 2 +- include/srsran/rrc/rrc_du_factory.h | 2 +- include/srsran/rrc/rrc_types.h | 2 +- include/srsran/rrc/rrc_ue.h | 2 +- include/srsran/rrc/rrc_ue_config.h | 2 +- include/srsran/ru/ru.h | 2 +- include/srsran/ru/ru_adapters.h | 2 +- include/srsran/ru/ru_configuration.h | 2 +- include/srsran/ru/ru_controller.h | 2 +- include/srsran/ru/ru_downlink_plane.h | 2 +- include/srsran/ru/ru_generic_configuration.h | 2 +- include/srsran/ru/ru_generic_factory.h | 2 +- include/srsran/ru/ru_ofh_configuration.h | 2 +- include/srsran/ru/ru_ofh_factory.h | 2 +- include/srsran/ru/ru_timing_notifier.h | 2 +- include/srsran/ru/ru_uplink_plane.h | 2 +- include/srsran/scheduler/config/bwp_configuration.h | 2 +- include/srsran/scheduler/config/cell_config_builder_params.h | 2 +- include/srsran/scheduler/config/csi_helper.h | 2 +- include/srsran/scheduler/config/dmrs.h | 2 +- include/srsran/scheduler/config/logical_channel_config.h | 2 +- .../srsran/scheduler/config/logical_channel_config_factory.h | 2 +- include/srsran/scheduler/config/logical_channel_group.h | 2 +- include/srsran/scheduler/config/sched_cell_config_helpers.h | 2 +- .../srsran/scheduler/config/scheduler_cell_config_validator.h | 2 +- include/srsran/scheduler/config/scheduler_config.h | 2 +- include/srsran/scheduler/config/scheduler_expert_config.h | 2 +- .../scheduler/config/scheduler_expert_config_validator.h | 2 +- .../srsran/scheduler/config/scheduler_ue_config_validator.h | 2 +- include/srsran/scheduler/config/serving_cell_config.h | 2 +- include/srsran/scheduler/config/serving_cell_config_factory.h | 2 +- .../srsran/scheduler/config/serving_cell_config_validator.h | 2 +- include/srsran/scheduler/config/si_scheduling_config.h | 2 +- include/srsran/scheduler/harq_id.h | 2 +- include/srsran/scheduler/mac_scheduler.h | 2 +- include/srsran/scheduler/resource_block_group.h | 2 +- include/srsran/scheduler/sched_consts.h | 2 +- include/srsran/scheduler/scheduler_configurator.h | 2 +- include/srsran/scheduler/scheduler_dci.h | 2 +- .../scheduler/scheduler_dl_buffer_state_indication_handler.h | 2 +- include/srsran/scheduler/scheduler_factory.h | 2 +- include/srsran/scheduler/scheduler_feedback_handler.h | 2 +- include/srsran/scheduler/scheduler_metrics.h | 2 +- include/srsran/scheduler/scheduler_paging_handler.h | 2 +- include/srsran/scheduler/scheduler_pucch_format.h | 2 +- include/srsran/scheduler/scheduler_slot_handler.h | 2 +- include/srsran/scheduler/vrb_alloc.h | 2 +- include/srsran/sdap/sdap.h | 2 +- include/srsran/sdap/sdap_config.h | 2 +- include/srsran/sdap/sdap_factory.h | 2 +- include/srsran/sdap/sdap_mapper.h | 2 +- include/srsran/security/ciphering.h | 2 +- include/srsran/security/integrity.h | 2 +- include/srsran/security/s3g.h | 2 +- include/srsran/security/security.h | 2 +- include/srsran/security/ssl.h | 2 +- include/srsran/security/zuc.h | 2 +- include/srsran/srslog/context.h | 2 +- include/srsran/srslog/detail/log_backend.h | 2 +- include/srsran/srslog/detail/log_entry.h | 2 +- include/srsran/srslog/detail/log_entry_metadata.h | 2 +- include/srsran/srslog/detail/support/any.h | 2 +- include/srsran/srslog/detail/support/backend_capacity.h | 2 +- include/srsran/srslog/detail/support/dyn_arg_store_pool.h | 2 +- include/srsran/srslog/detail/support/error_string.h | 2 +- include/srsran/srslog/detail/support/memory_buffer.h | 2 +- include/srsran/srslog/detail/support/thread_utils.h | 2 +- include/srsran/srslog/detail/support/tmpl_utils.h | 2 +- include/srsran/srslog/detail/support/work_queue.h | 2 +- include/srsran/srslog/event_trace.h | 2 +- include/srsran/srslog/formatter.h | 2 +- include/srsran/srslog/log_channel.h | 2 +- include/srsran/srslog/logger.h | 2 +- include/srsran/srslog/shared_types.h | 2 +- include/srsran/srslog/sink.h | 2 +- include/srsran/srslog/sink_repository.h | 2 +- include/srsran/srslog/srslog.h | 2 +- include/srsran/srslog/srslog_c.h | 2 +- include/srsran/srsvec/accumulate.h | 2 +- include/srsran/srsvec/add.h | 2 +- include/srsran/srsvec/aligned_vec.h | 2 +- include/srsran/srsvec/binary.h | 2 +- include/srsran/srsvec/bit.h | 2 +- include/srsran/srsvec/circ_shift.h | 2 +- include/srsran/srsvec/clip.h | 2 +- include/srsran/srsvec/compare.h | 2 +- include/srsran/srsvec/conversion.h | 2 +- include/srsran/srsvec/convolution.h | 2 +- include/srsran/srsvec/copy.h | 2 +- include/srsran/srsvec/detail/traits.h | 2 +- include/srsran/srsvec/division.h | 2 +- include/srsran/srsvec/dot_prod.h | 2 +- include/srsran/srsvec/fill.h | 2 +- include/srsran/srsvec/mean.h | 2 +- include/srsran/srsvec/modulus_square.h | 2 +- include/srsran/srsvec/prod.h | 2 +- include/srsran/srsvec/sc_prod.h | 2 +- include/srsran/srsvec/subtract.h | 2 +- include/srsran/srsvec/types.h | 2 +- include/srsran/srsvec/zero.h | 2 +- include/srsran/support/async/async_event_source.h | 2 +- include/srsran/support/async/async_no_op_task.h | 2 +- include/srsran/support/async/async_procedure.h | 2 +- include/srsran/support/async/async_queue.h | 2 +- include/srsran/support/async/async_task.h | 2 +- include/srsran/support/async/async_test_utils.h | 2 +- include/srsran/support/async/async_timer.h | 2 +- include/srsran/support/async/awaiter_memory_storage.h | 2 +- include/srsran/support/async/coroutine.h | 2 +- include/srsran/support/async/detail/base_task.h | 2 +- include/srsran/support/async/detail/event_impl.h | 2 +- include/srsran/support/async/detail/function_signature.h | 2 +- include/srsran/support/async/detail/promise_data.h | 2 +- include/srsran/support/async/detail/unique_coroutine.h | 2 +- include/srsran/support/async/eager_async_task.h | 2 +- include/srsran/support/async/event_sender_receiver.h | 2 +- include/srsran/support/async/event_signal.h | 2 +- include/srsran/support/async/execute_on.h | 2 +- include/srsran/support/async/fifo_async_task_scheduler.h | 2 +- include/srsran/support/async/manual_event.h | 2 +- include/srsran/support/async/protocol_transaction_manager.h | 2 +- include/srsran/support/backtrace.h | 2 +- include/srsran/support/benchmark_utils.h | 2 +- include/srsran/support/bit_encoding.h | 2 +- include/srsran/support/build_info/build_info.h | 2 +- include/srsran/support/cli11_utils.h | 2 +- include/srsran/support/compiler.h | 2 +- include/srsran/support/complex_normal_random.h | 2 +- include/srsran/support/config/validator_helpers.h | 2 +- include/srsran/support/config/validator_result.h | 2 +- include/srsran/support/config_parsers.h | 2 +- include/srsran/support/cpu_features.h | 2 +- include/srsran/support/detail/is_iterable.h | 2 +- include/srsran/support/detail/type_list.h | 2 +- include/srsran/support/error_handling.h | 2 +- include/srsran/support/event_tracing.h | 2 +- include/srsran/support/executors/blocking_task_worker.h | 2 +- include/srsran/support/executors/executor_tracer.h | 2 +- include/srsran/support/executors/manual_task_worker.h | 2 +- include/srsran/support/executors/priority_task_worker.h | 2 +- include/srsran/support/executors/strand_executor.h | 2 +- include/srsran/support/executors/sync_task_executor.h | 2 +- include/srsran/support/executors/task_execution_manager.h | 2 +- include/srsran/support/executors/task_executor.h | 2 +- include/srsran/support/executors/task_executor_utils.h | 2 +- include/srsran/support/executors/task_redispatcher.h | 2 +- include/srsran/support/executors/task_worker.h | 2 +- include/srsran/support/executors/task_worker_pool.h | 2 +- include/srsran/support/file_sink.h | 2 +- include/srsran/support/file_tensor.h | 2 +- include/srsran/support/file_vector.h | 2 +- include/srsran/support/format_utils.h | 2 +- include/srsran/support/io/io_broker.h | 2 +- include/srsran/support/io/io_broker_factory.h | 2 +- include/srsran/support/io/transport_layer_address.h | 2 +- include/srsran/support/math/gcd.h | 2 +- include/srsran/support/math_utils.h | 2 +- .../support/memory_pool/concurrent_thread_local_object_pool.h | 2 +- .../srsran/support/memory_pool/fixed_size_memory_block_pool.h | 2 +- include/srsran/support/memory_pool/heap_memory_resource.h | 2 +- include/srsran/support/memory_pool/lockfree_object_pool.h | 2 +- include/srsran/support/memory_pool/memory_block_list.h | 2 +- include/srsran/support/memory_pool/memory_pool_utils.h | 2 +- include/srsran/support/memory_pool/ring_buffer_pool.h | 2 +- include/srsran/support/memory_pool/ring_memory_allocator.h | 2 +- .../support/memory_pool/unsync_fixed_size_memory_block_pool.h | 2 +- include/srsran/support/prefixed_logger.h | 2 +- include/srsran/support/sdu_window.h | 2 +- include/srsran/support/signal_handler.h | 2 +- include/srsran/support/sockets.h | 2 +- include/srsran/support/span_printer.h | 2 +- include/srsran/support/srsran_assert.h | 2 +- include/srsran/support/srsran_test.h | 2 +- include/srsran/support/stats.h | 2 +- include/srsran/support/sysinfo.h | 2 +- include/srsran/support/test_utils.h | 2 +- include/srsran/support/timers.h | 2 +- include/srsran/support/tsan_options.h | 2 +- include/srsran/support/unique_thread.h | 2 +- include/srsran/support/units.h | 2 +- include/srsran/support/version/version.h | 2 +- lib/CMakeLists.txt | 2 +- lib/asn1/CMakeLists.txt | 2 +- lib/asn1/asn1_diff_utils.h | 2 +- lib/asn1/asn1_utils.cpp | 2 +- lib/asn1/e1ap/e1ap.cpp | 2 +- lib/asn1/e2ap/e2ap.cpp | 2 +- lib/asn1/e2ap/e2sm_rc.cpp | 2 +- lib/asn1/f1ap/common.cpp | 2 +- lib/asn1/f1ap/f1ap.cpp | 2 +- lib/asn1/f1ap/f1ap_ies.cpp | 2 +- lib/asn1/f1ap/f1ap_pdu_contents.cpp | 2 +- lib/asn1/f1ap/f1ap_pdu_contents_ue.cpp | 2 +- lib/asn1/f1ap/f1ap_pdu_items.cpp | 2 +- lib/asn1/ngap/common.cpp | 2 +- lib/asn1/ngap/ngap.cpp | 2 +- lib/asn1/ngap/ngap_ies.cpp | 2 +- lib/asn1/ngap/ngap_pdu_contents.cpp | 2 +- lib/asn1/rrc_nr/cell_group_config.cpp | 2 +- lib/asn1/rrc_nr/common.cpp | 2 +- lib/asn1/rrc_nr/dl_dcch_msg.cpp | 2 +- lib/asn1/rrc_nr/msg_common.cpp | 2 +- lib/asn1/rrc_nr/nr_sidelink_preconf.cpp | 2 +- lib/asn1/rrc_nr/nr_ue_variables.cpp | 2 +- lib/asn1/rrc_nr/pc5_rrc_definitions.cpp | 2 +- lib/asn1/rrc_nr/rrc_nr.cpp | 2 +- lib/asn1/rrc_nr/serving_cell.cpp | 2 +- lib/asn1/rrc_nr/ue_cap.cpp | 2 +- lib/asn1/rrc_nr/ul_dcch_msg.cpp | 2 +- lib/cu_cp/CMakeLists.txt | 2 +- lib/cu_cp/adapters/cell_meas_manager_adapters.h | 2 +- lib/cu_cp/adapters/cu_cp_adapters.h | 2 +- lib/cu_cp/adapters/du_processor_adapters.h | 2 +- lib/cu_cp/adapters/e1ap_adapters.h | 2 +- lib/cu_cp/adapters/f1ap_adapters.h | 2 +- lib/cu_cp/adapters/ngap_adapters.h | 2 +- lib/cu_cp/adapters/rrc_ue_adapters.h | 2 +- lib/cu_cp/cell_meas_manager/CMakeLists.txt | 2 +- lib/cu_cp/cell_meas_manager/cell_meas_manager_factory.cpp | 2 +- lib/cu_cp/cell_meas_manager/cell_meas_manager_helpers.cpp | 2 +- lib/cu_cp/cell_meas_manager/cell_meas_manager_helpers.h | 2 +- lib/cu_cp/cell_meas_manager/cell_meas_manager_impl.cpp | 2 +- lib/cu_cp/cell_meas_manager/cell_meas_manager_impl.h | 2 +- lib/cu_cp/cell_meas_manager/measurement_context.h | 2 +- lib/cu_cp/cu_cp_factory.cpp | 2 +- lib/cu_cp/cu_cp_impl.cpp | 2 +- lib/cu_cp/cu_cp_impl.h | 2 +- lib/cu_cp/cu_cp_impl_interface.h | 2 +- lib/cu_cp/cu_up_processor/cu_up_processor_factory.cpp | 2 +- lib/cu_cp/cu_up_processor/cu_up_processor_factory.h | 2 +- lib/cu_cp/cu_up_processor/cu_up_processor_impl.cpp | 2 +- lib/cu_cp/cu_up_processor/cu_up_processor_impl.h | 2 +- lib/cu_cp/cu_up_processor/cu_up_processor_repository.cpp | 2 +- lib/cu_cp/cu_up_processor/cu_up_processor_repository.h | 2 +- lib/cu_cp/du_processor/du_processor_factory.cpp | 2 +- lib/cu_cp/du_processor/du_processor_factory.h | 2 +- lib/cu_cp/du_processor/du_processor_impl.cpp | 2 +- lib/cu_cp/du_processor/du_processor_impl.h | 2 +- lib/cu_cp/du_processor/du_processor_repository.cpp | 2 +- lib/cu_cp/du_processor/du_processor_repository.h | 2 +- lib/cu_cp/log_format.h | 2 +- lib/cu_cp/mobility_manager/CMakeLists.txt | 2 +- lib/cu_cp/mobility_manager/mobility_manager_factory.cpp | 2 +- lib/cu_cp/mobility_manager/mobility_manager_impl.cpp | 2 +- lib/cu_cp/mobility_manager/mobility_manager_impl.h | 2 +- lib/cu_cp/routine_managers/cu_cp_routine_manager.cpp | 2 +- lib/cu_cp/routine_managers/cu_cp_routine_manager.h | 2 +- lib/cu_cp/routine_managers/du_processor_routine_manager.cpp | 2 +- lib/cu_cp/routine_managers/du_processor_routine_manager.h | 2 +- lib/cu_cp/routines/initial_cu_cp_setup_routine.cpp | 2 +- lib/cu_cp/routines/initial_cu_cp_setup_routine.h | 2 +- .../routines/mobility/handover_reconfiguration_routine.cpp | 2 +- .../routines/mobility/handover_reconfiguration_routine.h | 2 +- .../routines/mobility/inter_cu_handover_target_routine.cpp | 2 +- .../routines/mobility/inter_cu_handover_target_routine.h | 2 +- lib/cu_cp/routines/mobility/inter_du_handover_routine.cpp | 2 +- lib/cu_cp/routines/mobility/inter_du_handover_routine.h | 2 +- .../mobility/inter_ngran_node_n2_handover_routine.cpp | 2 +- .../routines/mobility/inter_ngran_node_n2_handover_routine.h | 2 +- lib/cu_cp/routines/mobility/mobility_helpers.cpp | 2 +- lib/cu_cp/routines/mobility/mobility_helpers.h | 2 +- .../routines/pdu_session_resource_modification_routine.cpp | 2 +- .../routines/pdu_session_resource_modification_routine.h | 2 +- lib/cu_cp/routines/pdu_session_resource_release_routine.cpp | 2 +- lib/cu_cp/routines/pdu_session_resource_release_routine.h | 2 +- lib/cu_cp/routines/pdu_session_resource_setup_routine.cpp | 2 +- lib/cu_cp/routines/pdu_session_resource_setup_routine.h | 2 +- lib/cu_cp/routines/pdu_session_routine_helpers.cpp | 2 +- lib/cu_cp/routines/pdu_session_routine_helpers.h | 2 +- .../routines/reestablishment_context_modification_routine.cpp | 2 +- .../routines/reestablishment_context_modification_routine.h | 2 +- lib/cu_cp/routines/ue_context_release_routine.cpp | 2 +- lib/cu_cp/routines/ue_context_release_routine.h | 2 +- lib/cu_cp/routines/ue_removal_routine.cpp | 2 +- lib/cu_cp/routines/ue_removal_routine.h | 2 +- lib/cu_cp/task_schedulers/cu_up_task_scheduler.cpp | 2 +- lib/cu_cp/task_schedulers/cu_up_task_scheduler.h | 2 +- lib/cu_cp/task_schedulers/du_task_scheduler.cpp | 2 +- lib/cu_cp/task_schedulers/du_task_scheduler.h | 2 +- lib/cu_cp/task_schedulers/ue_task_scheduler.cpp | 2 +- lib/cu_cp/task_schedulers/ue_task_scheduler.h | 2 +- lib/cu_cp/ue_manager_impl.cpp | 2 +- lib/cu_cp/ue_manager_impl.h | 2 +- lib/cu_cp/up_resource_manager/CMakeLists.txt | 2 +- lib/cu_cp/up_resource_manager/up_resource_manager_factory.cpp | 2 +- lib/cu_cp/up_resource_manager/up_resource_manager_helpers.cpp | 2 +- lib/cu_cp/up_resource_manager/up_resource_manager_helpers.h | 2 +- lib/cu_cp/up_resource_manager/up_resource_manager_impl.cpp | 2 +- lib/cu_cp/up_resource_manager/up_resource_manager_impl.h | 2 +- lib/cu_up/CMakeLists.txt | 2 +- lib/cu_up/adapters/e1ap_adapters.h | 2 +- lib/cu_up/adapters/f1u_adapters.h | 2 +- lib/cu_up/adapters/gtpu_adapters.h | 2 +- lib/cu_up/adapters/gw_adapters.h | 2 +- lib/cu_up/adapters/pdcp_adapters.h | 2 +- lib/cu_up/adapters/sdap_adapters.h | 2 +- lib/cu_up/cu_up_executor_mapper.cpp | 2 +- lib/cu_up/cu_up_factory.cpp | 2 +- lib/cu_up/cu_up_impl.cpp | 2 +- lib/cu_up/cu_up_impl.h | 2 +- lib/cu_up/cu_up_ue_logger.h | 2 +- lib/cu_up/drb_context.h | 2 +- lib/cu_up/pdu_session.h | 2 +- lib/cu_up/pdu_session_manager.h | 2 +- lib/cu_up/pdu_session_manager_impl.cpp | 2 +- lib/cu_up/pdu_session_manager_impl.h | 2 +- lib/cu_up/qos_flow_context.h | 2 +- lib/cu_up/routines/initial_cu_up_setup_routine.cpp | 2 +- lib/cu_up/routines/initial_cu_up_setup_routine.h | 2 +- lib/cu_up/ue_context.h | 2 +- lib/cu_up/ue_manager.cpp | 2 +- lib/cu_up/ue_manager.h | 2 +- lib/cu_up/ue_manager_interfaces.h | 2 +- lib/du/CMakeLists.txt | 2 +- lib/du/adapters/fapi_factory.cpp | 2 +- lib/du/adapters/fapi_factory.h | 2 +- lib/du/du_cell_config_validation.cpp | 2 +- lib/du/du_factory.cpp | 2 +- lib/du/du_impl.cpp | 2 +- lib/du/du_impl.h | 2 +- lib/du/du_low_impl.cpp | 2 +- lib/du/du_low_impl.h | 2 +- lib/du/du_update_config_helpers.cpp | 2 +- lib/du_high/CMakeLists.txt | 2 +- lib/du_high/adapters/adapters.h | 2 +- lib/du_high/adapters/du_high_adapter_factories.h | 2 +- lib/du_high/adapters/f1ap_adapters.h | 2 +- lib/du_high/adapters/mac_test_mode_adapter.cpp | 2 +- lib/du_high/adapters/mac_test_mode_adapter.h | 2 +- lib/du_high/du_high_executor_strategies.h | 2 +- lib/du_high/du_high_factory.cpp | 2 +- lib/du_high/du_high_impl.cpp | 2 +- lib/du_high/du_high_impl.h | 2 +- lib/du_manager/CMakeLists.txt | 2 +- lib/du_manager/converters/CMakeLists.txt | 2 +- lib/du_manager/converters/asn1_csi_meas_config_helpers.cpp | 2 +- lib/du_manager/converters/asn1_csi_meas_config_helpers.h | 2 +- lib/du_manager/converters/asn1_rrc_config_helpers.cpp | 2 +- lib/du_manager/converters/asn1_rrc_config_helpers.h | 2 +- lib/du_manager/converters/f1ap_configuration_helpers.cpp | 2 +- lib/du_manager/converters/f1ap_configuration_helpers.h | 2 +- lib/du_manager/converters/rlc_config_helpers.cpp | 2 +- lib/du_manager/converters/rlc_config_helpers.h | 2 +- lib/du_manager/converters/scheduler_configuration_helpers.cpp | 2 +- lib/du_manager/converters/scheduler_configuration_helpers.h | 2 +- lib/du_manager/du_cell_manager.cpp | 2 +- lib/du_manager/du_cell_manager.h | 2 +- lib/du_manager/du_manager_factory.cpp | 2 +- lib/du_manager/du_manager_impl.cpp | 2 +- lib/du_manager/du_manager_impl.h | 2 +- lib/du_manager/du_ue/CMakeLists.txt | 2 +- lib/du_manager/du_ue/du_bearer.cpp | 2 +- lib/du_manager/du_ue/du_bearer.h | 2 +- lib/du_manager/du_ue/du_ue.h | 2 +- lib/du_manager/du_ue/du_ue_adapters.cpp | 2 +- lib/du_manager/du_ue/du_ue_adapters.h | 2 +- lib/du_manager/du_ue/du_ue_bearer_manager.cpp | 2 +- lib/du_manager/du_ue/du_ue_bearer_manager.h | 2 +- lib/du_manager/du_ue/du_ue_controller_impl.cpp | 2 +- lib/du_manager/du_ue/du_ue_controller_impl.h | 2 +- lib/du_manager/du_ue/du_ue_manager.cpp | 2 +- lib/du_manager/du_ue/du_ue_manager.h | 2 +- lib/du_manager/du_ue/du_ue_manager_repository.h | 2 +- lib/du_manager/procedures/CMakeLists.txt | 2 +- lib/du_manager/procedures/du_stop_procedure.cpp | 2 +- lib/du_manager/procedures/du_stop_procedure.h | 2 +- .../procedures/du_ue_ric_configuration_procedure.cpp | 2 +- lib/du_manager/procedures/du_ue_ric_configuration_procedure.h | 2 +- lib/du_manager/procedures/initial_du_setup_procedure.cpp | 2 +- lib/du_manager/procedures/initial_du_setup_procedure.h | 2 +- lib/du_manager/procedures/procedure_logger.h | 2 +- lib/du_manager/procedures/ue_configuration_procedure.cpp | 2 +- lib/du_manager/procedures/ue_configuration_procedure.h | 2 +- lib/du_manager/procedures/ue_creation_procedure.cpp | 2 +- lib/du_manager/procedures/ue_creation_procedure.h | 2 +- lib/du_manager/procedures/ue_deletion_procedure.cpp | 2 +- lib/du_manager/procedures/ue_deletion_procedure.h | 2 +- lib/du_manager/ran_resource_management/CMakeLists.txt | 2 +- lib/du_manager/ran_resource_management/cell_group_config.h | 2 +- .../ran_resource_management/du_pucch_resource_manager.cpp | 2 +- .../ran_resource_management/du_pucch_resource_manager.h | 2 +- .../ran_resource_management/du_ran_resource_manager.h | 2 +- .../ran_resource_management/du_ran_resource_manager_impl.cpp | 2 +- .../ran_resource_management/du_ran_resource_manager_impl.h | 2 +- .../ran_resource_management/pucch_resource_generator.cpp | 2 +- .../ran_resource_management/pucch_resource_generator.h | 2 +- lib/e1ap/CMakeLists.txt | 2 +- lib/e1ap/common/e1ap_asn1_converters.h | 2 +- lib/e1ap/common/e1ap_asn1_helpers.h | 2 +- lib/e1ap/common/e1ap_asn1_packer.cpp | 2 +- lib/e1ap/common/e1ap_asn1_packer.h | 2 +- lib/e1ap/common/e1ap_asn1_utils.h | 2 +- lib/e1ap/cu_cp/e1ap_cu_cp_asn1_helpers.h | 2 +- lib/e1ap/cu_cp/e1ap_cu_cp_factory.cpp | 2 +- lib/e1ap/cu_cp/e1ap_cu_cp_impl.cpp | 2 +- lib/e1ap/cu_cp/e1ap_cu_cp_impl.h | 2 +- .../procedures/bearer_context_modification_procedure.cpp | 2 +- .../cu_cp/procedures/bearer_context_modification_procedure.h | 2 +- .../cu_cp/procedures/bearer_context_release_procedure.cpp | 2 +- lib/e1ap/cu_cp/procedures/bearer_context_release_procedure.h | 2 +- lib/e1ap/cu_cp/procedures/bearer_context_setup_procedure.cpp | 2 +- lib/e1ap/cu_cp/procedures/bearer_context_setup_procedure.h | 2 +- lib/e1ap/cu_cp/procedures/e1ap_transaction_manager.h | 2 +- lib/e1ap/cu_cp/ue_context/e1ap_bearer_transaction_manager.h | 2 +- lib/e1ap/cu_cp/ue_context/e1ap_cu_cp_ue_context.h | 2 +- lib/e1ap/cu_cp/ue_context/e1ap_ue_logger.h | 2 +- lib/e1ap/cu_up/e1ap_cu_up_asn1_helpers.h | 2 +- lib/e1ap/cu_up/e1ap_cu_up_connection_handler.cpp | 2 +- lib/e1ap/cu_up/e1ap_cu_up_connection_handler.h | 2 +- lib/e1ap/cu_up/e1ap_cu_up_factory.cpp | 2 +- lib/e1ap/cu_up/e1ap_cu_up_impl.cpp | 2 +- lib/e1ap/cu_up/e1ap_cu_up_impl.h | 2 +- lib/e1ap/cu_up/procedures/e1ap_cu_up_event_manager.h | 2 +- lib/e1ap/cu_up/procedures/e1ap_cu_up_setup_procedure.cpp | 2 +- lib/e1ap/cu_up/procedures/e1ap_cu_up_setup_procedure.h | 2 +- lib/e1ap/cu_up/ue_context/e1ap_cu_up_ue_context.h | 2 +- lib/e1ap/cu_up/ue_context/e1ap_ue_logger.h | 2 +- lib/e2/CMakeLists.txt | 2 +- lib/e2/common/e2_du_metrics_connector.cpp | 2 +- lib/e2/common/e2_entity.cpp | 2 +- lib/e2/common/e2_entity.h | 2 +- lib/e2/common/e2_factory.cpp | 2 +- lib/e2/common/e2_impl.cpp | 2 +- lib/e2/common/e2_impl.h | 2 +- lib/e2/common/e2_subscription_manager_impl.cpp | 2 +- lib/e2/common/e2_subscription_manager_impl.h | 2 +- lib/e2/common/e2ap_asn1_helpers.h | 2 +- lib/e2/common/e2ap_asn1_packer.cpp | 2 +- lib/e2/common/e2ap_asn1_packer.h | 2 +- lib/e2/common/e2ap_asn1_utils.h | 2 +- lib/e2/e2sm/e2sm_factory.cpp | 2 +- lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.cpp | 2 +- lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.h | 2 +- lib/e2/e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.cpp | 2 +- lib/e2/e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.h | 2 +- lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.cpp | 2 +- lib/e2/e2sm/e2sm_kpm/e2sm_kpm_impl.h | 2 +- lib/e2/e2sm/e2sm_kpm/e2sm_kpm_metric_defs.h | 2 +- lib/e2/e2sm/e2sm_kpm/e2sm_kpm_report_service_impl.cpp | 2 +- lib/e2/e2sm/e2sm_kpm/e2sm_kpm_report_service_impl.h | 2 +- lib/e2/e2sm/e2sm_kpm/e2sm_kpm_utils.cpp | 2 +- lib/e2/e2sm/e2sm_kpm/e2sm_kpm_utils.h | 2 +- lib/e2/e2sm/e2sm_manager.cpp | 2 +- lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.cpp | 2 +- lib/e2/e2sm/e2sm_rc/e2sm_rc_asn1_packer.h | 2 +- lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.cpp | 2 +- lib/e2/e2sm/e2sm_rc/e2sm_rc_control_action_du_executor.h | 2 +- lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.cpp | 2 +- lib/e2/e2sm/e2sm_rc/e2sm_rc_control_service_impl.h | 2 +- lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.cpp | 2 +- lib/e2/e2sm/e2sm_rc/e2sm_rc_impl.h | 2 +- lib/e2/procedures/e2_indication_procedure.cpp | 2 +- lib/e2/procedures/e2_indication_procedure.h | 2 +- lib/e2/procedures/e2_ric_control_procedure.cpp | 2 +- lib/e2/procedures/e2_ric_control_procedure.h | 2 +- lib/e2/procedures/e2_setup_procedure.cpp | 2 +- lib/e2/procedures/e2_setup_procedure.h | 2 +- lib/e2/procedures/e2_subscription_delete_procedure.cpp | 2 +- lib/e2/procedures/e2_subscription_delete_procedure.h | 2 +- lib/e2/procedures/e2_subscription_setup_procedure.cpp | 2 +- lib/e2/procedures/e2_subscription_setup_procedure.h | 2 +- lib/f1ap/CMakeLists.txt | 2 +- lib/f1ap/common/CMakeLists.txt | 2 +- lib/f1ap/common/asn1_helpers.cpp | 2 +- lib/f1ap/common/asn1_helpers.h | 2 +- lib/f1ap/common/colocated_message_handler.h | 2 +- lib/f1ap/common/f1ap_asn1_packer.cpp | 2 +- lib/f1ap/common/f1ap_asn1_packer.h | 2 +- lib/f1ap/common/f1ap_asn1_utils.h | 2 +- lib/f1ap/common/remote_message_handler.h | 2 +- lib/f1ap/cu_cp/CMakeLists.txt | 2 +- lib/f1ap/cu_cp/f1ap_asn1_converters.h | 2 +- lib/f1ap/cu_cp/f1ap_asn1_helpers.h | 2 +- lib/f1ap/cu_cp/f1ap_cu_factory.cpp | 2 +- lib/f1ap/cu_cp/f1ap_cu_impl.cpp | 2 +- lib/f1ap/cu_cp/f1ap_cu_impl.h | 2 +- .../cu_cp/procedures/ue_context_modification_procedure.cpp | 2 +- lib/f1ap/cu_cp/procedures/ue_context_modification_procedure.h | 2 +- lib/f1ap/cu_cp/procedures/ue_context_release_procedure.cpp | 2 +- lib/f1ap/cu_cp/procedures/ue_context_release_procedure.h | 2 +- lib/f1ap/cu_cp/procedures/ue_context_setup_procedure.cpp | 2 +- lib/f1ap/cu_cp/procedures/ue_context_setup_procedure.h | 2 +- lib/f1ap/cu_cp/ue_context/f1ap_cu_ue_context.h | 2 +- lib/f1ap/cu_cp/ue_context/f1ap_cu_ue_transaction_manager.h | 2 +- lib/f1ap/cu_cp/ue_context/f1ap_ue_logger.h | 2 +- lib/f1ap/du/CMakeLists.txt | 2 +- lib/f1ap/du/f1ap_du_connection_handler.cpp | 2 +- lib/f1ap/du/f1ap_du_connection_handler.h | 2 +- lib/f1ap/du/f1ap_du_context.h | 2 +- lib/f1ap/du/f1ap_du_factory.cpp | 2 +- lib/f1ap/du/f1ap_du_impl.cpp | 2 +- lib/f1ap/du/f1ap_du_impl.h | 2 +- lib/f1ap/du/procedures/CMakeLists.txt | 2 +- lib/f1ap/du/procedures/f1ap_du_event_manager.h | 2 +- lib/f1ap/du/procedures/f1ap_du_setup_procedure.cpp | 2 +- lib/f1ap/du/procedures/f1ap_du_setup_procedure.h | 2 +- lib/f1ap/du/procedures/f1ap_du_ue_context_common.h | 2 +- .../procedures/f1ap_du_ue_context_modification_procedure.cpp | 2 +- .../du/procedures/f1ap_du_ue_context_modification_procedure.h | 2 +- .../du/procedures/f1ap_du_ue_context_release_procedure.cpp | 2 +- lib/f1ap/du/procedures/f1ap_du_ue_context_release_procedure.h | 2 +- lib/f1ap/du/procedures/f1ap_du_ue_context_setup_procedure.cpp | 2 +- lib/f1ap/du/procedures/f1ap_du_ue_context_setup_procedure.h | 2 +- .../du/procedures/gnb_cu_configuration_update_procedure.cpp | 2 +- .../du/procedures/gnb_cu_configuration_update_procedure.h | 2 +- lib/f1ap/du/procedures/proc_logger.h | 2 +- lib/f1ap/du/ue_context/f1ap_du_ue.cpp | 2 +- lib/f1ap/du/ue_context/f1ap_du_ue.h | 2 +- lib/f1ap/du/ue_context/f1ap_du_ue_config_update.cpp | 2 +- lib/f1ap/du/ue_context/f1ap_du_ue_config_update.h | 2 +- lib/f1ap/du/ue_context/f1ap_du_ue_manager.h | 2 +- lib/f1ap/du/ue_context/f1ap_ue_context.h | 2 +- lib/f1ap/du/ue_context/f1c_du_bearer_impl.cpp | 2 +- lib/f1ap/du/ue_context/f1c_du_bearer_impl.h | 2 +- lib/f1ap/du/ue_context/ue_bearer_manager.cpp | 2 +- lib/f1ap/du/ue_context/ue_bearer_manager.h | 2 +- lib/f1u/CMakeLists.txt | 2 +- lib/f1u/cu_up/f1u_bearer_factory.cpp | 2 +- lib/f1u/cu_up/f1u_bearer_impl.cpp | 2 +- lib/f1u/cu_up/f1u_bearer_impl.h | 2 +- lib/f1u/du/f1u_bearer_factory.cpp | 2 +- lib/f1u/du/f1u_bearer_impl.cpp | 2 +- lib/f1u/du/f1u_bearer_impl.h | 2 +- lib/f1u/local_connector/f1u_local_connector.cpp | 2 +- lib/fapi/CMakeLists.txt | 2 +- lib/fapi/logging_decorator_factories.cpp | 2 +- lib/fapi/logging_slot_data_notifier_decorator.cpp | 2 +- lib/fapi/logging_slot_data_notifier_decorator.h | 2 +- lib/fapi/logging_slot_error_notifier_decorator.cpp | 2 +- lib/fapi/logging_slot_error_notifier_decorator.h | 2 +- lib/fapi/logging_slot_gateway_decorator.cpp | 2 +- lib/fapi/logging_slot_gateway_decorator.h | 2 +- lib/fapi/logging_slot_time_notifier_decorator.cpp | 2 +- lib/fapi/logging_slot_time_notifier_decorator.h | 2 +- lib/fapi/message_loggers.cpp | 2 +- lib/fapi/message_loggers.h | 2 +- lib/fapi/message_validators.cpp | 2 +- lib/fapi/pdu_validators/CMakeLists.txt | 2 +- lib/fapi/pdu_validators/dl_csi_pdu.cpp | 2 +- lib/fapi/pdu_validators/dl_csi_pdu.h | 2 +- lib/fapi/pdu_validators/dl_pdcch_pdu.cpp | 2 +- lib/fapi/pdu_validators/dl_pdcch_pdu.h | 2 +- lib/fapi/pdu_validators/dl_pdsch_pdu.cpp | 2 +- lib/fapi/pdu_validators/dl_pdsch_pdu.h | 2 +- lib/fapi/pdu_validators/dl_ssb_pdu.cpp | 2 +- lib/fapi/pdu_validators/dl_ssb_pdu.h | 2 +- lib/fapi/pdu_validators/field_checkers.h | 2 +- lib/fapi/pdu_validators/tx_precoding_and_beamforming_pdu.cpp | 2 +- lib/fapi/pdu_validators/tx_precoding_and_beamforming_pdu.h | 2 +- lib/fapi/pdu_validators/uci_pdus.cpp | 2 +- lib/fapi/pdu_validators/uci_pdus.h | 2 +- lib/fapi/pdu_validators/ul_prach_pdu.cpp | 2 +- lib/fapi/pdu_validators/ul_prach_pdu.h | 2 +- lib/fapi/pdu_validators/ul_pucch_pdu.cpp | 2 +- lib/fapi/pdu_validators/ul_pucch_pdu.h | 2 +- lib/fapi/pdu_validators/ul_pusch_pdu.cpp | 2 +- lib/fapi/pdu_validators/ul_pusch_pdu.h | 2 +- lib/fapi_adaptor/CMakeLists.txt | 2 +- lib/fapi_adaptor/mac/CMakeLists.txt | 2 +- lib/fapi_adaptor/mac/fapi_to_mac_data_msg_translator.cpp | 2 +- lib/fapi_adaptor/mac/fapi_to_mac_data_msg_translator.h | 2 +- lib/fapi_adaptor/mac/fapi_to_mac_error_msg_translator.cpp | 2 +- lib/fapi_adaptor/mac/fapi_to_mac_error_msg_translator.h | 2 +- lib/fapi_adaptor/mac/fapi_to_mac_time_msg_translator.cpp | 2 +- lib/fapi_adaptor/mac/fapi_to_mac_time_msg_translator.h | 2 +- lib/fapi_adaptor/mac/mac_fapi_adaptor_factory_impl.cpp | 2 +- lib/fapi_adaptor/mac/mac_fapi_adaptor_factory_impl.h | 2 +- lib/fapi_adaptor/mac/mac_fapi_adaptor_impl.cpp | 2 +- lib/fapi_adaptor/mac/mac_fapi_adaptor_impl.h | 2 +- lib/fapi_adaptor/mac/mac_to_fapi_translator.cpp | 2 +- lib/fapi_adaptor/mac/mac_to_fapi_translator.h | 2 +- lib/fapi_adaptor/mac/messages/CMakeLists.txt | 2 +- lib/fapi_adaptor/mac/messages/pdcch.cpp | 2 +- lib/fapi_adaptor/mac/messages/pdsch.cpp | 2 +- lib/fapi_adaptor/mac/messages/prach.cpp | 2 +- lib/fapi_adaptor/mac/messages/pucch.cpp | 2 +- lib/fapi_adaptor/mac/messages/pusch.cpp | 2 +- lib/fapi_adaptor/mac/messages/ssb.cpp | 2 +- lib/fapi_adaptor/phy/CMakeLists.txt | 2 +- lib/fapi_adaptor/phy/fapi_to_phy_translator.cpp | 2 +- lib/fapi_adaptor/phy/fapi_to_phy_translator.h | 2 +- lib/fapi_adaptor/phy/messages/CMakeLists.txt | 2 +- lib/fapi_adaptor/phy/messages/csi_rs.cpp | 2 +- lib/fapi_adaptor/phy/messages/pdcch.cpp | 2 +- lib/fapi_adaptor/phy/messages/pdsch.cpp | 2 +- lib/fapi_adaptor/phy/messages/prach.cpp | 2 +- lib/fapi_adaptor/phy/messages/pucch.cpp | 2 +- lib/fapi_adaptor/phy/messages/pusch.cpp | 2 +- lib/fapi_adaptor/phy/messages/ssb.cpp | 2 +- lib/fapi_adaptor/phy/phy_fapi_adaptor_factory_impl.cpp | 2 +- lib/fapi_adaptor/phy/phy_fapi_adaptor_factory_impl.h | 2 +- lib/fapi_adaptor/phy/phy_fapi_adaptor_impl.cpp | 2 +- lib/fapi_adaptor/phy/phy_fapi_adaptor_impl.h | 2 +- lib/fapi_adaptor/phy/phy_to_fapi_results_event_translator.cpp | 2 +- lib/fapi_adaptor/phy/phy_to_fapi_results_event_translator.h | 2 +- lib/fapi_adaptor/phy/phy_to_fapi_time_event_translator.cpp | 2 +- lib/fapi_adaptor/phy/phy_to_fapi_time_event_translator.h | 2 +- lib/fapi_adaptor/precoding_matrix_mapper.cpp | 2 +- lib/fapi_adaptor/precoding_matrix_mapper_functions.h | 2 +- lib/fapi_adaptor/precoding_matrix_repository.cpp | 2 +- lib/fapi_adaptor/precoding_matrix_repository_builder.h | 2 +- lib/fapi_adaptor/precoding_matrix_table_generator.cpp | 2 +- lib/fapi_adaptor/uci_part2_correspondence_generator.cpp | 2 +- lib/fapi_adaptor/uci_part2_correspondence_mapper.cpp | 2 +- lib/fapi_adaptor/uci_part2_correspondence_repository.cpp | 2 +- lib/fapi_adaptor/uci_part2_mapper_functions.h | 2 +- lib/gateways/CMakeLists.txt | 2 +- lib/gateways/sctp_network_gateway_factory.cpp | 2 +- lib/gateways/sctp_network_gateway_impl.cpp | 2 +- lib/gateways/sctp_network_gateway_impl.h | 2 +- lib/gateways/udp_network_gateway_factory.cpp | 2 +- lib/gateways/udp_network_gateway_impl.cpp | 2 +- lib/gateways/udp_network_gateway_impl.h | 2 +- lib/gtpu/CMakeLists.txt | 2 +- lib/gtpu/gtpu_demux_factory.cpp | 2 +- lib/gtpu/gtpu_demux_impl.cpp | 2 +- lib/gtpu/gtpu_demux_impl.h | 2 +- lib/gtpu/gtpu_echo_factory.cpp | 2 +- lib/gtpu/gtpu_echo_impl.h | 2 +- lib/gtpu/gtpu_echo_rx_impl.h | 2 +- lib/gtpu/gtpu_echo_tx_impl.h | 2 +- lib/gtpu/gtpu_pdu.cpp | 2 +- lib/gtpu/gtpu_pdu.h | 2 +- lib/gtpu/gtpu_teid_pool_factory.cpp | 2 +- lib/gtpu/gtpu_teid_pool_impl.h | 2 +- lib/gtpu/gtpu_tunnel_base_rx.h | 2 +- lib/gtpu/gtpu_tunnel_base_tx.h | 2 +- lib/gtpu/gtpu_tunnel_impl_ngu.h | 2 +- lib/gtpu/gtpu_tunnel_logger.h | 2 +- lib/gtpu/gtpu_tunnel_ngu_factory.cpp | 2 +- lib/gtpu/gtpu_tunnel_ngu_rx.h | 2 +- lib/gtpu/gtpu_tunnel_ngu_tx.h | 2 +- lib/hal/CMakeLists.txt | 2 +- lib/hal/dpdk/CMakeLists.txt | 2 +- lib/hal/dpdk/bbdev/CMakeLists.txt | 2 +- lib/hal/dpdk/bbdev/bbdev.cpp | 2 +- lib/hal/dpdk/bbdev/bbdev.h | 2 +- lib/hal/dpdk/bbdev/bbdev_acc.cpp | 2 +- lib/hal/dpdk/bbdev/bbdev_acc_factory.cpp | 2 +- lib/hal/dpdk/bbdev/bbdev_op_pool_factory.cpp | 2 +- lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_decoder.cpp | 2 +- lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_decoder.h | 2 +- lib/hal/dpdk/dpdk.cpp | 2 +- lib/hal/dpdk/dpdk.h | 2 +- lib/hal/dpdk/dpdk_eal_factory.cpp | 2 +- lib/hal/dpdk/mbuf_pool_factory.cpp | 2 +- lib/hal/phy/CMakeLists.txt | 2 +- lib/hal/phy/upper/CMakeLists.txt | 2 +- lib/hal/phy/upper/channel_processors/CMakeLists.txt | 2 +- lib/hal/phy/upper/channel_processors/pusch/CMakeLists.txt | 2 +- .../pusch/ext_harq_buffer_context_repository_factory.cpp | 2 +- lib/hal/phy/upper/channel_processors/pusch/hal_factories.cpp | 2 +- .../pusch/hw_accelerator_pusch_dec_acc100_impl.cpp | 2 +- .../pusch/hw_accelerator_pusch_dec_acc100_impl.h | 2 +- .../pusch/hw_accelerator_pusch_dec_impl.cpp | 2 +- .../channel_processors/pusch/hw_accelerator_pusch_dec_impl.h | 2 +- lib/instrumentation/CMakeLists.txt | 2 +- lib/instrumentation/traces/du_traces.cpp | 2 +- lib/instrumentation/traces/ru_traces.cpp | 2 +- lib/instrumentation/traces/up_traces.cpp | 2 +- lib/mac/CMakeLists.txt | 2 +- lib/mac/config/mac_cell_group_config_factory.cpp | 2 +- lib/mac/config/mac_config_helpers.cpp | 2 +- lib/mac/mac_config_interfaces.h | 2 +- lib/mac/mac_ctrl/mac_config.h | 2 +- lib/mac/mac_ctrl/mac_controller.cpp | 2 +- lib/mac/mac_ctrl/mac_controller.h | 2 +- lib/mac/mac_ctrl/mac_scheduler_configurator.h | 2 +- lib/mac/mac_ctrl/ue_creation_procedure.cpp | 2 +- lib/mac/mac_ctrl/ue_creation_procedure.h | 2 +- lib/mac/mac_ctrl/ue_delete_procedure.cpp | 2 +- lib/mac/mac_ctrl/ue_delete_procedure.h | 2 +- lib/mac/mac_ctrl/ue_reconfiguration_procedure.cpp | 2 +- lib/mac/mac_ctrl/ue_reconfiguration_procedure.h | 2 +- lib/mac/mac_dl/dl_sch_pdu_assembler.cpp | 2 +- lib/mac/mac_dl/dl_sch_pdu_assembler.h | 2 +- lib/mac/mac_dl/mac_cell_processor.cpp | 2 +- lib/mac/mac_dl/mac_cell_processor.h | 2 +- lib/mac/mac_dl/mac_dl_processor.cpp | 2 +- lib/mac/mac_dl/mac_dl_processor.h | 2 +- lib/mac/mac_dl/mac_dl_ue_manager.cpp | 2 +- lib/mac/mac_dl/mac_dl_ue_manager.h | 2 +- lib/mac/mac_dl/mac_scheduler_cell_info_handler.h | 2 +- lib/mac/mac_dl/paging_pdu_assembler.cpp | 2 +- lib/mac/mac_dl/paging_pdu_assembler.h | 2 +- lib/mac/mac_dl/rar_pdu_assembler.cpp | 2 +- lib/mac/mac_dl/rar_pdu_assembler.h | 2 +- lib/mac/mac_dl/sib_pdu_assembler.h | 2 +- lib/mac/mac_dl/ssb_assembler.cpp | 2 +- lib/mac/mac_dl/ssb_assembler.h | 2 +- lib/mac/mac_factory.cpp | 2 +- lib/mac/mac_impl.cpp | 2 +- lib/mac/mac_impl.h | 2 +- lib/mac/mac_sched/mac_scheduler_adapter.h | 2 +- lib/mac/mac_sched/rlf_detector.h | 2 +- lib/mac/mac_sched/srsran_scheduler_adapter.cpp | 2 +- lib/mac/mac_sched/srsran_scheduler_adapter.h | 2 +- lib/mac/mac_sched/uci_cell_decoder.cpp | 2 +- lib/mac/mac_sched/uci_cell_decoder.h | 2 +- lib/mac/mac_ul/lcid_ul_sch.h | 2 +- lib/mac/mac_ul/mac_scheduler_ce_info_handler.h | 2 +- lib/mac/mac_ul/mac_ul_processor.h | 2 +- lib/mac/mac_ul/mac_ul_sch_pdu.cpp | 2 +- lib/mac/mac_ul/mac_ul_sch_pdu.h | 2 +- lib/mac/mac_ul/mac_ul_ue_manager.cpp | 2 +- lib/mac/mac_ul/mac_ul_ue_manager.h | 2 +- lib/mac/mac_ul/pdu_rx_handler.cpp | 2 +- lib/mac/mac_ul/pdu_rx_handler.h | 2 +- lib/mac/mac_ul/ul_bsr.cpp | 2 +- lib/mac/mac_ul/ul_bsr.h | 2 +- lib/mac/mac_ul/ul_phr.h | 2 +- lib/mac/rnti_manager.h | 2 +- lib/ngap/CMakeLists.txt | 2 +- lib/ngap/ngap_asn1_converters.h | 2 +- lib/ngap/ngap_asn1_helpers.h | 2 +- lib/ngap/ngap_asn1_packer.cpp | 2 +- lib/ngap/ngap_asn1_packer.h | 2 +- lib/ngap/ngap_asn1_utils.h | 2 +- lib/ngap/ngap_context.h | 2 +- lib/ngap/ngap_factory.cpp | 2 +- lib/ngap/ngap_impl.cpp | 2 +- lib/ngap/ngap_impl.h | 2 +- lib/ngap/procedures/ng_setup_procedure.cpp | 2 +- lib/ngap/procedures/ng_setup_procedure.h | 2 +- .../procedures/ngap_dl_nas_message_transfer_procedure.cpp | 2 +- lib/ngap/procedures/ngap_dl_nas_message_transfer_procedure.h | 2 +- lib/ngap/procedures/ngap_handover_preparation_procedure.cpp | 2 +- lib/ngap/procedures/ngap_handover_preparation_procedure.h | 2 +- .../ngap_handover_resource_allocation_procedure.cpp | 2 +- .../procedures/ngap_handover_resource_allocation_procedure.h | 2 +- lib/ngap/procedures/ngap_initial_context_setup_procedure.cpp | 2 +- lib/ngap/procedures/ngap_initial_context_setup_procedure.h | 2 +- .../procedures/ngap_pdu_session_resource_modify_procedure.cpp | 2 +- .../procedures/ngap_pdu_session_resource_modify_procedure.h | 2 +- .../ngap_pdu_session_resource_release_procedure.cpp | 2 +- .../procedures/ngap_pdu_session_resource_release_procedure.h | 2 +- .../procedures/ngap_pdu_session_resource_setup_procedure.cpp | 2 +- .../procedures/ngap_pdu_session_resource_setup_procedure.h | 2 +- lib/ngap/procedures/ngap_procedure_helpers.h | 2 +- lib/ngap/procedures/ngap_transaction_manager.h | 2 +- lib/ngap/procedures/ngap_ue_context_release_procedure.cpp | 2 +- lib/ngap/procedures/ngap_ue_context_release_procedure.h | 2 +- lib/ngap/ue_context/ngap_ue_context.h | 2 +- lib/ngap/ue_context/ngap_ue_logger.h | 2 +- lib/ofh/CMakeLists.txt | 2 +- lib/ofh/compression/CMakeLists.txt | 2 +- lib/ofh/compression/avx2_helpers.h | 2 +- lib/ofh/compression/avx512_helpers.h | 2 +- lib/ofh/compression/compressed_prb_packer.cpp | 2 +- lib/ofh/compression/compressed_prb_packer.h | 2 +- lib/ofh/compression/compressed_prb_unpacker.cpp | 2 +- lib/ofh/compression/compressed_prb_unpacker.h | 2 +- lib/ofh/compression/compression_factory.cpp | 2 +- lib/ofh/compression/iq_compression_bfp_avx2.cpp | 2 +- lib/ofh/compression/iq_compression_bfp_avx2.h | 2 +- lib/ofh/compression/iq_compression_bfp_avx512.cpp | 2 +- lib/ofh/compression/iq_compression_bfp_avx512.h | 2 +- lib/ofh/compression/iq_compression_bfp_impl.cpp | 2 +- lib/ofh/compression/iq_compression_bfp_impl.h | 2 +- lib/ofh/compression/iq_compression_bfp_neon.cpp | 2 +- lib/ofh/compression/iq_compression_bfp_neon.h | 2 +- lib/ofh/compression/iq_compression_death_impl.cpp | 2 +- lib/ofh/compression/iq_compression_death_impl.h | 2 +- lib/ofh/compression/iq_compression_none_avx512.cpp | 2 +- lib/ofh/compression/iq_compression_none_avx512.h | 2 +- lib/ofh/compression/iq_compression_none_impl.cpp | 2 +- lib/ofh/compression/iq_compression_none_impl.h | 2 +- lib/ofh/compression/iq_compressor_selector.cpp | 2 +- lib/ofh/compression/iq_compressor_selector.h | 2 +- lib/ofh/compression/iq_decompressor_selector.cpp | 2 +- lib/ofh/compression/iq_decompressor_selector.h | 2 +- lib/ofh/compression/neon_helpers.h | 2 +- lib/ofh/compression/packing_utils_avx2.cpp | 2 +- lib/ofh/compression/packing_utils_avx2.h | 2 +- lib/ofh/compression/packing_utils_avx512.cpp | 2 +- lib/ofh/compression/packing_utils_avx512.h | 2 +- lib/ofh/compression/packing_utils_neon.cpp | 2 +- lib/ofh/compression/packing_utils_neon.h | 2 +- lib/ofh/compression/quantizer.h | 2 +- lib/ofh/ecpri/CMakeLists.txt | 2 +- lib/ofh/ecpri/ecpri_factories.cpp | 2 +- lib/ofh/ecpri/ecpri_packet_builder_impl.cpp | 2 +- lib/ofh/ecpri/ecpri_packet_builder_impl.h | 2 +- lib/ofh/ecpri/ecpri_packet_decoder_impl.cpp | 2 +- lib/ofh/ecpri/ecpri_packet_decoder_impl.h | 2 +- lib/ofh/ethernet/CMakeLists.txt | 2 +- lib/ofh/ethernet/dpdk/CMakeLists.txt | 2 +- lib/ofh/ethernet/dpdk/dpdk_ethernet_factories.cpp | 2 +- lib/ofh/ethernet/dpdk/dpdk_ethernet_factories.h | 2 +- lib/ofh/ethernet/dpdk/dpdk_ethernet_receiver.cpp | 2 +- lib/ofh/ethernet/dpdk/dpdk_ethernet_receiver.h | 2 +- lib/ofh/ethernet/dpdk/dpdk_ethernet_transmitter.cpp | 2 +- lib/ofh/ethernet/dpdk/dpdk_ethernet_transmitter.h | 2 +- lib/ofh/ethernet/ethernet_constants.h | 2 +- lib/ofh/ethernet/ethernet_factories.cpp | 2 +- lib/ofh/ethernet/ethernet_receiver_impl.cpp | 2 +- lib/ofh/ethernet/ethernet_receiver_impl.h | 2 +- lib/ofh/ethernet/ethernet_transmitter_impl.cpp | 2 +- lib/ofh/ethernet/ethernet_transmitter_impl.h | 2 +- lib/ofh/ethernet/vlan_ethernet_frame_builder_impl.cpp | 2 +- lib/ofh/ethernet/vlan_ethernet_frame_builder_impl.h | 2 +- lib/ofh/ethernet/vlan_ethernet_frame_decoder_impl.cpp | 2 +- lib/ofh/ethernet/vlan_ethernet_frame_decoder_impl.h | 2 +- lib/ofh/ofh_factories.cpp | 2 +- lib/ofh/ofh_sector_controller.cpp | 2 +- lib/ofh/ofh_sector_controller.h | 2 +- lib/ofh/ofh_sector_impl.cpp | 2 +- lib/ofh/ofh_sector_impl.h | 2 +- lib/ofh/receiver/CMakeLists.txt | 2 +- lib/ofh/receiver/ofh_data_flow_uplane_uplink_data.h | 2 +- lib/ofh/receiver/ofh_data_flow_uplane_uplink_data_impl.cpp | 2 +- lib/ofh/receiver/ofh_data_flow_uplane_uplink_data_impl.h | 2 +- lib/ofh/receiver/ofh_data_flow_uplane_uplink_prach.h | 2 +- lib/ofh/receiver/ofh_data_flow_uplane_uplink_prach_impl.cpp | 2 +- lib/ofh/receiver/ofh_data_flow_uplane_uplink_prach_impl.h | 2 +- lib/ofh/receiver/ofh_message_receiver.cpp | 2 +- lib/ofh/receiver/ofh_message_receiver.h | 2 +- lib/ofh/receiver/ofh_receiver_controller.cpp | 2 +- lib/ofh/receiver/ofh_receiver_controller.h | 2 +- lib/ofh/receiver/ofh_receiver_factories.cpp | 2 +- lib/ofh/receiver/ofh_receiver_factories.h | 2 +- lib/ofh/receiver/ofh_receiver_impl.cpp | 2 +- lib/ofh/receiver/ofh_receiver_impl.h | 2 +- lib/ofh/receiver/ofh_rx_window_checker.cpp | 2 +- lib/ofh/receiver/ofh_rx_window_checker.h | 2 +- lib/ofh/receiver/ofh_uplane_prach_data_flow_notifier.cpp | 2 +- lib/ofh/receiver/ofh_uplane_prach_data_flow_notifier.h | 2 +- lib/ofh/receiver/ofh_uplane_prach_symbol_data_flow_writer.cpp | 2 +- lib/ofh/receiver/ofh_uplane_prach_symbol_data_flow_writer.h | 2 +- lib/ofh/receiver/ofh_uplane_rx_symbol_data_flow_notifier.cpp | 2 +- lib/ofh/receiver/ofh_uplane_rx_symbol_data_flow_notifier.h | 2 +- lib/ofh/receiver/ofh_uplane_rx_symbol_data_flow_writer.cpp | 2 +- lib/ofh/receiver/ofh_uplane_rx_symbol_data_flow_writer.h | 2 +- lib/ofh/serdes/CMakeLists.txt | 2 +- .../ofh_cplane_message_builder_dynamic_compression_impl.cpp | 2 +- .../ofh_cplane_message_builder_dynamic_compression_impl.h | 2 +- lib/ofh/serdes/ofh_cplane_message_builder_impl.cpp | 2 +- lib/ofh/serdes/ofh_cplane_message_builder_impl.h | 2 +- .../ofh_cplane_message_builder_static_compression_impl.cpp | 2 +- .../ofh_cplane_message_builder_static_compression_impl.h | 2 +- lib/ofh/serdes/ofh_cuplane_constants.h | 2 +- lib/ofh/serdes/ofh_serdes_factories.cpp | 2 +- .../ofh_uplane_message_builder_dynamic_compression_impl.cpp | 2 +- .../ofh_uplane_message_builder_dynamic_compression_impl.h | 2 +- lib/ofh/serdes/ofh_uplane_message_builder_impl.cpp | 2 +- lib/ofh/serdes/ofh_uplane_message_builder_impl.h | 2 +- .../ofh_uplane_message_builder_static_compression_impl.cpp | 2 +- .../ofh_uplane_message_builder_static_compression_impl.h | 2 +- .../ofh_uplane_message_decoder_dynamic_compression_impl.cpp | 2 +- .../ofh_uplane_message_decoder_dynamic_compression_impl.h | 2 +- lib/ofh/serdes/ofh_uplane_message_decoder_impl.cpp | 2 +- lib/ofh/serdes/ofh_uplane_message_decoder_impl.h | 2 +- .../ofh_uplane_message_decoder_static_compression_impl.cpp | 2 +- .../ofh_uplane_message_decoder_static_compression_impl.h | 2 +- lib/ofh/support/network_order_binary_deserializer.h | 2 +- lib/ofh/support/network_order_binary_serializer.h | 2 +- lib/ofh/support/prach_context_repository.h | 2 +- lib/ofh/support/uplink_context_repository.h | 2 +- lib/ofh/support/uplink_cplane_context_repository.h | 2 +- lib/ofh/timing/CMakeLists.txt | 2 +- lib/ofh/timing/ofh_timing_manager_impl.cpp | 2 +- lib/ofh/timing/ofh_timing_manager_impl.h | 2 +- lib/ofh/timing/realtime_timing_worker.cpp | 2 +- lib/ofh/timing/realtime_timing_worker.h | 2 +- lib/ofh/transmitter/CMakeLists.txt | 2 +- lib/ofh/transmitter/helpers.h | 2 +- .../transmitter/ofh_data_flow_cplane_scheduling_commands.h | 2 +- .../ofh_data_flow_cplane_scheduling_commands_impl.cpp | 2 +- .../ofh_data_flow_cplane_scheduling_commands_impl.h | 2 +- ...ofh_data_flow_cplane_scheduling_commands_task_dispatcher.h | 2 +- lib/ofh/transmitter/ofh_data_flow_uplane_downlink_data.h | 2 +- .../transmitter/ofh_data_flow_uplane_downlink_data_impl.cpp | 2 +- lib/ofh/transmitter/ofh_data_flow_uplane_downlink_data_impl.h | 2 +- .../ofh_data_flow_uplane_downlink_task_dispatcher.h | 2 +- lib/ofh/transmitter/ofh_downlink_handler_broadcast_impl.cpp | 2 +- lib/ofh/transmitter/ofh_downlink_handler_broadcast_impl.h | 2 +- lib/ofh/transmitter/ofh_downlink_handler_impl.cpp | 2 +- lib/ofh/transmitter/ofh_downlink_handler_impl.h | 2 +- lib/ofh/transmitter/ofh_downlink_manager.h | 2 +- lib/ofh/transmitter/ofh_downlink_manager_broadcast_impl.cpp | 2 +- lib/ofh/transmitter/ofh_downlink_manager_broadcast_impl.h | 2 +- lib/ofh/transmitter/ofh_downlink_manager_impl.cpp | 2 +- lib/ofh/transmitter/ofh_downlink_manager_impl.h | 2 +- lib/ofh/transmitter/ofh_message_transmitter_impl.cpp | 2 +- lib/ofh/transmitter/ofh_message_transmitter_impl.h | 2 +- lib/ofh/transmitter/ofh_transmitter_factories.cpp | 2 +- lib/ofh/transmitter/ofh_transmitter_factories.h | 2 +- lib/ofh/transmitter/ofh_transmitter_impl.cpp | 2 +- lib/ofh/transmitter/ofh_transmitter_impl.h | 2 +- .../transmitter/ofh_transmitter_ota_symbol_task_dispatcher.h | 2 +- lib/ofh/transmitter/ofh_tx_window_checker.h | 2 +- lib/ofh/transmitter/ofh_uplane_fragment_size_calculator.cpp | 2 +- lib/ofh/transmitter/ofh_uplane_fragment_size_calculator.h | 2 +- lib/ofh/transmitter/ofh_uplink_request_handler_impl.cpp | 2 +- lib/ofh/transmitter/ofh_uplink_request_handler_impl.h | 2 +- .../transmitter/ofh_uplink_request_handler_task_dispatcher.h | 2 +- lib/ofh/transmitter/scoped_frame_buffer.h | 2 +- lib/ofh/transmitter/sequence_identifier_generator.h | 2 +- lib/pcap/CMakeLists.txt | 2 +- lib/pcap/backend_pcap_writer.cpp | 2 +- lib/pcap/backend_pcap_writer.h | 2 +- lib/pcap/dlt_pcap_impl.cpp | 2 +- lib/pcap/dlt_pcap_impl.h | 2 +- lib/pcap/mac_pcap_impl.cpp | 2 +- lib/pcap/mac_pcap_impl.h | 2 +- lib/pcap/pcap_file_writer.cpp | 2 +- lib/pcap/pcap_file_writer.h | 2 +- lib/pcap/pcap_rlc_pdu_context.cpp | 2 +- lib/pcap/rlc_pcap_impl.cpp | 2 +- lib/pcap/rlc_pcap_impl.h | 2 +- lib/pdcp/CMakeLists.txt | 2 +- lib/pdcp/pdcp_bearer_logger.h | 2 +- lib/pdcp/pdcp_entity_impl.h | 2 +- lib/pdcp/pdcp_entity_rx.cpp | 2 +- lib/pdcp/pdcp_entity_rx.h | 2 +- lib/pdcp/pdcp_entity_tx.cpp | 2 +- lib/pdcp/pdcp_entity_tx.h | 2 +- lib/pdcp/pdcp_entity_tx_rx_base.h | 2 +- lib/pdcp/pdcp_factory.cpp | 2 +- lib/pdcp/pdcp_interconnect.h | 2 +- lib/pdcp/pdcp_pdu.cpp | 2 +- lib/pdcp/pdcp_pdu.h | 2 +- lib/pdcp/pdcp_rx_metrics_impl.h | 2 +- lib/pdcp/pdcp_sn.h | 2 +- lib/pdcp/pdcp_tx_metrics_impl.h | 2 +- lib/phy/CMakeLists.txt | 2 +- lib/phy/generic_functions/CMakeLists.txt | 2 +- lib/phy/generic_functions/dft_processor_fftw_impl.cpp | 2 +- lib/phy/generic_functions/dft_processor_fftw_impl.h | 2 +- lib/phy/generic_functions/generic_functions_factories.cpp | 2 +- lib/phy/generic_functions/precoding/CMakeLists.txt | 2 +- lib/phy/generic_functions/precoding/channel_precoder_avx2.cpp | 2 +- lib/phy/generic_functions/precoding/channel_precoder_avx2.h | 2 +- .../generic_functions/precoding/channel_precoder_avx512.cpp | 2 +- lib/phy/generic_functions/precoding/channel_precoder_avx512.h | 2 +- .../generic_functions/precoding/channel_precoder_generic.cpp | 2 +- .../generic_functions/precoding/channel_precoder_generic.h | 2 +- lib/phy/generic_functions/precoding/channel_precoder_impl.cpp | 2 +- lib/phy/generic_functions/precoding/channel_precoder_impl.h | 2 +- lib/phy/generic_functions/precoding/precoding_factories.cpp | 2 +- lib/phy/lower/CMakeLists.txt | 2 +- lib/phy/lower/amplitude_controller/CMakeLists.txt | 2 +- .../amplitude_controller_clipping_impl.cpp | 2 +- .../amplitude_controller/amplitude_controller_clipping_impl.h | 2 +- .../amplitude_controller/amplitude_controller_factories.cpp | 2 +- .../amplitude_controller_scaling_impl.cpp | 2 +- .../amplitude_controller/amplitude_controller_scaling_impl.h | 2 +- lib/phy/lower/lower_phy_baseband_processor.cpp | 2 +- lib/phy/lower/lower_phy_baseband_processor.h | 2 +- lib/phy/lower/lower_phy_factory.cpp | 2 +- lib/phy/lower/lower_phy_impl.cpp | 2 +- lib/phy/lower/lower_phy_impl.h | 2 +- lib/phy/lower/modulation/CMakeLists.txt | 2 +- lib/phy/lower/modulation/modulation_factories.cpp | 2 +- lib/phy/lower/modulation/ofdm_demodulator_impl.cpp | 2 +- lib/phy/lower/modulation/ofdm_demodulator_impl.h | 2 +- lib/phy/lower/modulation/ofdm_modulator_impl.cpp | 2 +- lib/phy/lower/modulation/ofdm_modulator_impl.h | 2 +- lib/phy/lower/modulation/ofdm_prach_demodulator_impl.cpp | 2 +- lib/phy/lower/modulation/ofdm_prach_demodulator_impl.h | 2 +- lib/phy/lower/modulation/phase_compensation_lut.h | 2 +- lib/phy/lower/processors/CMakeLists.txt | 2 +- lib/phy/lower/processors/adaptors/CMakeLists.txt | 2 +- .../lower/processors/adaptors/processor_handler_adaptor.cpp | 2 +- lib/phy/lower/processors/adaptors/processor_handler_adaptor.h | 2 +- .../lower/processors/adaptors/processor_notifier_adaptor.cpp | 2 +- .../lower/processors/adaptors/processor_notifier_adaptor.h | 2 +- lib/phy/lower/processors/downlink/CMakeLists.txt | 2 +- .../processors/downlink/downlink_processor_baseband_impl.cpp | 2 +- .../processors/downlink/downlink_processor_baseband_impl.h | 2 +- .../processors/downlink/downlink_processor_factories.cpp | 2 +- lib/phy/lower/processors/downlink/downlink_processor_impl.cpp | 2 +- lib/phy/lower/processors/downlink/downlink_processor_impl.h | 2 +- lib/phy/lower/processors/downlink/pdxch/CMakeLists.txt | 2 +- .../processors/downlink/pdxch/pdxch_processor_factories.cpp | 2 +- .../lower/processors/downlink/pdxch/pdxch_processor_impl.cpp | 2 +- .../lower/processors/downlink/pdxch/pdxch_processor_impl.h | 2 +- lib/phy/lower/processors/resource_grid_request_pool.h | 2 +- lib/phy/lower/processors/uplink/CMakeLists.txt | 2 +- lib/phy/lower/processors/uplink/prach/CMakeLists.txt | 2 +- .../processors/uplink/prach/prach_processor_factories.cpp | 2 +- lib/phy/lower/processors/uplink/prach/prach_processor_impl.h | 2 +- .../lower/processors/uplink/prach/prach_processor_worker.cpp | 2 +- .../lower/processors/uplink/prach/prach_processor_worker.h | 2 +- lib/phy/lower/processors/uplink/puxch/CMakeLists.txt | 2 +- .../processors/uplink/puxch/puxch_processor_factories.cpp | 2 +- .../lower/processors/uplink/puxch/puxch_processor_impl.cpp | 2 +- lib/phy/lower/processors/uplink/puxch/puxch_processor_impl.h | 2 +- .../lower/processors/uplink/uplink_processor_factories.cpp | 2 +- lib/phy/lower/processors/uplink/uplink_processor_impl.cpp | 2 +- lib/phy/lower/processors/uplink/uplink_processor_impl.h | 2 +- lib/phy/support/CMakeLists.txt | 2 +- lib/phy/support/interpolator/interpolator_linear_impl.cpp | 2 +- lib/phy/support/interpolator/interpolator_linear_impl.h | 2 +- lib/phy/support/prach_buffer_impl.h | 2 +- lib/phy/support/prach_buffer_pool_impl.cpp | 2 +- lib/phy/support/prach_buffer_pool_impl.h | 2 +- lib/phy/support/re_pattern.cpp | 2 +- lib/phy/support/resource_grid_dimensions.h | 2 +- lib/phy/support/resource_grid_impl.cpp | 2 +- lib/phy/support/resource_grid_impl.h | 2 +- lib/phy/support/resource_grid_mapper_impl.cpp | 2 +- lib/phy/support/resource_grid_mapper_impl.h | 2 +- lib/phy/support/resource_grid_pool_asynchronous_impl.cpp | 2 +- lib/phy/support/resource_grid_pool_asynchronous_impl.h | 2 +- lib/phy/support/resource_grid_pool_generic_impl.cpp | 2 +- lib/phy/support/resource_grid_pool_generic_impl.h | 2 +- lib/phy/support/resource_grid_reader_impl.cpp | 2 +- lib/phy/support/resource_grid_reader_impl.h | 2 +- lib/phy/support/resource_grid_writer_impl.cpp | 2 +- lib/phy/support/resource_grid_writer_impl.h | 2 +- lib/phy/support/support_factories.cpp | 2 +- lib/phy/upper/CMakeLists.txt | 2 +- lib/phy/upper/channel_coding/CMakeLists.txt | 2 +- lib/phy/upper/channel_coding/channel_coding_factories.cpp | 2 +- lib/phy/upper/channel_coding/crc_calculator_clmul_impl.cpp | 2 +- lib/phy/upper/channel_coding/crc_calculator_clmul_impl.h | 2 +- lib/phy/upper/channel_coding/crc_calculator_generic_impl.cpp | 2 +- lib/phy/upper/channel_coding/crc_calculator_generic_impl.h | 2 +- lib/phy/upper/channel_coding/crc_calculator_lut_impl.cpp | 2 +- lib/phy/upper/channel_coding/crc_calculator_lut_impl.h | 2 +- lib/phy/upper/channel_coding/ldpc/CMakeLists.txt | 2 +- lib/phy/upper/channel_coding/ldpc/avx2_support.h | 2 +- lib/phy/upper/channel_coding/ldpc/avx512_support.h | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_decoder_avx2.cpp | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_decoder_avx2.h | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_decoder_avx512.cpp | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_decoder_avx512.h | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_decoder_generic.cpp | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_decoder_generic.h | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_decoder_impl.cpp | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_decoder_impl.h | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_decoder_neon.cpp | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_decoder_neon.h | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_encoder_avx2.cpp | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_encoder_avx2.h | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_encoder_generic.cpp | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_encoder_generic.h | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_encoder_impl.cpp | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_encoder_impl.h | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_encoder_neon.cpp | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_encoder_neon.h | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_graph_impl.cpp | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_graph_impl.h | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_luts_impl.cpp | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_luts_impl.h | 2 +- .../channel_coding/ldpc/ldpc_rate_dematcher_avx2_impl.cpp | 2 +- .../upper/channel_coding/ldpc/ldpc_rate_dematcher_avx2_impl.h | 2 +- .../channel_coding/ldpc/ldpc_rate_dematcher_avx512_impl.cpp | 2 +- .../channel_coding/ldpc/ldpc_rate_dematcher_avx512_impl.h | 2 +- .../upper/channel_coding/ldpc/ldpc_rate_dematcher_impl.cpp | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_rate_dematcher_impl.h | 2 +- .../channel_coding/ldpc/ldpc_rate_dematcher_neon_impl.cpp | 2 +- .../upper/channel_coding/ldpc/ldpc_rate_dematcher_neon_impl.h | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_rate_matcher_impl.cpp | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_rate_matcher_impl.h | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_segmenter_impl.cpp | 2 +- lib/phy/upper/channel_coding/ldpc/ldpc_segmenter_impl.h | 2 +- lib/phy/upper/channel_coding/ldpc/neon_support.h | 2 +- lib/phy/upper/channel_coding/ldpc/simd_support.h | 2 +- lib/phy/upper/channel_coding/ldpc/simd_types.h | 2 +- lib/phy/upper/channel_coding/polar/CMakeLists.txt | 2 +- lib/phy/upper/channel_coding/polar/polar_allocator_impl.cpp | 2 +- lib/phy/upper/channel_coding/polar/polar_allocator_impl.h | 2 +- lib/phy/upper/channel_coding/polar/polar_code_impl.cpp | 2 +- lib/phy/upper/channel_coding/polar/polar_code_impl.h | 2 +- lib/phy/upper/channel_coding/polar/polar_deallocator_impl.cpp | 2 +- lib/phy/upper/channel_coding/polar/polar_deallocator_impl.h | 2 +- lib/phy/upper/channel_coding/polar/polar_decoder_impl.cpp | 2 +- lib/phy/upper/channel_coding/polar/polar_decoder_impl.h | 2 +- lib/phy/upper/channel_coding/polar/polar_encoder_impl.cpp | 2 +- lib/phy/upper/channel_coding/polar/polar_encoder_impl.h | 2 +- lib/phy/upper/channel_coding/polar/polar_interleaver_impl.cpp | 2 +- lib/phy/upper/channel_coding/polar/polar_interleaver_impl.h | 2 +- .../upper/channel_coding/polar/polar_rate_dematcher_impl.cpp | 2 +- .../upper/channel_coding/polar/polar_rate_dematcher_impl.h | 2 +- .../upper/channel_coding/polar/polar_rate_matcher_impl.cpp | 2 +- lib/phy/upper/channel_coding/polar/polar_rate_matcher_impl.h | 2 +- .../upper/channel_coding/short/short_block_detector_impl.cpp | 2 +- .../upper/channel_coding/short/short_block_detector_impl.h | 2 +- .../upper/channel_coding/short/short_block_encoder_impl.cpp | 2 +- lib/phy/upper/channel_coding/short/short_block_encoder_impl.h | 2 +- lib/phy/upper/channel_modulation/CMakeLists.txt | 2 +- lib/phy/upper/channel_modulation/avx2_helpers.h | 2 +- .../upper/channel_modulation/channel_modulation_factories.cpp | 2 +- lib/phy/upper/channel_modulation/demodulation_mapper_impl.cpp | 2 +- lib/phy/upper/channel_modulation/demodulation_mapper_impl.h | 2 +- .../upper/channel_modulation/demodulation_mapper_intervals.h | 2 +- .../upper/channel_modulation/demodulation_mapper_qam16.cpp | 2 +- lib/phy/upper/channel_modulation/demodulation_mapper_qam16.h | 2 +- .../upper/channel_modulation/demodulation_mapper_qam256.cpp | 2 +- lib/phy/upper/channel_modulation/demodulation_mapper_qam256.h | 2 +- .../upper/channel_modulation/demodulation_mapper_qam64.cpp | 2 +- lib/phy/upper/channel_modulation/demodulation_mapper_qam64.h | 2 +- lib/phy/upper/channel_modulation/demodulation_mapper_qpsk.cpp | 2 +- lib/phy/upper/channel_modulation/demodulation_mapper_qpsk.h | 2 +- .../upper/channel_modulation/evm_calculator_generic_impl.cpp | 2 +- .../upper/channel_modulation/evm_calculator_generic_impl.h | 2 +- lib/phy/upper/channel_modulation/modulation_mapper_impl.cpp | 2 +- lib/phy/upper/channel_modulation/modulation_mapper_impl.h | 2 +- lib/phy/upper/channel_modulation/neon_helpers.h | 2 +- lib/phy/upper/channel_processors/CMakeLists.txt | 2 +- .../upper/channel_processors/channel_processor_factories.cpp | 2 +- lib/phy/upper/channel_processors/pbch_encoder_impl.cpp | 2 +- lib/phy/upper/channel_processors/pbch_encoder_impl.h | 2 +- lib/phy/upper/channel_processors/pbch_modulator_impl.cpp | 2 +- lib/phy/upper/channel_processors/pbch_modulator_impl.h | 2 +- lib/phy/upper/channel_processors/pdcch_encoder_impl.cpp | 2 +- lib/phy/upper/channel_processors/pdcch_encoder_impl.h | 2 +- lib/phy/upper/channel_processors/pdcch_modulator_impl.cpp | 2 +- lib/phy/upper/channel_processors/pdcch_modulator_impl.h | 2 +- lib/phy/upper/channel_processors/pdcch_processor_impl.cpp | 2 +- lib/phy/upper/channel_processors/pdcch_processor_impl.h | 2 +- lib/phy/upper/channel_processors/pdcch_processor_pool.h | 2 +- .../upper/channel_processors/pdsch_codeblock_processor.cpp | 2 +- lib/phy/upper/channel_processors/pdsch_codeblock_processor.h | 2 +- lib/phy/upper/channel_processors/pdsch_encoder_impl.cpp | 2 +- lib/phy/upper/channel_processors/pdsch_encoder_impl.h | 2 +- lib/phy/upper/channel_processors/pdsch_modulator_impl.cpp | 2 +- lib/phy/upper/channel_processors/pdsch_modulator_impl.h | 2 +- .../channel_processors/pdsch_processor_concurrent_impl.cpp | 2 +- .../channel_processors/pdsch_processor_concurrent_impl.h | 2 +- lib/phy/upper/channel_processors/pdsch_processor_impl.cpp | 2 +- lib/phy/upper/channel_processors/pdsch_processor_impl.h | 2 +- .../upper/channel_processors/pdsch_processor_lite_impl.cpp | 2 +- lib/phy/upper/channel_processors/pdsch_processor_lite_impl.h | 2 +- lib/phy/upper/channel_processors/pdsch_processor_pool.h | 2 +- .../channel_processors/pdsch_processor_validator_impl.cpp | 2 +- .../upper/channel_processors/pdsch_processor_validator_impl.h | 2 +- .../upper/channel_processors/prach_detector_generic_impl.cpp | 2 +- .../upper/channel_processors/prach_detector_generic_impl.h | 2 +- .../channel_processors/prach_detector_generic_thresholds.h | 2 +- .../channel_processors/prach_detector_phy_validator_impl.cpp | 2 +- lib/phy/upper/channel_processors/prach_detector_pool.h | 2 +- lib/phy/upper/channel_processors/prach_generator_impl.cpp | 2 +- lib/phy/upper/channel_processors/prach_generator_impl.h | 2 +- lib/phy/upper/channel_processors/pucch_demodulator_impl.cpp | 2 +- lib/phy/upper/channel_processors/pucch_demodulator_impl.h | 2 +- lib/phy/upper/channel_processors/pucch_detector_impl.cpp | 2 +- lib/phy/upper/channel_processors/pucch_detector_impl.h | 2 +- lib/phy/upper/channel_processors/pucch_processor_impl.cpp | 2 +- lib/phy/upper/channel_processors/pucch_processor_impl.h | 2 +- lib/phy/upper/channel_processors/pucch_processor_pool.h | 2 +- lib/phy/upper/channel_processors/pusch/CMakeLists.txt | 2 +- lib/phy/upper/channel_processors/pusch/factories.cpp | 2 +- .../pusch/logging_pusch_processor_decorator.h | 2 +- .../channel_processors/pusch/pusch_codeblock_decoder.cpp | 2 +- .../upper/channel_processors/pusch/pusch_codeblock_decoder.h | 2 +- .../channel_processors/pusch/pusch_decoder_buffer_dummy.h | 2 +- .../upper/channel_processors/pusch/pusch_decoder_hw_impl.cpp | 2 +- .../upper/channel_processors/pusch/pusch_decoder_hw_impl.h | 2 +- lib/phy/upper/channel_processors/pusch/pusch_decoder_impl.cpp | 2 +- lib/phy/upper/channel_processors/pusch/pusch_decoder_impl.h | 2 +- .../upper/channel_processors/pusch/pusch_demodulator_impl.cpp | 2 +- .../upper/channel_processors/pusch/pusch_demodulator_impl.h | 2 +- .../upper/channel_processors/pusch/pusch_processor_impl.cpp | 2 +- lib/phy/upper/channel_processors/pusch/pusch_processor_impl.h | 2 +- .../pusch/pusch_processor_notifier_adaptor.h | 2 +- lib/phy/upper/channel_processors/pusch/pusch_processor_pool.h | 2 +- .../channel_processors/pusch/pusch_uci_decoder_notifier.h | 2 +- .../channel_processors/pusch/pusch_uci_decoder_wrapper.h | 2 +- .../upper/channel_processors/pusch/ulsch_demultiplex_impl.cpp | 2 +- .../upper/channel_processors/pusch/ulsch_demultiplex_impl.h | 2 +- lib/phy/upper/channel_processors/ssb_processor_impl.cpp | 2 +- lib/phy/upper/channel_processors/ssb_processor_impl.h | 2 +- lib/phy/upper/channel_processors/ssb_processor_pool.h | 2 +- lib/phy/upper/channel_processors/uci/CMakeLists.txt | 2 +- lib/phy/upper/channel_processors/uci/factories.cpp | 2 +- lib/phy/upper/channel_processors/uci/uci_decoder_impl.cpp | 2 +- lib/phy/upper/channel_processors/uci/uci_decoder_impl.h | 2 +- lib/phy/upper/downlink_processor_pool_impl.cpp | 2 +- lib/phy/upper/downlink_processor_pool_impl.h | 2 +- lib/phy/upper/downlink_processor_single_executor_impl.cpp | 2 +- lib/phy/upper/downlink_processor_single_executor_impl.h | 2 +- lib/phy/upper/downlink_processor_single_executor_state.h | 2 +- lib/phy/upper/equalization/CMakeLists.txt | 2 +- lib/phy/upper/equalization/channel_equalizer_zf_impl.cpp | 2 +- lib/phy/upper/equalization/channel_equalizer_zf_impl.h | 2 +- lib/phy/upper/equalization/equalization_factories.cpp | 2 +- lib/phy/upper/equalization/equalize_zf_1xn.h | 2 +- lib/phy/upper/equalization/equalize_zf_2x2.cpp | 2 +- lib/phy/upper/equalization/equalize_zf_2x2.h | 2 +- lib/phy/upper/log_likelihood_ratio.cpp | 2 +- lib/phy/upper/processor_pool_helpers.h | 2 +- lib/phy/upper/rb_allocation.cpp | 2 +- lib/phy/upper/rx_buffer_codeblock_pool.h | 2 +- lib/phy/upper/rx_buffer_impl.h | 2 +- lib/phy/upper/rx_buffer_pool_impl.cpp | 2 +- lib/phy/upper/rx_buffer_pool_impl.h | 2 +- lib/phy/upper/sequence_generators/CMakeLists.txt | 2 +- .../sequence_generators/low_papr_sequence_collection_impl.cpp | 2 +- .../sequence_generators/low_papr_sequence_collection_impl.h | 2 +- .../sequence_generators/low_papr_sequence_generator_impl.cpp | 2 +- .../sequence_generators/low_papr_sequence_generator_impl.h | 2 +- .../pseudo_random_generator_fast_advance.h | 2 +- .../sequence_generators/pseudo_random_generator_impl.cpp | 2 +- .../upper/sequence_generators/pseudo_random_generator_impl.h | 2 +- .../pseudo_random_generator_initializers.h | 2 +- .../sequence_generators/pseudo_random_generator_sequence.h | 2 +- .../sequence_generators/sequence_generator_factories.cpp | 2 +- lib/phy/upper/signal_processors/CMakeLists.txt | 2 +- lib/phy/upper/signal_processors/dmrs_helper.h | 2 +- lib/phy/upper/signal_processors/dmrs_pbch_processor_impl.cpp | 2 +- lib/phy/upper/signal_processors/dmrs_pbch_processor_impl.h | 2 +- lib/phy/upper/signal_processors/dmrs_pdcch_processor_impl.cpp | 2 +- lib/phy/upper/signal_processors/dmrs_pdcch_processor_impl.h | 2 +- lib/phy/upper/signal_processors/dmrs_pdsch_processor_impl.cpp | 2 +- lib/phy/upper/signal_processors/dmrs_pdsch_processor_impl.h | 2 +- lib/phy/upper/signal_processors/dmrs_pusch_estimator_impl.cpp | 2 +- lib/phy/upper/signal_processors/dmrs_pusch_estimator_impl.h | 2 +- lib/phy/upper/signal_processors/nzp_csi_rs_generator_impl.cpp | 2 +- lib/phy/upper/signal_processors/nzp_csi_rs_generator_impl.h | 2 +- lib/phy/upper/signal_processors/nzp_csi_rs_generator_pool.h | 2 +- .../signal_processors/port_channel_estimator_average_impl.cpp | 2 +- .../signal_processors/port_channel_estimator_average_impl.h | 2 +- lib/phy/upper/signal_processors/pss_processor_impl.cpp | 2 +- lib/phy/upper/signal_processors/pss_processor_impl.h | 2 +- .../pucch/dmrs_pucch_processor_format1_impl.cpp | 2 +- .../pucch/dmrs_pucch_processor_format1_impl.h | 2 +- .../pucch/dmrs_pucch_processor_format2_impl.cpp | 2 +- .../pucch/dmrs_pucch_processor_format2_impl.h | 2 +- lib/phy/upper/signal_processors/pucch/pucch_helper.h | 2 +- .../upper/signal_processors/pucch/pucch_orthogonal_sequence.h | 2 +- .../upper/signal_processors/signal_processor_factories.cpp | 2 +- lib/phy/upper/signal_processors/sss_processor_impl.cpp | 2 +- lib/phy/upper/signal_processors/sss_processor_impl.h | 2 +- lib/phy/upper/tx_buffer_codeblock_pool.h | 2 +- lib/phy/upper/tx_buffer_impl.h | 2 +- lib/phy/upper/tx_buffer_pool_impl.cpp | 2 +- lib/phy/upper/tx_buffer_pool_impl.h | 2 +- lib/phy/upper/uplink_processor_impl.cpp | 2 +- lib/phy/upper/uplink_processor_impl.h | 2 +- lib/phy/upper/uplink_processor_pool_impl.cpp | 2 +- lib/phy/upper/uplink_processor_pool_impl.h | 2 +- lib/phy/upper/uplink_processor_task_dispatcher.h | 2 +- lib/phy/upper/uplink_request_processor_impl.cpp | 2 +- lib/phy/upper/uplink_request_processor_impl.h | 2 +- lib/phy/upper/upper_phy_factories.cpp | 2 +- lib/phy/upper/upper_phy_impl.cpp | 2 +- lib/phy/upper/upper_phy_impl.h | 2 +- lib/phy/upper/upper_phy_pdu_validators.h | 2 +- lib/phy/upper/upper_phy_rx_results_notifier_wrapper.cpp | 2 +- lib/phy/upper/upper_phy_rx_results_notifier_wrapper.h | 2 +- lib/phy/upper/upper_phy_rx_symbol_handler_impl.cpp | 2 +- lib/phy/upper/upper_phy_rx_symbol_handler_impl.h | 2 +- lib/phy/upper/upper_phy_rx_symbol_handler_printer_decorator.h | 2 +- lib/phy/upper/vrb_to_prb_mapper.cpp | 2 +- lib/psup/CMakeLists.txt | 2 +- lib/psup/psup_packing.cpp | 2 +- lib/radio/CMakeLists.txt | 2 +- lib/radio/radio_factory.cpp | 2 +- lib/radio/uhd/CMakeLists.txt | 2 +- lib/radio/uhd/radio_config_uhd_validator.cpp | 2 +- lib/radio/uhd/radio_config_uhd_validator.h | 2 +- lib/radio/uhd/radio_uhd_baseband_gateway.h | 2 +- lib/radio/uhd/radio_uhd_device.h | 2 +- lib/radio/uhd/radio_uhd_device_type.h | 2 +- lib/radio/uhd/radio_uhd_exception_handler.h | 2 +- lib/radio/uhd/radio_uhd_impl.cpp | 2 +- lib/radio/uhd/radio_uhd_impl.h | 2 +- lib/radio/uhd/radio_uhd_multi_usrp.h | 2 +- lib/radio/uhd/radio_uhd_rx_stream.cpp | 2 +- lib/radio/uhd/radio_uhd_rx_stream.h | 2 +- lib/radio/uhd/radio_uhd_tx_stream.cpp | 2 +- lib/radio/uhd/radio_uhd_tx_stream.h | 2 +- lib/radio/uhd/radio_uhd_tx_stream_fsm.h | 2 +- lib/radio/zmq/CMakeLists.txt | 2 +- lib/radio/zmq/radio_config_zmq_validator.cpp | 2 +- lib/radio/zmq/radio_config_zmq_validator.h | 2 +- lib/radio/zmq/radio_factory_zmq_impl.cpp | 2 +- lib/radio/zmq/radio_factory_zmq_impl.h | 2 +- lib/radio/zmq/radio_session_zmq_impl.cpp | 2 +- lib/radio/zmq/radio_session_zmq_impl.h | 2 +- lib/radio/zmq/radio_zmq_baseband_gateway.h | 2 +- lib/radio/zmq/radio_zmq_rx_channel.cpp | 2 +- lib/radio/zmq/radio_zmq_rx_channel.h | 2 +- lib/radio/zmq/radio_zmq_rx_channel_fsm.h | 2 +- lib/radio/zmq/radio_zmq_rx_stream.cpp | 2 +- lib/radio/zmq/radio_zmq_rx_stream.h | 2 +- lib/radio/zmq/radio_zmq_timer.h | 2 +- lib/radio/zmq/radio_zmq_tx_align_interface.h | 2 +- lib/radio/zmq/radio_zmq_tx_channel.cpp | 2 +- lib/radio/zmq/radio_zmq_tx_channel.h | 2 +- lib/radio/zmq/radio_zmq_tx_channel_fsm.h | 2 +- lib/radio/zmq/radio_zmq_tx_stream.cpp | 2 +- lib/radio/zmq/radio_zmq_tx_stream.h | 2 +- lib/ran/CMakeLists.txt | 2 +- lib/ran/band_helper.cpp | 2 +- lib/ran/csi_report/csi_report_config_helpers.cpp | 2 +- lib/ran/csi_report/csi_report_on_pucch_helpers.cpp | 2 +- lib/ran/csi_report/csi_report_on_pusch_helpers.cpp | 2 +- lib/ran/csi_rs/csi_rs_config_helpers.cpp | 2 +- lib/ran/csi_rs/csi_rs_pattern.cpp | 2 +- lib/ran/csi_rs/frequency_allocation_type.cpp | 2 +- lib/ran/gnb_format.h | 2 +- lib/ran/pdcch/cce_to_prb_mapping.cpp | 2 +- lib/ran/pdcch/dci_packing.cpp | 2 +- lib/ran/pdcch/pdcch_candidates.cpp | 2 +- lib/ran/pdcch/pdcch_type0_css_coreset_config.cpp | 2 +- lib/ran/pdcch/pdcch_type0_css_occasions.cpp | 2 +- lib/ran/pdcch/search_space.cpp | 2 +- lib/ran/pdsch/dlsch_info.cpp | 2 +- lib/ran/pdsch/pdsch_antenna_port_mapping.cpp | 2 +- lib/ran/pdsch/pdsch_mcs.cpp | 2 +- lib/ran/prach/prach_configuration.cpp | 2 +- lib/ran/prach/prach_cyclic_shifts.cpp | 2 +- lib/ran/prach/prach_frequency_mapping.cpp | 2 +- lib/ran/prach/prach_helper.cpp | 2 +- lib/ran/prach/prach_preamble_information.cpp | 2 +- lib/ran/precoding/precoding_codebooks.cpp | 2 +- lib/ran/pusch/pusch_mcs.cpp | 2 +- lib/ran/pusch/pusch_uci_beta_offset.cpp | 2 +- lib/ran/pusch/ulsch_info.cpp | 2 +- lib/ran/resource_allocation/resource_allocation_frequency.cpp | 2 +- lib/ran/sch/sch_segmentation.cpp | 2 +- lib/ran/ssb_freq_position_generator.cpp | 2 +- lib/ran/ssb_freq_position_generator.h | 2 +- lib/ran/ssb_gscn.cpp | 2 +- lib/ran/ssb_mapping.cpp | 2 +- lib/ran/tdd_ul_dl_config.cpp | 2 +- lib/ran/uci/uci_part2_size_calculator.cpp | 2 +- lib/rlc/CMakeLists.txt | 2 +- lib/rlc/rlc_am_entity.h | 2 +- lib/rlc/rlc_am_interconnect.h | 2 +- lib/rlc/rlc_am_pdu.cpp | 2 +- lib/rlc/rlc_am_pdu.h | 2 +- lib/rlc/rlc_base_entity.h | 2 +- lib/rlc/rlc_bearer_logger.h | 2 +- lib/rlc/rlc_factory.cpp | 2 +- lib/rlc/rlc_pdu_recycler.h | 2 +- lib/rlc/rlc_retx_queue.h | 2 +- lib/rlc/rlc_rx_am_entity.cpp | 2 +- lib/rlc/rlc_rx_am_entity.h | 2 +- lib/rlc/rlc_rx_entity.h | 2 +- lib/rlc/rlc_rx_metrics_container.h | 2 +- lib/rlc/rlc_rx_tm_entity.cpp | 2 +- lib/rlc/rlc_rx_tm_entity.h | 2 +- lib/rlc/rlc_rx_um_entity.cpp | 2 +- lib/rlc/rlc_rx_um_entity.h | 2 +- lib/rlc/rlc_sdu_queue.h | 2 +- lib/rlc/rlc_tm_entity.h | 2 +- lib/rlc/rlc_tx_am_entity.cpp | 2 +- lib/rlc/rlc_tx_am_entity.h | 2 +- lib/rlc/rlc_tx_entity.h | 2 +- lib/rlc/rlc_tx_metrics_container.h | 2 +- lib/rlc/rlc_tx_tm_entity.cpp | 2 +- lib/rlc/rlc_tx_tm_entity.h | 2 +- lib/rlc/rlc_tx_um_entity.cpp | 2 +- lib/rlc/rlc_tx_um_entity.h | 2 +- lib/rlc/rlc_um_entity.h | 2 +- lib/rlc/rlc_um_pdu.h | 2 +- lib/rrc/CMakeLists.txt | 2 +- lib/rrc/rrc_du_factory.cpp | 2 +- lib/rrc/rrc_du_impl.cpp | 2 +- lib/rrc/rrc_du_impl.h | 2 +- lib/rrc/ue/adapters/pdcp_adapters.h | 2 +- lib/rrc/ue/meas_types_validators.cpp | 2 +- lib/rrc/ue/procedures/rrc_reconfiguration_procedure.cpp | 2 +- lib/rrc/ue/procedures/rrc_reconfiguration_procedure.h | 2 +- lib/rrc/ue/procedures/rrc_reestablishment_procedure.cpp | 2 +- lib/rrc/ue/procedures/rrc_reestablishment_procedure.h | 2 +- lib/rrc/ue/procedures/rrc_security_mode_command_procedure.cpp | 2 +- lib/rrc/ue/procedures/rrc_security_mode_command_procedure.h | 2 +- lib/rrc/ue/procedures/rrc_setup_procedure.cpp | 2 +- lib/rrc/ue/procedures/rrc_setup_procedure.h | 2 +- .../ue/procedures/rrc_ue_capability_transfer_procedure.cpp | 2 +- lib/rrc/ue/procedures/rrc_ue_capability_transfer_procedure.h | 2 +- lib/rrc/ue/procedures/rrc_ue_event_manager.h | 2 +- lib/rrc/ue/rrc_asn1_converters.h | 2 +- lib/rrc/ue/rrc_asn1_helpers.h | 2 +- lib/rrc/ue/rrc_measurement_types_asn1_converters.h | 2 +- lib/rrc/ue/rrc_ue_context.cpp | 2 +- lib/rrc/ue/rrc_ue_context.h | 2 +- lib/rrc/ue/rrc_ue_helpers.cpp | 2 +- lib/rrc/ue/rrc_ue_helpers.h | 2 +- lib/rrc/ue/rrc_ue_impl.cpp | 2 +- lib/rrc/ue/rrc_ue_impl.h | 2 +- lib/rrc/ue/rrc_ue_logger.h | 2 +- lib/rrc/ue/rrc_ue_message_handlers.cpp | 2 +- lib/rrc/ue/rrc_ue_message_senders.cpp | 2 +- lib/rrc/ue/rrc_ue_srb_context.h | 2 +- lib/ru/CMakeLists.txt | 2 +- lib/ru/generic/CMakeLists.txt | 2 +- lib/ru/generic/lower_phy_factory.h | 2 +- lib/ru/generic/ru_config_validator.h | 2 +- lib/ru/generic/ru_controller_generic_impl.cpp | 2 +- lib/ru/generic/ru_controller_generic_impl.h | 2 +- lib/ru/generic/ru_downlink_handler_generic_impl.cpp | 2 +- lib/ru/generic/ru_downlink_handler_generic_impl.h | 2 +- lib/ru/generic/ru_factory_generic_impl.cpp | 2 +- lib/ru/generic/ru_generic_impl.cpp | 2 +- lib/ru/generic/ru_generic_impl.h | 2 +- lib/ru/generic/ru_radio_notifier_handler.h | 2 +- lib/ru/generic/ru_timing_adapter.h | 2 +- lib/ru/generic/ru_uplink_request_handler_generic_impl.cpp | 2 +- lib/ru/generic/ru_uplink_request_handler_generic_impl.h | 2 +- lib/ru/generic/rx_symbol_adapter.h | 2 +- lib/ru/ofh/CMakeLists.txt | 2 +- lib/ru/ofh/ru_ofh_config_validator.cpp | 2 +- lib/ru/ofh/ru_ofh_controller_impl.cpp | 2 +- lib/ru/ofh/ru_ofh_controller_impl.h | 2 +- lib/ru/ofh/ru_ofh_downlink_plane_handler_proxy.cpp | 2 +- lib/ru/ofh/ru_ofh_downlink_plane_handler_proxy.h | 2 +- lib/ru/ofh/ru_ofh_factory.cpp | 2 +- lib/ru/ofh/ru_ofh_impl.cpp | 2 +- lib/ru/ofh/ru_ofh_impl.h | 2 +- lib/ru/ofh/ru_ofh_rx_symbol_handler_impl.cpp | 2 +- lib/ru/ofh/ru_ofh_rx_symbol_handler_impl.h | 2 +- lib/ru/ofh/ru_ofh_timing_notifier_impl.cpp | 2 +- lib/ru/ofh/ru_ofh_timing_notifier_impl.h | 2 +- lib/ru/ofh/ru_ofh_uplink_plane_handler_proxy.cpp | 2 +- lib/ru/ofh/ru_ofh_uplink_plane_handler_proxy.h | 2 +- lib/scheduler/CMakeLists.txt | 2 +- lib/scheduler/cell/CMakeLists.txt | 2 +- lib/scheduler/cell/resource_block_group.cpp | 2 +- lib/scheduler/cell/resource_grid.cpp | 2 +- lib/scheduler/cell/resource_grid.h | 2 +- lib/scheduler/cell/resource_grid_util.h | 2 +- lib/scheduler/cell/scheduler_prb.cpp | 2 +- lib/scheduler/cell/scheduler_prb.h | 2 +- lib/scheduler/cell/vrb_alloc.cpp | 2 +- lib/scheduler/cell_scheduler.cpp | 2 +- lib/scheduler/cell_scheduler.h | 2 +- lib/scheduler/common_scheduling/CMakeLists.txt | 2 +- lib/scheduler/common_scheduling/csi_rs_scheduler.cpp | 2 +- lib/scheduler/common_scheduling/csi_rs_scheduler.h | 2 +- lib/scheduler/common_scheduling/paging_scheduler.cpp | 2 +- lib/scheduler/common_scheduling/paging_scheduler.h | 2 +- lib/scheduler/common_scheduling/prach_scheduler.cpp | 2 +- lib/scheduler/common_scheduling/prach_scheduler.h | 2 +- lib/scheduler/common_scheduling/ra_scheduler.cpp | 2 +- lib/scheduler/common_scheduling/ra_scheduler.h | 2 +- lib/scheduler/common_scheduling/si_message_scheduler.cpp | 2 +- lib/scheduler/common_scheduling/si_message_scheduler.h | 2 +- lib/scheduler/common_scheduling/sib_scheduler.cpp | 2 +- lib/scheduler/common_scheduling/sib_scheduler.h | 2 +- lib/scheduler/common_scheduling/ssb_scheduler.cpp | 2 +- lib/scheduler/common_scheduling/ssb_scheduler.h | 2 +- lib/scheduler/config/CMakeLists.txt | 2 +- lib/scheduler/config/cell_configuration.cpp | 2 +- lib/scheduler/config/cell_configuration.h | 2 +- lib/scheduler/config/csi_helper.cpp | 2 +- lib/scheduler/config/logical_channel_config_factory.cpp | 2 +- lib/scheduler/config/sched_cell_config_helpers.cpp | 2 +- lib/scheduler/config/sched_config_manager.cpp | 2 +- lib/scheduler/config/sched_config_manager.h | 2 +- lib/scheduler/config/scheduler_cell_config_validator.cpp | 2 +- lib/scheduler/config/scheduler_ue_config_validator.cpp | 2 +- lib/scheduler/config/serving_cell_config_factory.cpp | 2 +- lib/scheduler/config/serving_cell_config_validator.cpp | 2 +- lib/scheduler/config/ue_configuration.cpp | 2 +- lib/scheduler/config/ue_configuration.h | 2 +- lib/scheduler/logging/CMakeLists.txt | 2 +- lib/scheduler/logging/scheduler_event_logger.cpp | 2 +- lib/scheduler/logging/scheduler_event_logger.h | 2 +- lib/scheduler/logging/scheduler_metric_handler.cpp | 2 +- lib/scheduler/logging/scheduler_metrics_handler.h | 2 +- lib/scheduler/logging/scheduler_metrics_ue_configurator.h | 2 +- lib/scheduler/logging/scheduler_result_logger.cpp | 2 +- lib/scheduler/logging/scheduler_result_logger.h | 2 +- .../pdcch_scheduling/pdcch_resource_allocator_impl.cpp | 2 +- .../pdcch_scheduling/pdcch_resource_allocator_impl.h | 2 +- .../pdcch_scheduling/pdcch_slot_resource_allocator.cpp | 2 +- .../pdcch_scheduling/pdcch_slot_resource_allocator.h | 2 +- lib/scheduler/policy/scheduler_policy.h | 2 +- lib/scheduler/policy/scheduler_policy_factory.cpp | 2 +- lib/scheduler/policy/scheduler_policy_factory.h | 2 +- lib/scheduler/policy/scheduler_time_rr.cpp | 2 +- lib/scheduler/policy/scheduler_time_rr.h | 2 +- lib/scheduler/policy/ue_allocator.h | 2 +- lib/scheduler/pucch_scheduling/pucch_allocator.h | 2 +- lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp | 2 +- lib/scheduler/pucch_scheduling/pucch_allocator_impl.h | 2 +- lib/scheduler/pucch_scheduling/pucch_guardbands_scheduler.cpp | 2 +- lib/scheduler/pucch_scheduling/pucch_guardbands_scheduler.h | 2 +- lib/scheduler/pucch_scheduling/pucch_resource_manager.cpp | 2 +- lib/scheduler/pucch_scheduling/pucch_resource_manager.h | 2 +- lib/scheduler/scheduler_factory.cpp | 2 +- lib/scheduler/scheduler_impl.cpp | 2 +- lib/scheduler/scheduler_impl.h | 2 +- lib/scheduler/support/bwp_helpers.h | 2 +- lib/scheduler/support/config_helpers.h | 2 +- lib/scheduler/support/csi_report_helpers.cpp | 2 +- lib/scheduler/support/csi_report_helpers.h | 2 +- lib/scheduler/support/dci_builder.cpp | 2 +- lib/scheduler/support/dci_builder.h | 2 +- lib/scheduler/support/dmrs_helpers.h | 2 +- lib/scheduler/support/mcs_calculator.cpp | 2 +- lib/scheduler/support/mcs_calculator.h | 2 +- lib/scheduler/support/mcs_tbs_calculator.cpp | 2 +- lib/scheduler/support/mcs_tbs_calculator.h | 2 +- lib/scheduler/support/outer_loop_link_adaptation.h | 2 +- lib/scheduler/support/pdcch/pdcch_mapping.h | 2 +- lib/scheduler/support/pdcch/pdcch_pdu_parameters.h | 2 +- lib/scheduler/support/pdcch/pdcch_type0_helpers.cpp | 2 +- lib/scheduler/support/pdcch/pdcch_type0_helpers.h | 2 +- lib/scheduler/support/pdcch/search_space_helper.h | 2 +- lib/scheduler/support/pdcch_aggregation_level_calculator.cpp | 2 +- lib/scheduler/support/pdcch_aggregation_level_calculator.h | 2 +- lib/scheduler/support/pdsch/pdsch_default_time_allocation.cpp | 2 +- lib/scheduler/support/pdsch/pdsch_default_time_allocation.h | 2 +- lib/scheduler/support/pdsch/pdsch_dmrs_symbol_mask.cpp | 2 +- lib/scheduler/support/pdsch/pdsch_dmrs_symbol_mask.h | 2 +- lib/scheduler/support/pdsch/pdsch_resource_allocation.h | 2 +- lib/scheduler/support/prbs_calculator.cpp | 2 +- lib/scheduler/support/prbs_calculator.h | 2 +- lib/scheduler/support/pucch/pucch_default_resource.cpp | 2 +- lib/scheduler/support/pucch/pucch_default_resource.h | 2 +- lib/scheduler/support/pusch/pusch_default_time_allocation.cpp | 2 +- lib/scheduler/support/pusch/pusch_default_time_allocation.h | 2 +- lib/scheduler/support/pusch/pusch_dmrs_symbol_mask.cpp | 2 +- lib/scheduler/support/pusch/pusch_dmrs_symbol_mask.h | 2 +- lib/scheduler/support/pusch/pusch_resource_allocation.h | 2 +- lib/scheduler/support/rb_helper.cpp | 2 +- lib/scheduler/support/rb_helper.h | 2 +- lib/scheduler/support/sch_pdu_builder.cpp | 2 +- lib/scheduler/support/sch_pdu_builder.h | 2 +- lib/scheduler/support/slot_event_list.h | 2 +- lib/scheduler/support/slot_sync_point.h | 2 +- lib/scheduler/support/sr_helper.cpp | 2 +- lib/scheduler/support/sr_helper.h | 2 +- lib/scheduler/support/ssb_helpers.h | 2 +- lib/scheduler/support/tbs_calculator.cpp | 2 +- lib/scheduler/support/tbs_calculator.h | 2 +- lib/scheduler/uci_scheduling/uci_allocator.h | 2 +- lib/scheduler/uci_scheduling/uci_allocator_impl.cpp | 2 +- lib/scheduler/uci_scheduling/uci_allocator_impl.h | 2 +- lib/scheduler/uci_scheduling/uci_scheduler.h | 2 +- lib/scheduler/uci_scheduling/uci_scheduler_impl.cpp | 2 +- lib/scheduler/uci_scheduling/uci_scheduler_impl.h | 2 +- lib/scheduler/ue_scheduling/CMakeLists.txt | 2 +- lib/scheduler/ue_scheduling/dl_logical_channel_manager.cpp | 2 +- lib/scheduler/ue_scheduling/dl_logical_channel_manager.h | 2 +- lib/scheduler/ue_scheduling/harq_process.cpp | 2 +- lib/scheduler/ue_scheduling/harq_process.h | 2 +- lib/scheduler/ue_scheduling/ta_manager.cpp | 2 +- lib/scheduler/ue_scheduling/ta_manager.h | 2 +- lib/scheduler/ue_scheduling/ue.cpp | 2 +- lib/scheduler/ue_scheduling/ue.h | 2 +- lib/scheduler/ue_scheduling/ue_cell.cpp | 2 +- lib/scheduler/ue_scheduling/ue_cell.h | 2 +- lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp | 2 +- lib/scheduler/ue_scheduling/ue_cell_grid_allocator.h | 2 +- lib/scheduler/ue_scheduling/ue_channel_state_manager.cpp | 2 +- lib/scheduler/ue_scheduling/ue_channel_state_manager.h | 2 +- lib/scheduler/ue_scheduling/ue_event_manager.cpp | 2 +- lib/scheduler/ue_scheduling/ue_event_manager.h | 2 +- lib/scheduler/ue_scheduling/ue_link_adaptation_controller.cpp | 2 +- lib/scheduler/ue_scheduling/ue_link_adaptation_controller.h | 2 +- .../ue_scheduling/ue_pdsch_param_candidate_searcher.h | 2 +- lib/scheduler/ue_scheduling/ue_repository.cpp | 2 +- lib/scheduler/ue_scheduling/ue_repository.h | 2 +- lib/scheduler/ue_scheduling/ue_scheduler.h | 2 +- lib/scheduler/ue_scheduling/ue_scheduler_impl.cpp | 2 +- lib/scheduler/ue_scheduling/ue_scheduler_impl.h | 2 +- lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp | 2 +- lib/scheduler/ue_scheduling/ue_srb0_scheduler.h | 2 +- lib/scheduler/ue_scheduling/ul_logical_channel_manager.cpp | 2 +- lib/scheduler/ue_scheduling/ul_logical_channel_manager.h | 2 +- lib/sdap/CMakeLists.txt | 2 +- lib/sdap/sdap_entity_impl.h | 2 +- lib/sdap/sdap_entity_rx_impl.h | 2 +- lib/sdap/sdap_entity_tx_impl.h | 2 +- lib/sdap/sdap_factory.cpp | 2 +- lib/sdap/sdap_session_logger.h | 2 +- lib/security/CMakeLists.txt | 2 +- lib/security/s3g.cpp | 2 +- lib/security/security.cpp | 2 +- lib/security/zuc.cpp | 2 +- lib/srslog/CMakeLists.txt | 2 +- lib/srslog/backend_worker.cpp | 2 +- lib/srslog/backend_worker.h | 2 +- lib/srslog/event_trace.cpp | 2 +- lib/srslog/formatters/json_formatter.cpp | 2 +- lib/srslog/formatters/json_formatter.h | 2 +- lib/srslog/formatters/text_formatter.cpp | 2 +- lib/srslog/formatters/text_formatter.h | 2 +- lib/srslog/log_backend_impl.h | 2 +- lib/srslog/object_repository.h | 2 +- lib/srslog/sinks/buffered_file_sink.h | 2 +- lib/srslog/sinks/file_sink.h | 2 +- lib/srslog/sinks/file_utils.h | 2 +- lib/srslog/sinks/stream_sink.h | 2 +- lib/srslog/sinks/syslog_sink.h | 2 +- lib/srslog/sinks/udp_sink.h | 2 +- lib/srslog/srslog.cpp | 2 +- lib/srslog/srslog_c.cpp | 2 +- lib/srslog/srslog_instance.h | 2 +- lib/srsvec/CMakeLists.txt | 2 +- lib/srsvec/accumulate.cpp | 2 +- lib/srsvec/add.cpp | 2 +- lib/srsvec/aligned_vec.cpp | 2 +- lib/srsvec/bit.cpp | 2 +- lib/srsvec/clip.cpp | 2 +- lib/srsvec/compare.cpp | 2 +- lib/srsvec/conversion.cpp | 2 +- lib/srsvec/convolution.cpp | 2 +- lib/srsvec/division.cpp | 2 +- lib/srsvec/dot_prod.cpp | 2 +- lib/srsvec/modulus_square.cpp | 2 +- lib/srsvec/prod.cpp | 2 +- lib/srsvec/sc_prod.cpp | 2 +- lib/srsvec/simd.h | 2 +- lib/srsvec/subtract.cpp | 2 +- lib/support/CMakeLists.txt | 2 +- lib/support/backtrace.cpp | 2 +- lib/support/bit_encoding.cpp | 2 +- lib/support/build_info/CMakeLists.txt | 2 +- lib/support/build_info/build_info.cpp | 2 +- lib/support/build_info/hashes.h.in | 2 +- lib/support/byte_buffer.cpp | 2 +- lib/support/byte_buffer_chain.cpp | 2 +- lib/support/config_yaml.cpp | 2 +- lib/support/event_tracing.cpp | 2 +- lib/support/executors/task_execution_manager.cpp | 2 +- lib/support/executors/task_worker.cpp | 2 +- lib/support/executors/task_worker_pool.cpp | 2 +- lib/support/math_utils.cpp | 2 +- lib/support/network/CMakeLists.txt | 2 +- lib/support/network/epoll_helper.h | 2 +- lib/support/network/io_broker_epoll.cpp | 2 +- lib/support/network/io_broker_epoll.h | 2 +- lib/support/network/io_broker_factory.cpp | 2 +- lib/support/network/transport_layer_address.cpp | 2 +- lib/support/sdu_window_impl.h | 2 +- lib/support/signal_handler.cpp | 2 +- lib/support/sysinfo.cpp | 2 +- lib/support/timers.cpp | 2 +- lib/support/unique_thread.cpp | 2 +- lib/support/version/CMakeLists.txt | 2 +- lib/support/version/version.cpp | 2 +- lib/support/version/version_info.h.in | 2 +- scripts/srsran_performance | 2 +- tests/benchmarks/CMakeLists.txt | 2 +- tests/benchmarks/adt/CMakeLists.txt | 2 +- tests/benchmarks/adt/bounded_bitset_benchmark_helpers.h | 2 +- tests/benchmarks/adt/bounded_bitset_count_benchmark.cpp | 2 +- tests/benchmarks/adt/bounded_bitset_range_benchmark.cpp | 2 +- tests/benchmarks/du_high/CMakeLists.txt | 2 +- tests/benchmarks/du_high/du_high_benchmark.cpp | 2 +- tests/benchmarks/gateways/CMakeLists.txt | 2 +- tests/benchmarks/gateways/udp_network_gateway_benchmark.cpp | 2 +- tests/benchmarks/ofh/CMakeLists.txt | 2 +- tests/benchmarks/ofh/ofh_compression_benchmark.cpp | 2 +- tests/benchmarks/pdcp/CMakeLists.txt | 2 +- tests/benchmarks/pdcp/pdcp_rx_benchmark.cpp | 2 +- tests/benchmarks/pdcp/pdcp_tx_benchmark.cpp | 2 +- tests/benchmarks/phy/CMakeLists.txt | 2 +- tests/benchmarks/phy/generic_functions/CMakeLists.txt | 2 +- .../phy/generic_functions/dft_processor_benchmark.cpp | 2 +- tests/benchmarks/phy/upper/CMakeLists.txt | 2 +- tests/benchmarks/phy/upper/channel_coding/CMakeLists.txt | 2 +- tests/benchmarks/phy/upper/channel_coding/ldpc/CMakeLists.txt | 2 +- .../phy/upper/channel_coding/ldpc/ldpc_decoder_benchmark.cpp | 2 +- .../phy/upper/channel_coding/ldpc/ldpc_encoder_benchmark.cpp | 2 +- tests/benchmarks/phy/upper/channel_modulation/CMakeLists.txt | 2 +- .../upper/channel_modulation/modulation_chain_benchmark.cpp | 2 +- tests/benchmarks/phy/upper/channel_processors/CMakeLists.txt | 2 +- .../upper/channel_processors/pdsch_processor_benchmark.cpp | 2 +- .../phy/upper/channel_processors/prach_detector_benchmark.cpp | 2 +- .../phy/upper/channel_processors/pusch/CMakeLists.txt | 2 +- .../pusch/pusch_decoder_hwacc_benchmark.cpp | 2 +- .../channel_processors/pusch/pusch_processor_benchmark.cpp | 2 +- tests/benchmarks/phy/upper/equalization/CMakeLists.txt | 2 +- .../phy/upper/equalization/channel_equalizer_benchmark.cpp | 2 +- tests/benchmarks/phy/upper/precoding/CMakeLists.txt | 2 +- .../phy/upper/precoding/channel_precoder_benchmark.cpp | 2 +- tests/benchmarks/phy/upper/signal_processors/CMakeLists.txt | 2 +- .../signal_processors/dmrs_pdsch_processor_benchmark.cpp | 2 +- tests/benchmarks/rlc/CMakeLists.txt | 2 +- tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp | 2 +- tests/benchmarks/rlc/rlc_handle_status_report.cpp | 2 +- tests/benchmarks/scheduler/CMakeLists.txt | 2 +- tests/benchmarks/scheduler/scheduler_multi_ue_benchmark.cpp | 2 +- tests/benchmarks/scheduler/scheduler_no_ues_benchmark.cpp | 2 +- tests/benchmarks/scheduler/scheduler_test_doubles.h | 2 +- tests/e2e/conftest.py | 2 +- tests/e2e/pyproject.toml | 2 +- tests/e2e/tests/__init__.py | 2 +- tests/e2e/tests/attach_detach.py | 2 +- tests/e2e/tests/iperf.py | 2 +- tests/e2e/tests/iperf_alt.py | 2 +- tests/e2e/tests/ping.py | 2 +- tests/e2e/tests/steps/__init__.py | 2 +- tests/e2e/tests/steps/configuration.py | 2 +- tests/e2e/tests/steps/stub.py | 2 +- tests/e2e/tests/validate_configuration.py | 2 +- tests/e2e/tests/viavi.py | 2 +- tests/integrationtests/CMakeLists.txt | 2 +- tests/integrationtests/du_high/CMakeLists.txt | 2 +- tests/integrationtests/du_high/du_high_many_ues_test.cpp | 2 +- tests/integrationtests/du_high/du_high_test.cpp | 2 +- tests/integrationtests/du_high/mac_test_mode_adapter_test.cpp | 2 +- tests/integrationtests/du_high/paging_test.cpp | 2 +- .../du_high/test_utils/du_high_test_bench.cpp | 2 +- .../integrationtests/du_high/test_utils/du_high_test_bench.h | 2 +- .../du_high/test_utils/du_high_worker_manager.h | 2 +- tests/integrationtests/du_high_cu/CMakeLists.txt | 2 +- tests/integrationtests/du_high_cu/cu_du_test.cpp | 2 +- tests/integrationtests/du_high_cu/cu_multi_du_test.cpp | 2 +- .../integrationtests/du_high_cu/du_high_cu_test_simulator.cpp | 2 +- tests/integrationtests/du_high_cu/du_high_cu_test_simulator.h | 2 +- tests/integrationtests/e2ap/CMakeLists.txt | 2 +- tests/integrationtests/e2ap/e2ap_integration_test.cpp | 2 +- tests/integrationtests/ngap/CMakeLists.txt | 2 +- tests/integrationtests/ngap/ngap_integration_test.cpp | 2 +- tests/integrationtests/ofh/CMakeLists.txt | 2 +- tests/integrationtests/ofh/ofh_integration_test.cpp | 2 +- tests/integrationtests/rlc/CMakeLists.txt | 2 +- tests/integrationtests/rlc/rlc_stress_test.cpp | 2 +- tests/integrationtests/rlc/rlc_stress_test.h | 2 +- tests/integrationtests/rlc/rlc_stress_test_args.h | 2 +- tests/integrationtests/rlc/rlc_stress_test_f1.h | 2 +- tests/integrationtests/rlc/rlc_stress_test_mac.cpp | 2 +- tests/integrationtests/rlc/rlc_stress_test_mac.h | 2 +- tests/integrationtests/rlc/rlc_stress_test_rrc.h | 2 +- tests/integrationtests/rlc/rlc_stress_test_traffic.cpp | 2 +- tests/integrationtests/rlc/rlc_stress_test_traffic.h | 2 +- tests/test_doubles/CMakeLists.txt | 2 +- tests/test_doubles/f1ap/CMakeLists.txt | 2 +- tests/test_doubles/f1ap/f1ap_test_message_validators.cpp | 2 +- tests/test_doubles/f1ap/f1ap_test_message_validators.h | 2 +- tests/test_doubles/f1ap/f1ap_test_messages.cpp | 2 +- tests/test_doubles/f1ap/f1ap_test_messages.h | 2 +- tests/test_doubles/f1ap/f1c_test_local_gateway.h | 2 +- tests/test_doubles/f1u/dummy_f1u_du_gateway.h | 2 +- tests/test_doubles/mac/CMakeLists.txt | 2 +- tests/test_doubles/mac/dummy_mac_result_notifier.cpp | 2 +- tests/test_doubles/mac/dummy_mac_result_notifier.h | 2 +- tests/test_doubles/mac/dummy_scheduler_ue_metric_notifier.h | 2 +- tests/test_doubles/mac/mac_test_messages.cpp | 2 +- tests/test_doubles/mac/mac_test_messages.h | 2 +- tests/unittests/CMakeLists.txt | 2 +- tests/unittests/adt/CMakeLists.txt | 2 +- tests/unittests/adt/blocking_queue_test.cpp | 2 +- tests/unittests/adt/bounded_bitset_test.cpp | 2 +- tests/unittests/adt/bounded_integer_test.cpp | 2 +- tests/unittests/adt/byte_buffer_chain_test.cpp | 2 +- tests/unittests/adt/byte_buffer_segment_test.cpp | 2 +- tests/unittests/adt/byte_buffer_test.cpp | 2 +- tests/unittests/adt/circular_map_test.cpp | 2 +- tests/unittests/adt/circular_map_test_alt.cpp | 2 +- tests/unittests/adt/concurrent_queue_test.cpp | 2 +- tests/unittests/adt/expected_test.cpp | 2 +- tests/unittests/adt/filter_view_test.cpp | 2 +- tests/unittests/adt/interval_test.cpp | 2 +- tests/unittests/adt/optional_test.cpp | 2 +- tests/unittests/adt/ring_buffer_test.cpp | 2 +- tests/unittests/adt/slotted_array_test.cpp | 2 +- tests/unittests/adt/span_formatter_test.cpp | 2 +- tests/unittests/adt/static_vector_test.cpp | 2 +- tests/unittests/adt/strong_type_test.cpp | 2 +- tests/unittests/adt/tiny_optional_test.cpp | 2 +- tests/unittests/adt/unique_function_test.cpp | 2 +- tests/unittests/asn1/CMakeLists.txt | 2 +- tests/unittests/asn1/asn1_e1ap_test.cpp | 2 +- tests/unittests/asn1/asn1_e2ap_test.cpp | 2 +- tests/unittests/asn1/asn1_f1ap_test.cpp | 2 +- tests/unittests/asn1/asn1_ngap_test.cpp | 2 +- tests/unittests/asn1/asn1_rrc_nr_test.cpp | 2 +- tests/unittests/asn1/asn1_utils_test.cpp | 2 +- tests/unittests/cu_cp/CMakeLists.txt | 2 +- tests/unittests/cu_cp/cell_meas_manager/CMakeLists.txt | 2 +- .../cu_cp/cell_meas_manager/cell_meas_manager_test.cpp | 2 +- .../cell_meas_manager/cell_meas_manager_test_helpers.cpp | 2 +- .../cu_cp/cell_meas_manager/cell_meas_manager_test_helpers.h | 2 +- tests/unittests/cu_cp/cu_cp_config_test.cpp | 2 +- tests/unittests/cu_cp/cu_cp_test.cpp | 2 +- tests/unittests/cu_cp/cu_cp_test_helpers.cpp | 2 +- tests/unittests/cu_cp/cu_cp_test_helpers.h | 2 +- tests/unittests/cu_cp/cu_up_processor/CMakeLists.txt | 2 +- .../unittests/cu_cp/cu_up_processor/cu_up_processor_test.cpp | 2 +- .../cu_cp/cu_up_processor/cu_up_processor_test_helpers.cpp | 2 +- .../cu_cp/cu_up_processor/cu_up_processor_test_helpers.h | 2 +- tests/unittests/cu_cp/du_processor/CMakeLists.txt | 2 +- .../du_processor_routine_manager_test_helpers.cpp | 2 +- .../du_processor/du_processor_routine_manager_test_helpers.h | 2 +- tests/unittests/cu_cp/du_processor/du_processor_test.cpp | 2 +- .../cu_cp/du_processor/du_processor_test_helpers.cpp | 2 +- .../unittests/cu_cp/du_processor/du_processor_test_helpers.h | 2 +- .../inter_ngran_node_n2_handover_routine_test.cpp | 2 +- .../inter_ngran_node_n2_handover_routine_test_helpers.h | 2 +- .../pdu_session_resource_modification_routine_test.cpp | 2 +- .../pdu_session_resource_release_routine_test.cpp | 2 +- .../du_processor/pdu_session_resource_routine_test_helpers.h | 2 +- .../du_processor/pdu_session_resource_setup_routine_test.cpp | 2 +- .../cu_cp/du_processor/ue_context_release_routine_test.cpp | 2 +- tests/unittests/cu_cp/du_processor_test_messages.cpp | 2 +- tests/unittests/cu_cp/du_processor_test_messages.h | 2 +- tests/unittests/cu_cp/mobility/CMakeLists.txt | 2 +- .../cu_cp/mobility/handover_reconfiguration_routine_test.cpp | 2 +- .../cu_cp/mobility/inter_du_handover_routine_test.cpp | 2 +- .../cu_cp/mobility/inter_du_handover_routine_test_helpers.cpp | 2 +- .../cu_cp/mobility/inter_du_handover_routine_test_helpers.h | 2 +- tests/unittests/cu_cp/mobility/mobility_test_helpers.cpp | 2 +- tests/unittests/cu_cp/mobility/mobility_test_helpers.h | 2 +- tests/unittests/cu_cp/mobility/mobility_test_messages.h | 2 +- tests/unittests/cu_cp/test_helpers.cpp | 2 +- tests/unittests/cu_cp/test_helpers.h | 2 +- tests/unittests/cu_cp/ue_manager/CMakeLists.txt | 2 +- tests/unittests/cu_cp/ue_manager/ue_manager_test.cpp | 2 +- tests/unittests/cu_cp/ue_manager/ue_manager_test_helpers.cpp | 2 +- tests/unittests/cu_cp/ue_manager/ue_manager_test_helpers.h | 2 +- tests/unittests/cu_cp/up_resource_manager/CMakeLists.txt | 2 +- .../cu_cp/up_resource_manager/up_resource_manager_test.cpp | 2 +- tests/unittests/cu_up/CMakeLists.txt | 2 +- tests/unittests/cu_up/cu_up_test.cpp | 2 +- tests/unittests/cu_up/cu_up_test_helpers.h | 2 +- tests/unittests/cu_up/pdu_session_manager_test.cpp | 2 +- tests/unittests/cu_up/pdu_session_manager_test.h | 2 +- tests/unittests/cu_up/ue_manager_test.cpp | 2 +- tests/unittests/du_manager/CMakeLists.txt | 2 +- tests/unittests/du_manager/du_manager_test_helpers.cpp | 2 +- tests/unittests/du_manager/du_manager_test_helpers.h | 2 +- tests/unittests/du_manager/du_ran_resource_manager_test.cpp | 2 +- tests/unittests/du_manager/du_ue/du_bearer_test.cpp | 2 +- tests/unittests/du_manager/du_ue/ue_manager_test.cpp | 2 +- .../du_manager/mac_cell_group_config_converter_test.cpp | 2 +- .../procedures/du_manager_procedure_test_helpers.cpp | 2 +- .../du_manager/procedures/du_manager_procedure_test_helpers.h | 2 +- .../procedures/du_ue_ric_configuration_procedure_test.cpp | 2 +- .../unittests/du_manager/procedures/ue_configuration_test.cpp | 2 +- tests/unittests/du_manager/procedures/ue_creation_test.cpp | 2 +- tests/unittests/du_manager/procedures/ue_deletion_test.cpp | 2 +- tests/unittests/du_manager/pucch_resource_generator_test.cpp | 2 +- .../du_manager/serving_cell_config_converter_test.cpp | 2 +- tests/unittests/du_manager/sib_test.cpp | 2 +- tests/unittests/e1ap/CMakeLists.txt | 2 +- tests/unittests/e1ap/common/CMakeLists.txt | 2 +- tests/unittests/e1ap/common/e1ap_asn1_packer_test.cpp | 2 +- tests/unittests/e1ap/common/e1ap_cu_cp_test_messages.cpp | 2 +- tests/unittests/e1ap/common/e1ap_cu_cp_test_messages.h | 2 +- tests/unittests/e1ap/common/e1ap_cu_up_test_messages.cpp | 2 +- tests/unittests/e1ap/common/e1ap_cu_up_test_messages.h | 2 +- tests/unittests/e1ap/common/test_helpers.cpp | 2 +- tests/unittests/e1ap/common/test_helpers.h | 2 +- tests/unittests/e1ap/cu_cp/CMakeLists.txt | 2 +- .../e1ap_cu_cp_bearer_context_modification_procedure_test.cpp | 2 +- .../e1ap_cu_cp_bearer_context_release_procedure_test.cpp | 2 +- .../cu_cp/e1ap_cu_cp_bearer_context_setup_procedure_test.cpp | 2 +- .../unittests/e1ap/cu_cp/e1ap_cu_cp_setup_procedure_test.cpp | 2 +- tests/unittests/e1ap/cu_cp/e1ap_cu_cp_test.cpp | 2 +- tests/unittests/e1ap/cu_cp/e1ap_cu_cp_test_helpers.cpp | 2 +- tests/unittests/e1ap/cu_cp/e1ap_cu_cp_test_helpers.h | 2 +- tests/unittests/e1ap/cu_cp/e1ap_cu_cp_ue_context_test.cpp | 2 +- tests/unittests/e1ap/cu_cp/e1ap_test_local_gateway.h | 2 +- tests/unittests/e1ap/cu_up/CMakeLists.txt | 2 +- tests/unittests/e1ap/cu_up/e1ap_cu_up_test.cpp | 2 +- tests/unittests/e1ap/cu_up/e1ap_cu_up_test_helpers.cpp | 2 +- tests/unittests/e1ap/cu_up/e1ap_cu_up_test_helpers.h | 2 +- tests/unittests/e2/CMakeLists.txt | 2 +- tests/unittests/e2/common/e2_asn1_packer_test.cpp | 2 +- tests/unittests/e2/common/e2_test_helpers.h | 2 +- tests/unittests/e2/e2_ric_control_procedure_test.cpp | 2 +- tests/unittests/e2/e2_setup_procedure_test.cpp | 2 +- tests/unittests/e2/e2_subscription_setup_test.cpp | 2 +- tests/unittests/e2/e2ap_network_adapter_test.cpp | 2 +- tests/unittests/e2/e2sm_kpm_meas_provider_test.cpp | 2 +- tests/unittests/e2/e2sm_kpm_test.cpp | 2 +- tests/unittests/f1ap/CMakeLists.txt | 2 +- tests/unittests/f1ap/common/CMakeLists.txt | 2 +- tests/unittests/f1ap/common/f1ap_asn1_helpers_test.cpp | 2 +- tests/unittests/f1ap/common/f1ap_asn1_packer_test.cpp | 2 +- tests/unittests/f1ap/common/f1ap_cu_test_messages.cpp | 2 +- tests/unittests/f1ap/common/f1ap_cu_test_messages.h | 2 +- tests/unittests/f1ap/common/f1ap_du_test_messages.cpp | 2 +- tests/unittests/f1ap/common/f1ap_du_test_messages.h | 2 +- tests/unittests/f1ap/common/test_helpers.h | 2 +- tests/unittests/f1ap/cu_cp/CMakeLists.txt | 2 +- tests/unittests/f1ap/cu_cp/f1ap_cu_msg_filler_test.cpp | 2 +- tests/unittests/f1ap/cu_cp/f1ap_cu_paging_test.cpp | 2 +- tests/unittests/f1ap/cu_cp/f1ap_cu_test.cpp | 2 +- tests/unittests/f1ap/cu_cp/f1ap_cu_test_helpers.cpp | 2 +- tests/unittests/f1ap/cu_cp/f1ap_cu_test_helpers.h | 2 +- .../cu_cp/f1ap_cu_ue_context_modification_procedure_test.cpp | 2 +- .../f1ap/cu_cp/f1ap_cu_ue_context_release_procedure_test.cpp | 2 +- .../f1ap/cu_cp/f1ap_cu_ue_context_setup_procedure_test.cpp | 2 +- tests/unittests/f1ap/cu_cp/f1ap_cu_ue_context_test.cpp | 2 +- tests/unittests/f1ap/du/CMakeLists.txt | 2 +- .../f1ap/du/f1ap_du_dl_rrc_message_transfer_test.cpp | 2 +- tests/unittests/f1ap/du/f1ap_du_setup_procedure_test.cpp | 2 +- tests/unittests/f1ap/du/f1ap_du_test_helpers.cpp | 2 +- tests/unittests/f1ap/du/f1ap_du_test_helpers.h | 2 +- tests/unittests/f1ap/du/f1ap_du_ue_config_test.cpp | 2 +- .../f1ap/du/f1ap_du_ue_context_modification_test.cpp | 2 +- tests/unittests/f1ap/du/f1ap_du_ue_context_release_test.cpp | 2 +- .../f1ap/du/f1ap_du_ue_context_setup_procedure_test.cpp | 2 +- .../f1ap/du/f1ap_du_ul_rrc_message_transfer_test.cpp | 2 +- tests/unittests/f1u/CMakeLists.txt | 2 +- tests/unittests/f1u/common/f1u_connector_test.cpp | 2 +- tests/unittests/f1u/cu_up/CMakeLists.txt | 2 +- tests/unittests/f1u/cu_up/f1u_cu_up_bearer_test.cpp | 2 +- tests/unittests/f1u/du/CMakeLists.txt | 2 +- tests/unittests/f1u/du/f1u_du_bearer_test.cpp | 2 +- tests/unittests/fapi/CMakeLists.txt | 2 +- tests/unittests/fapi/builders/CMakeLists.txt | 2 +- tests/unittests/fapi/builders/crc_indication_test.cpp | 2 +- tests/unittests/fapi/builders/dl_csi_pdu_test.cpp | 2 +- tests/unittests/fapi/builders/dl_pdcch_pdu_test.cpp | 2 +- tests/unittests/fapi/builders/dl_pdsch_pdu_test.cpp | 2 +- tests/unittests/fapi/builders/dl_ssb_pdu_test.cpp | 2 +- tests/unittests/fapi/builders/dl_tti_request_test.cpp | 2 +- tests/unittests/fapi/builders/error_indication_test.cpp | 2 +- tests/unittests/fapi/builders/rach_indicator_test.cpp | 2 +- tests/unittests/fapi/builders/rx_data_indication_test.cpp | 2 +- tests/unittests/fapi/builders/slot_indication_test.cpp | 2 +- tests/unittests/fapi/builders/tx_data_request_test.cpp | 2 +- .../fapi/builders/tx_precoding_and_beamforming_pdu_test.cpp | 2 +- tests/unittests/fapi/builders/uci_indication_test.cpp | 2 +- tests/unittests/fapi/builders/ul_dci_request_test.cpp | 2 +- tests/unittests/fapi/builders/ul_prach_pdu_test.cpp | 2 +- tests/unittests/fapi/builders/ul_pucch_pdu_test.cpp | 2 +- tests/unittests/fapi/builders/ul_pusch_pdu_test.cpp | 2 +- tests/unittests/fapi/builders/ul_tti_request_test.cpp | 2 +- tests/unittests/fapi/validators/CMakeLists.txt | 2 +- tests/unittests/fapi/validators/crc_indication_test.cpp | 2 +- tests/unittests/fapi/validators/dl_csi_pdu_test.cpp | 2 +- tests/unittests/fapi/validators/dl_pdcch_pdu_test.cpp | 2 +- tests/unittests/fapi/validators/dl_pdsch_pdu_test.cpp | 2 +- tests/unittests/fapi/validators/dl_ssb_pdu_test.cpp | 2 +- tests/unittests/fapi/validators/dl_tti_request_test.cpp | 2 +- tests/unittests/fapi/validators/error_indication_test.cpp | 2 +- tests/unittests/fapi/validators/helpers.cpp | 2 +- tests/unittests/fapi/validators/helpers.h | 2 +- tests/unittests/fapi/validators/rach_indication_test.cpp | 2 +- tests/unittests/fapi/validators/rx_data_indication_test.cpp | 2 +- tests/unittests/fapi/validators/slot_indication_test.cpp | 2 +- tests/unittests/fapi/validators/tx_data_request_test.cpp | 2 +- .../fapi/validators/tx_precoding_and_beamforming_pdu_test.cpp | 2 +- tests/unittests/fapi/validators/uci_indication_test.cpp | 2 +- tests/unittests/fapi/validators/ul_dci_request_test.cpp | 2 +- tests/unittests/fapi/validators/ul_prach_pdu_test.cpp | 2 +- tests/unittests/fapi/validators/ul_pucch_pdu_test.cpp | 2 +- tests/unittests/fapi/validators/ul_pusch_pdu_test.cpp | 2 +- tests/unittests/fapi/validators/ul_tti_request_test.cpp | 2 +- tests/unittests/fapi_adaptor/CMakeLists.txt | 2 +- .../fapi_adaptor/adaptor_performance_dl_tti_request.cpp | 2 +- tests/unittests/fapi_adaptor/mac/CMakeLists.txt | 2 +- .../fapi_adaptor/mac/fapi_to_mac_data_msg_translator_test.cpp | 2 +- .../fapi_adaptor/mac/mac_to_fapi_translator_test.cpp | 2 +- tests/unittests/fapi_adaptor/mac/messages/CMakeLists.txt | 2 +- .../unittests/fapi_adaptor/mac/messages/dl_pdcch_pdu_test.cpp | 2 +- .../unittests/fapi_adaptor/mac/messages/dl_pdsch_pdu_test.cpp | 2 +- tests/unittests/fapi_adaptor/mac/messages/dl_ssb_pdu_test.cpp | 2 +- tests/unittests/fapi_adaptor/mac/messages/helpers.cpp | 2 +- tests/unittests/fapi_adaptor/mac/messages/helpers.h | 2 +- .../unittests/fapi_adaptor/mac/messages/ul_prach_pdu_test.cpp | 2 +- .../unittests/fapi_adaptor/mac/messages/ul_pucch_pdu_test.cpp | 2 +- .../unittests/fapi_adaptor/mac/messages/ul_pusch_pdu_test.cpp | 2 +- tests/unittests/fapi_adaptor/phy/CMakeLists.txt | 2 +- .../fapi_adaptor/phy/fapi_to_phy_translator_test.cpp | 2 +- tests/unittests/fapi_adaptor/phy/messages/CMakeLists.txt | 2 +- .../unittests/fapi_adaptor/phy/messages/dl_pdcch_pdu_test.cpp | 2 +- .../unittests/fapi_adaptor/phy/messages/dl_pdsch_pdu_test.cpp | 2 +- tests/unittests/fapi_adaptor/phy/messages/dl_ssb_pdu_test.cpp | 2 +- .../unittests/fapi_adaptor/phy/messages/ul_prach_pdu_test.cpp | 2 +- .../unittests/fapi_adaptor/phy/messages/ul_pucch_pdu_test.cpp | 2 +- .../unittests/fapi_adaptor/phy/messages/ul_pusch_pdu_test.cpp | 2 +- .../fapi_adaptor/precoding_matrix_table_generator_test.cpp | 2 +- .../unittests/fapi_adaptor/uci_part2_correspondence_test.cpp | 2 +- tests/unittests/gateways/CMakeLists.txt | 2 +- .../gateways/baseband/baseband_gateway_buffer_test_doubles.h | 2 +- .../baseband/baseband_gateway_receiver_test_doubles.h | 2 +- .../gateways/baseband/baseband_gateway_test_doubles.h | 2 +- .../baseband/baseband_gateway_transmitter_test_doubles.h | 2 +- tests/unittests/gateways/sctp_network_gateway_test.cpp | 2 +- tests/unittests/gateways/test_helpers.h | 2 +- tests/unittests/gateways/udp_network_gateway_test.cpp | 2 +- tests/unittests/gnb/CMakeLists.txt | 2 +- tests/unittests/gnb/metrics_plotter_stdout_test.cpp | 2 +- tests/unittests/gtpu/CMakeLists.txt | 2 +- tests/unittests/gtpu/gtpu_demux_test.cpp | 2 +- tests/unittests/gtpu/gtpu_echo_test.cpp | 2 +- tests/unittests/gtpu/gtpu_test.cpp | 2 +- tests/unittests/gtpu/gtpu_test_allocator.cpp | 2 +- tests/unittests/gtpu/gtpu_test_shared.h | 2 +- tests/unittests/gtpu/gtpu_tunnel_ngu_rx_test.cpp | 2 +- tests/unittests/gtpu/gtpu_tunnel_ngu_test.cpp | 2 +- tests/unittests/mac/CMakeLists.txt | 2 +- tests/unittests/mac/dl_sch_pdu_assembler_test.cpp | 2 +- tests/unittests/mac/mac_cell_processor_test.cpp | 2 +- tests/unittests/mac/mac_ctrl_test.cpp | 2 +- tests/unittests/mac/mac_ctrl_test_dummies.cpp | 2 +- tests/unittests/mac/mac_ctrl_test_dummies.h | 2 +- tests/unittests/mac/mac_dl_cfg_test.cpp | 2 +- tests/unittests/mac/mac_rar_pdu_assembler_test.cpp | 2 +- tests/unittests/mac/mac_rlf_detector_test.cpp | 2 +- tests/unittests/mac/mac_test_helpers.cpp | 2 +- tests/unittests/mac/mac_test_helpers.h | 2 +- tests/unittests/mac/mac_ue_create_test.cpp | 2 +- tests/unittests/mac/mac_ul_pdu_test.cpp | 2 +- tests/unittests/mac/mac_ul_processor_test.cpp | 2 +- tests/unittests/ngap/CMakeLists.txt | 2 +- tests/unittests/ngap/ng_setup_procedure_test.cpp | 2 +- tests/unittests/ngap/ngap_asn1_packer_test.cpp | 2 +- tests/unittests/ngap/ngap_error_indication_test.cpp | 2 +- tests/unittests/ngap/ngap_handover_test.cpp | 2 +- tests/unittests/ngap/ngap_nas_message_test.cpp | 2 +- tests/unittests/ngap/ngap_paging_test.cpp | 2 +- .../ngap/ngap_pdu_session_resource_release_procedure_test.cpp | 2 +- .../ngap/ngap_pdu_session_resource_setup_procedure_test.cpp | 2 +- tests/unittests/ngap/ngap_test_helpers.cpp | 2 +- tests/unittests/ngap/ngap_test_helpers.h | 2 +- tests/unittests/ngap/ngap_test_messages.cpp | 2 +- tests/unittests/ngap/ngap_test_messages.h | 2 +- .../ngap/ngap_ue_context_management_procedure_test.cpp | 2 +- tests/unittests/ngap/test_helpers.h | 2 +- tests/unittests/ofh/CMakeLists.txt | 2 +- tests/unittests/ofh/compression/CMakeLists.txt | 2 +- tests/unittests/ofh/compression/ofh_compression_test.cpp | 2 +- tests/unittests/ofh/compression/ofh_compression_test_data.h | 2 +- .../ofh/compression/ofh_iq_compressor_test_doubles.h | 2 +- .../ofh/compression/ofh_iq_decompressor_test_doubles.h | 2 +- tests/unittests/ofh/ecpri/CMakeLists.txt | 2 +- tests/unittests/ofh/ecpri/ecpri_packet_builder_test.cpp | 2 +- tests/unittests/ofh/ecpri/ecpri_packet_builder_test_doubles.h | 2 +- tests/unittests/ofh/ecpri/ecpri_packet_decoder_impl_test.cpp | 2 +- tests/unittests/ofh/ethernet/CMakeLists.txt | 2 +- tests/unittests/ofh/ethernet/ethernet_frame_pool_test.cpp | 2 +- .../ofh/ethernet/vlan_ethernet_frame_builder_test.cpp | 2 +- .../ofh/ethernet/vlan_ethernet_frame_builder_test_doubles.h | 2 +- .../ofh/ethernet/vlan_ethernet_frame_decoder_test.cpp | 2 +- .../ofh/ofh_uplane_rx_symbol_notifier_test_doubles.h | 2 +- tests/unittests/ofh/receiver/CMakeLists.txt | 2 +- tests/unittests/ofh/receiver/helpers.h | 2 +- .../receiver/ofh_data_flow_uplane_uplink_data_impl_test.cpp | 2 +- .../receiver/ofh_data_flow_uplane_uplink_prach_impl_test.cpp | 2 +- tests/unittests/ofh/receiver/ofh_message_receiver_test.cpp | 2 +- tests/unittests/ofh/receiver/ofh_rx_window_checker_test.cpp | 2 +- .../ofh/receiver/ofh_sequence_id_checker_impl_test.cpp | 2 +- .../ofh/receiver/ofh_uplane_prach_data_flow_notifier_test.cpp | 2 +- .../ofh_uplane_prach_symbol_data_flow_writer_test.cpp | 2 +- .../receiver/ofh_uplane_rx_symbol_data_flow_notifier_test.cpp | 2 +- .../receiver/ofh_uplane_rx_symbol_data_flow_writer_test.cpp | 2 +- tests/unittests/ofh/serdes/CMakeLists.txt | 2 +- ...fh_cplane_packet_builder_dynamic_compression_impl_test.cpp | 2 +- .../ofh/serdes/ofh_cplane_packet_builder_impl_test.cpp | 2 +- ...ofh_cplane_packet_builder_static_compression_impl_test.cpp | 2 +- .../serdes/ofh_uplane_packet_builder_dynamic_impl_test.cpp | 2 +- .../ofh/serdes/ofh_uplane_packet_builder_static_impl_test.cpp | 2 +- .../serdes/ofh_uplane_packet_decoder_dynamic_impl_test.cpp | 2 +- .../ofh/serdes/ofh_uplane_packet_decoder_static_impl_test.cpp | 2 +- tests/unittests/ofh/slot_symbol_point_test.cpp | 2 +- tests/unittests/ofh/transmitter/CMakeLists.txt | 2 +- .../ofh_data_flow_cplane_scheduling_commands_test.cpp | 2 +- .../ofh_data_flow_cplane_scheduling_commands_test_doubles.h | 2 +- .../ofh_data_flow_uplane_downlink_data_impl_test.cpp | 2 +- .../ofh/transmitter/ofh_downlink_handler_impl_test.cpp | 2 +- .../transmitter/ofh_uplane_packet_segment_calculator_test.cpp | 2 +- .../ofh/transmitter/ofh_uplink_request_handler_impl_test.cpp | 2 +- .../ofh/transmitter/sequence_identifier_generator_test.cpp | 2 +- tests/unittests/pcap/CMakeLists.txt | 2 +- tests/unittests/pcap/mac_pcap_test.cpp | 2 +- tests/unittests/pcap/ngap_pcap_test.cpp | 2 +- tests/unittests/pcap/rlc_pcap_test.cpp | 2 +- tests/unittests/pdcp/CMakeLists.txt | 2 +- tests/unittests/pdcp/pdcp_gen_helper.cpp | 2 +- tests/unittests/pdcp/pdcp_rx_metrics_test.cpp | 2 +- tests/unittests/pdcp/pdcp_rx_metrics_test.h | 2 +- tests/unittests/pdcp/pdcp_rx_reestablish_test.cpp | 2 +- tests/unittests/pdcp/pdcp_rx_reestablish_test.h | 2 +- tests/unittests/pdcp/pdcp_rx_status_report_test.cpp | 2 +- tests/unittests/pdcp/pdcp_rx_status_report_test.h | 2 +- tests/unittests/pdcp/pdcp_rx_test.cpp | 2 +- tests/unittests/pdcp/pdcp_rx_test.h | 2 +- tests/unittests/pdcp/pdcp_rx_test_helpers.h | 2 +- tests/unittests/pdcp/pdcp_test_vectors.h | 2 +- tests/unittests/pdcp/pdcp_tx_empty_pool_test.cpp | 2 +- tests/unittests/pdcp/pdcp_tx_metrics_test.cpp | 2 +- tests/unittests/pdcp/pdcp_tx_metrics_test.h | 2 +- tests/unittests/pdcp/pdcp_tx_reestablish_test.cpp | 2 +- tests/unittests/pdcp/pdcp_tx_reestablish_test.h | 2 +- tests/unittests/pdcp/pdcp_tx_status_report_test.cpp | 2 +- tests/unittests/pdcp/pdcp_tx_status_report_test.h | 2 +- tests/unittests/pdcp/pdcp_tx_test.cpp | 2 +- tests/unittests/pdcp/pdcp_tx_test.h | 2 +- tests/unittests/pdcp/pdcp_tx_test_helpers.h | 2 +- tests/unittests/phy/CMakeLists.txt | 2 +- tests/unittests/phy/generic_functions/CMakeLists.txt | 2 +- tests/unittests/phy/generic_functions/dft_processor_test.cpp | 2 +- .../unittests/phy/generic_functions/dft_processor_test_data.h | 2 +- .../phy/generic_functions/dft_processor_test_doubles.h | 2 +- .../phy/generic_functions/dft_processor_vectortest.cpp | 2 +- .../unittests/phy/generic_functions/precoding/CMakeLists.txt | 2 +- .../phy/generic_functions/precoding/channel_precoder_test.cpp | 2 +- tests/unittests/phy/lower/CMakeLists.txt | 2 +- .../amplitude_control/amplitude_controller_test_doubles.h | 2 +- tests/unittests/phy/lower/lower_phy_test.cpp | 2 +- tests/unittests/phy/lower/lower_phy_test_doubles.h | 2 +- tests/unittests/phy/lower/modulation/CMakeLists.txt | 2 +- .../phy/lower/modulation/ofdm_demodulator_test_data.h | 2 +- .../phy/lower/modulation/ofdm_demodulator_test_doubles.h | 2 +- .../phy/lower/modulation/ofdm_demodulator_unittest.cpp | 2 +- .../phy/lower/modulation/ofdm_demodulator_vectortest.cpp | 2 +- .../unittests/phy/lower/modulation/ofdm_modulator_test_data.h | 2 +- .../phy/lower/modulation/ofdm_modulator_test_doubles.h | 2 +- .../phy/lower/modulation/ofdm_modulator_unittest.cpp | 2 +- .../phy/lower/modulation/ofdm_modulator_vectortest.cpp | 2 +- .../phy/lower/modulation/ofdm_prach_demodulator_test.cpp | 2 +- .../phy/lower/modulation/ofdm_prach_demodulator_test_data.h | 2 +- .../lower/modulation/ofdm_prach_demodulator_test_doubles.h | 2 +- tests/unittests/phy/lower/processors/CMakeLists.txt | 2 +- tests/unittests/phy/lower/processors/downlink/CMakeLists.txt | 2 +- .../downlink/downlink_processor_notifier_test_doubles.h | 2 +- .../processors/downlink/downlink_processor_test_doubles.h | 2 +- .../processors/downlink/lower_phy_downlink_processor_test.cpp | 2 +- .../phy/lower/processors/downlink/pdxch/CMakeLists.txt | 2 +- .../downlink/pdxch/pdxch_processor_notifier_test_doubles.h | 2 +- .../lower/processors/downlink/pdxch/pdxch_processor_test.cpp | 2 +- .../processors/downlink/pdxch/pdxch_processor_test_doubles.h | 2 +- tests/unittests/phy/lower/processors/uplink/CMakeLists.txt | 2 +- .../processors/uplink/lower_phy_uplink_processor_test.cpp | 2 +- .../phy/lower/processors/uplink/prach/CMakeLists.txt | 2 +- .../uplink/prach/prach_processor_notifier_test_doubles.h | 2 +- .../lower/processors/uplink/prach/prach_processor_test.cpp | 2 +- .../processors/uplink/prach/prach_processor_test_doubles.h | 2 +- .../phy/lower/processors/uplink/puxch/CMakeLists.txt | 2 +- .../uplink/puxch/puxch_processor_notifier_test_doubles.h | 2 +- .../lower/processors/uplink/puxch/puxch_processor_test.cpp | 2 +- .../processors/uplink/puxch/puxch_processor_test_doubles.h | 2 +- .../uplink/uplink_processor_notifier_test_doubles.h | 2 +- tests/unittests/phy/phy_test_utils.h | 2 +- tests/unittests/phy/support/CMakeLists.txt | 2 +- tests/unittests/phy/support/interpolator_test.cpp | 2 +- tests/unittests/phy/support/prach_buffer_test_doubles.h | 2 +- tests/unittests/phy/support/precoding_configuration_test.cpp | 2 +- tests/unittests/phy/support/re_pattern_test.cpp | 2 +- tests/unittests/phy/support/resource_grid_mapper_test.cpp | 2 +- .../unittests/phy/support/resource_grid_mapper_test_doubles.h | 2 +- tests/unittests/phy/support/resource_grid_pool_test.cpp | 2 +- tests/unittests/phy/support/resource_grid_test.cpp | 2 +- tests/unittests/phy/support/resource_grid_test_doubles.h | 2 +- tests/unittests/phy/upper/CMakeLists.txt | 2 +- tests/unittests/phy/upper/channel_coding/CMakeLists.txt | 2 +- .../phy/upper/channel_coding/crc_calculator_test.cpp | 2 +- tests/unittests/phy/upper/channel_coding/ldpc/CMakeLists.txt | 2 +- .../phy/upper/channel_coding/ldpc/ldpc_enc_dec_test.cpp | 2 +- .../phy/upper/channel_coding/ldpc/ldpc_encoder_test_data.h | 2 +- .../upper/channel_coding/ldpc/ldpc_rate_matcher_test_data.h | 2 +- .../unittests/phy/upper/channel_coding/ldpc/ldpc_rm_test.cpp | 2 +- .../phy/upper/channel_coding/ldpc/ldpc_segmenter_test.cpp | 2 +- .../phy/upper/channel_coding/ldpc/ldpc_segmenter_test_data.h | 2 +- tests/unittests/phy/upper/channel_coding/polar/CMakeLists.txt | 2 +- .../phy/upper/channel_coding/polar/polar_chain_test.cpp | 2 +- .../phy/upper/channel_coding/polar/polar_interleaver_test.cpp | 2 +- tests/unittests/phy/upper/channel_coding/short/CMakeLists.txt | 2 +- .../upper/channel_coding/short/short_block_detector_test.cpp | 2 +- .../channel_coding/short/short_block_detector_test_data.h | 2 +- .../upper/channel_coding/short/short_block_encoder_test.cpp | 2 +- .../channel_coding/short/short_block_encoder_test_data.h | 2 +- tests/unittests/phy/upper/channel_modulation/CMakeLists.txt | 2 +- .../phy/upper/channel_modulation/demodulation_mapper_test.cpp | 2 +- .../upper/channel_modulation/demodulation_mapper_test_data.h | 2 +- .../phy/upper/channel_modulation/evm_calculator_test.cpp | 2 +- .../phy/upper/channel_modulation/modulation_mapper_test.cpp | 2 +- .../upper/channel_modulation/modulation_mapper_test_data.h | 2 +- tests/unittests/phy/upper/channel_processors/CMakeLists.txt | 2 +- .../phy/upper/channel_processors/pbch_encoder_doubles.h | 2 +- .../phy/upper/channel_processors/pbch_encoder_test.cpp | 2 +- .../phy/upper/channel_processors/pbch_encoder_test_data.h | 2 +- .../phy/upper/channel_processors/pbch_modulator_doubles.h | 2 +- .../phy/upper/channel_processors/pbch_modulator_test.cpp | 2 +- .../phy/upper/channel_processors/pbch_modulator_test_data.h | 2 +- .../phy/upper/channel_processors/pdcch_encoder_test.cpp | 2 +- .../phy/upper/channel_processors/pdcch_encoder_test_data.h | 2 +- .../phy/upper/channel_processors/pdcch_encoder_test_doubles.h | 2 +- .../phy/upper/channel_processors/pdcch_modulator_test.cpp | 2 +- .../phy/upper/channel_processors/pdcch_modulator_test_data.h | 2 +- .../upper/channel_processors/pdcch_modulator_test_doubles.h | 2 +- .../phy/upper/channel_processors/pdcch_processor_test_data.h | 2 +- .../upper/channel_processors/pdcch_processor_test_doubles.h | 2 +- .../phy/upper/channel_processors/pdcch_processor_unittest.cpp | 2 +- .../upper/channel_processors/pdcch_processor_vectortest.cpp | 2 +- .../phy/upper/channel_processors/pdsch_encoder_test.cpp | 2 +- .../phy/upper/channel_processors/pdsch_encoder_test_data.h | 2 +- .../phy/upper/channel_processors/pdsch_modulator_test.cpp | 2 +- .../phy/upper/channel_processors/pdsch_modulator_test_data.h | 2 +- .../phy/upper/channel_processors/pdsch_processor_test_data.h | 2 +- .../upper/channel_processors/pdsch_processor_test_doubles.h | 2 +- .../phy/upper/channel_processors/pdsch_processor_unittest.cpp | 2 +- .../channel_processors/pdsch_processor_validator_test.cpp | 2 +- .../upper/channel_processors/pdsch_processor_vectortest.cpp | 2 +- .../phy/upper/channel_processors/prach_detector_test_data.h | 2 +- .../upper/channel_processors/prach_detector_test_doubles.h | 2 +- .../upper/channel_processors/prach_detector_vectortest.cpp | 2 +- .../phy/upper/channel_processors/prach_generator_test_data.h | 2 +- .../upper/channel_processors/prach_generator_test_doubles.h | 2 +- .../upper/channel_processors/prach_generator_vectortest.cpp | 2 +- .../channel_processors/pucch_demodulator_format2_test.cpp | 2 +- .../channel_processors/pucch_demodulator_format2_test_data.h | 2 +- .../phy/upper/channel_processors/pucch_detector_test.cpp | 2 +- .../phy/upper/channel_processors/pucch_detector_test_data.h | 2 +- .../upper/channel_processors/pucch_detector_test_doubles.h | 2 +- .../channel_processors/pucch_processor_format1_test_data.h | 2 +- .../channel_processors/pucch_processor_format1_unittest.cpp | 2 +- .../channel_processors/pucch_processor_format1_vectortest.cpp | 2 +- .../channel_processors/pucch_processor_format2_test_data.h | 2 +- .../channel_processors/pucch_processor_format2_vectortest.cpp | 2 +- .../upper/channel_processors/pucch_processor_test_doubles.h | 2 +- .../pucch_processor_validator_format1_test.cpp | 2 +- .../pucch_processor_validator_format2_test.cpp | 2 +- .../phy/upper/channel_processors/pusch/CMakeLists.txt | 2 +- .../pusch/pusch_codeword_buffer_test_doubles.h | 2 +- .../pusch/pusch_decoder_buffer_test_doubles.h | 2 +- .../channel_processors/pusch/pusch_decoder_notifier_spy.h | 2 +- .../upper/channel_processors/pusch/pusch_decoder_test_data.h | 2 +- .../channel_processors/pusch/pusch_decoder_test_doubles.h | 2 +- .../channel_processors/pusch/pusch_decoder_vectortest.cpp | 2 +- .../pusch/pusch_demodulator_notifier_test_doubles.h | 2 +- .../channel_processors/pusch/pusch_demodulator_test_data.h | 2 +- .../channel_processors/pusch/pusch_demodulator_test_doubles.h | 2 +- .../channel_processors/pusch/pusch_demodulator_vectortest.cpp | 2 +- .../pusch/pusch_processor_result_test_doubles.h | 2 +- .../channel_processors/pusch/pusch_processor_test_data.h | 2 +- .../channel_processors/pusch/pusch_processor_test_doubles.h | 2 +- .../channel_processors/pusch/pusch_processor_unittest.cpp | 2 +- .../pusch/pusch_processor_validator_test.cpp | 2 +- .../channel_processors/pusch/pusch_processor_vectortest.cpp | 2 +- .../upper/channel_processors/pusch/ulsch_demultiplex_test.cpp | 2 +- .../channel_processors/pusch/ulsch_demultiplex_test_data.h | 2 +- .../channel_processors/pusch/ulsch_demultiplex_test_doubles.h | 2 +- .../phy/upper/channel_processors/ssb_processor_test_data.h | 2 +- .../phy/upper/channel_processors/ssb_processor_test_doubles.h | 2 +- .../phy/upper/channel_processors/ssb_processor_unittest.cpp | 2 +- .../phy/upper/channel_processors/ssb_processor_vectortest.cpp | 2 +- .../unittests/phy/upper/channel_processors/uci/CMakeLists.txt | 2 +- .../phy/upper/channel_processors/uci/uci_decoder_test.cpp | 2 +- .../phy/upper/channel_processors/uci/uci_decoder_test_data.h | 2 +- .../upper/channel_processors/uci/uci_decoder_test_doubles.h | 2 +- tests/unittests/phy/upper/dl_processor_test_data.h | 2 +- tests/unittests/phy/upper/downlink_processor_pool_test.cpp | 2 +- tests/unittests/phy/upper/downlink_processor_test.cpp | 2 +- tests/unittests/phy/upper/downlink_processor_test_doubles.h | 2 +- tests/unittests/phy/upper/equalization/CMakeLists.txt | 2 +- .../phy/upper/equalization/channel_equalizer_test.cpp | 2 +- .../phy/upper/equalization/channel_equalizer_test_data.h | 2 +- tests/unittests/phy/upper/hard_decision_test.cpp | 2 +- tests/unittests/phy/upper/log_likelihood_ratio_test.cpp | 2 +- tests/unittests/phy/upper/rx_buffer_pool_test.cpp | 2 +- tests/unittests/phy/upper/rx_buffer_test_doubles.h | 2 +- tests/unittests/phy/upper/sequence_generators/CMakeLists.txt | 2 +- .../sequence_generators/low_papr_sequence_generator_test.cpp | 2 +- .../sequence_generators/pseudo_random_generator_test.cpp | 2 +- tests/unittests/phy/upper/signal_processors/CMakeLists.txt | 2 +- .../phy/upper/signal_processors/dmrs_pbch_processor_doubles.h | 2 +- .../phy/upper/signal_processors/dmrs_pbch_processor_test.cpp | 2 +- .../upper/signal_processors/dmrs_pbch_processor_test_data.h | 2 +- .../phy/upper/signal_processors/dmrs_pdcch_processor_test.cpp | 2 +- .../upper/signal_processors/dmrs_pdcch_processor_test_data.h | 2 +- .../signal_processors/dmrs_pdcch_processor_test_doubles.h | 2 +- .../phy/upper/signal_processors/dmrs_pdsch_processor_test.cpp | 2 +- .../upper/signal_processors/dmrs_pdsch_processor_test_data.h | 2 +- .../phy/upper/signal_processors/dmrs_pucch_processor_test.cpp | 2 +- .../upper/signal_processors/dmrs_pucch_processor_test_data.h | 2 +- .../signal_processors/dmrs_pucch_processor_test_doubles.h | 2 +- .../phy/upper/signal_processors/dmrs_pusch_estimator_test.cpp | 2 +- .../upper/signal_processors/dmrs_pusch_estimator_test_data.h | 2 +- .../signal_processors/dmrs_pusch_estimator_test_doubles.h | 2 +- .../phy/upper/signal_processors/nzp_csi_rs_generator_test.cpp | 2 +- .../upper/signal_processors/nzp_csi_rs_generator_test_data.h | 2 +- .../signal_processors/nzp_csi_rs_generator_test_doubles.h | 2 +- .../upper/signal_processors/port_channel_estimator_test.cpp | 2 +- .../signal_processors/port_channel_estimator_test_data.h | 2 +- .../phy/upper/signal_processors/pss_processor_doubles.h | 2 +- .../phy/upper/signal_processors/pss_processor_test.cpp | 2 +- .../phy/upper/signal_processors/sss_processor_doubles.h | 2 +- .../phy/upper/signal_processors/sss_processor_test.cpp | 2 +- tests/unittests/phy/upper/tx_buffer_pool_test_doubles.h | 2 +- tests/unittests/phy/upper/tx_buffer_test_doubles.h | 2 +- tests/unittests/phy/upper/uplink_processor_test.cpp | 2 +- tests/unittests/phy/upper/uplink_processor_test_doubles.h | 2 +- tests/unittests/phy/upper/uplink_request_processor_test.cpp | 2 +- .../phy/upper/uplink_request_processor_test_doubles.h | 2 +- tests/unittests/phy/upper/upper_phy_rg_gateway_test_doubles.h | 2 +- .../phy/upper/upper_phy_rx_results_notifier_test_doubles.h | 2 +- .../unittests/phy/upper/upper_phy_rx_symbol_handler_test.cpp | 2 +- .../upper/upper_phy_rx_symbol_request_notifier_test_doubles.h | 2 +- tests/unittests/phy/upper/vrb_to_prb_mapper_test.cpp | 2 +- tests/unittests/psup/CMakeLists.txt | 2 +- tests/unittests/psup/psup_packing_test.cpp | 2 +- tests/unittests/radio/CMakeLists.txt | 2 +- tests/unittests/radio/zmq/CMakeLists.txt | 2 +- tests/unittests/radio/zmq/radio_zmq_loopback_test.cpp | 2 +- tests/unittests/radio/zmq/radio_zmq_validator_test.cpp | 2 +- tests/unittests/ran/CMakeLists.txt | 2 +- tests/unittests/ran/band_helper_test.cpp | 2 +- tests/unittests/ran/bcd_helpers_test.cpp | 2 +- .../ran/csi_report/csi_report_on_pucch_helpers_test.cpp | 2 +- .../ran/csi_report/csi_report_on_pucch_validator_test.cpp | 2 +- .../ran/csi_report/csi_report_on_pusch_helpers_test.cpp | 2 +- .../ran/csi_report/csi_report_on_pusch_validator_test.cpp | 2 +- tests/unittests/ran/nr_cgi_helpers_test.cpp | 2 +- tests/unittests/ran/pdcch/dci_packing_test.cpp | 2 +- tests/unittests/ran/pdcch/dci_packing_validator_test.cpp | 2 +- tests/unittests/ran/pdcch/pdcch_candidates_common_test.cpp | 2 +- tests/unittests/ran/pdcch/pdcch_candidates_common_test_data.h | 2 +- tests/unittests/ran/pdcch/pdcch_candidates_ue_test.cpp | 2 +- tests/unittests/ran/pdcch/pdcch_candidates_ue_test_data.h | 2 +- .../ran/pdcch/pdcch_type0_css_coreset_config_test.cpp | 2 +- tests/unittests/ran/pdsch/pdsch_mcs_table_test.cpp | 2 +- tests/unittests/ran/prach/prach_configuration_test.cpp | 2 +- tests/unittests/ran/prach/prach_cyclic_shifts_test.cpp | 2 +- tests/unittests/ran/prach/prach_frequency_mapping_test.cpp | 2 +- tests/unittests/ran/pucch/pucch_info_test.cpp | 2 +- tests/unittests/ran/pusch/pusch_mcs_table_test.cpp | 2 +- tests/unittests/ran/pusch/ulsch_info_test.cpp | 2 +- tests/unittests/ran/pusch/ulsch_info_test_data.h | 2 +- .../resource_allocation_frequency_test.cpp | 2 +- tests/unittests/ran/slot_point_test.cpp | 2 +- tests/unittests/ran/ssb_coreset0_freq_pos_checker.cpp | 2 +- tests/unittests/ran/ssb_coreset0_freq_pos_checker.h | 2 +- tests/unittests/ran/ssb_gscn_test.cpp | 2 +- tests/unittests/ran/ssb_mapping_test.cpp | 2 +- tests/unittests/ran/test_ssb_coreset0_freq_pos_generator.cpp | 2 +- tests/unittests/rlc/CMakeLists.txt | 2 +- tests/unittests/rlc/rlc_am_pdu_test.cpp | 2 +- tests/unittests/rlc/rlc_pdu_recycler_test.cpp | 2 +- tests/unittests/rlc/rlc_retx_queue_test.cpp | 2 +- tests/unittests/rlc/rlc_rx_am_test.cpp | 2 +- tests/unittests/rlc/rlc_rx_tm_test.cpp | 2 +- tests/unittests/rlc/rlc_sdu_queue_test.cpp | 2 +- tests/unittests/rlc/rlc_test_helpers.h | 2 +- tests/unittests/rlc/rlc_tx_am_test.cpp | 2 +- tests/unittests/rlc/rlc_tx_tm_test.cpp | 2 +- tests/unittests/rlc/rlc_um_pdu_test.cpp | 2 +- tests/unittests/rlc/rlc_um_test.cpp | 2 +- tests/unittests/rrc/CMakeLists.txt | 2 +- tests/unittests/rrc/rrc_ue_capability_transfer_proc_test.cpp | 2 +- tests/unittests/rrc/rrc_ue_dl_info_transfer_proc_test.cpp | 2 +- tests/unittests/rrc/rrc_ue_meas_report_test.cpp | 2 +- tests/unittests/rrc/rrc_ue_reconfig_proc_test.cpp | 2 +- tests/unittests/rrc/rrc_ue_reest_proc_test.cpp | 2 +- tests/unittests/rrc/rrc_ue_setup_proc_test.cpp | 2 +- tests/unittests/rrc/rrc_ue_smc_proc_test.cpp | 2 +- tests/unittests/rrc/rrc_ue_test_helpers.h | 2 +- tests/unittests/rrc/rrc_ue_test_messages.cpp | 2 +- tests/unittests/rrc/rrc_ue_test_messages.h | 2 +- tests/unittests/rrc/test_helpers.h | 2 +- tests/unittests/scheduler/CMakeLists.txt | 2 +- tests/unittests/scheduler/cell_resource_grid/CMakeLists.txt | 2 +- .../scheduler/cell_resource_grid/cell_resource_grid_test.cpp | 2 +- .../unittests/scheduler/cell_resource_grid/sched_prb_test.cpp | 2 +- tests/unittests/scheduler/common_scheduling/CMakeLists.txt | 2 +- .../scheduler/common_scheduling/paging_scheduler_test.cpp | 2 +- .../scheduler/common_scheduling/prach_scheduler_test.cpp | 2 +- .../scheduler/common_scheduling/ra_scheduler_test.cpp | 2 +- .../scheduler/common_scheduling/sib1_scheduler_test.cpp | 2 +- .../scheduler/common_scheduling/ssb_scheduler_test.cpp | 2 +- tests/unittests/scheduler/config/CMakeLists.txt | 2 +- tests/unittests/scheduler/config/csi_helper_test.cpp | 2 +- tests/unittests/scheduler/multi_cell_scheduler_test.cpp | 2 +- tests/unittests/scheduler/multiple_ue_sched_test.cpp | 2 +- .../scheduler/pdcch/pdcch_resource_allocator_test.cpp | 2 +- tests/unittests/scheduler/policy/CMakeLists.txt | 2 +- tests/unittests/scheduler/policy/scheduler_policy_test.cpp | 2 +- tests/unittests/scheduler/scheduler_metrics_handler_test.cpp | 2 +- tests/unittests/scheduler/scheduler_no_ue_test.cpp | 2 +- tests/unittests/scheduler/scheduler_retx_test.cpp | 2 +- tests/unittests/scheduler/scheduler_ta_cmd_test.cpp | 2 +- tests/unittests/scheduler/scheduler_tdd_test.cpp | 2 +- tests/unittests/scheduler/scheduler_ue_fallback_mode_test.cpp | 2 +- tests/unittests/scheduler/scheduler_ue_removal_test.cpp | 2 +- tests/unittests/scheduler/support/CMakeLists.txt | 2 +- tests/unittests/scheduler/support/dmrs_helpers_test.cpp | 2 +- tests/unittests/scheduler/support/mcs_calculator_test.cpp | 2 +- tests/unittests/scheduler/support/mcs_tbs_calculator_test.cpp | 2 +- .../support/pdcch/pdcch_type0_css_occassions_test.cpp | 2 +- .../support/pdcch_aggregation_level_calculator_test.cpp | 2 +- .../support/pdsch/pdsch_default_time_allocation_test.cpp | 2 +- .../scheduler/support/pdsch/pdsch_dmrs_symbol_mask_test.cpp | 2 +- tests/unittests/scheduler/support/prbs_calculator_test.cpp | 2 +- .../scheduler/support/pucch/pucch_default_resource_test.cpp | 2 +- .../support/pusch/pusch_default_time_allocation_test.cpp | 2 +- .../scheduler/support/pusch/pusch_dmrs_symbol_mask_test.cpp | 2 +- tests/unittests/scheduler/support/tbs_calculator_test.cpp | 2 +- tests/unittests/scheduler/support/tbs_calculator_test_data.h | 2 +- tests/unittests/scheduler/test_utils/CMakeLists.txt | 2 +- tests/unittests/scheduler/test_utils/config_generators.h | 2 +- tests/unittests/scheduler/test_utils/dummy_test_components.h | 2 +- tests/unittests/scheduler/test_utils/indication_generators.h | 2 +- tests/unittests/scheduler/test_utils/result_test_helpers.h | 2 +- .../scheduler/test_utils/scheduler_output_test_helpers.cpp | 2 +- .../scheduler/test_utils/scheduler_output_test_helpers.h | 2 +- tests/unittests/scheduler/test_utils/scheduler_test_bench.h | 2 +- tests/unittests/scheduler/test_utils/scheduler_test_suite.cpp | 2 +- tests/unittests/scheduler/test_utils/scheduler_test_suite.h | 2 +- tests/unittests/scheduler/uci_and_pucch/CMakeLists.txt | 2 +- .../scheduler/uci_and_pucch/pucch_alloc_common_harq_test.cpp | 2 +- .../scheduler/uci_and_pucch/pucch_alloc_harq_sr_csi_test.cpp | 2 +- .../scheduler/uci_and_pucch/pucch_guardbands_sched_test.cpp | 2 +- .../scheduler/uci_and_pucch/pucch_res_manager_test.cpp | 2 +- .../scheduler/uci_and_pucch/scheduler_uci_indication_test.cpp | 2 +- .../unittests/scheduler/uci_and_pucch/uci_allocator_test.cpp | 2 +- .../unittests/scheduler/uci_and_pucch/uci_scheduling_test.cpp | 2 +- tests/unittests/scheduler/uci_and_pucch/uci_test_utils.cpp | 2 +- tests/unittests/scheduler/uci_and_pucch/uci_test_utils.h | 2 +- tests/unittests/scheduler/ue_scheduling/CMakeLists.txt | 2 +- tests/unittests/scheduler/ue_scheduling/harq_entity_test.cpp | 2 +- tests/unittests/scheduler/ue_scheduling/harq_process_test.cpp | 2 +- .../scheduler/ue_scheduling/logical_channel_test.cpp | 2 +- .../unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp | 2 +- tests/unittests/scheduler/ue_scheduling/ta_manager_test.cpp | 2 +- .../scheduler/ue_scheduling/ue_configuration_test.cpp | 2 +- .../scheduler/ue_scheduling/ue_grid_allocator_test.cpp | 2 +- .../scheduler/ue_scheduling/ue_harq_link_adaptation_test.cpp | 2 +- .../ue_scheduling/ue_link_adaptation_controller_test.cpp | 2 +- .../ue_scheduling/ue_pdsch_param_candidate_searcher_test.cpp | 2 +- .../scheduler/ue_scheduling/ul_logical_channel_test.cpp | 2 +- tests/unittests/sdap/CMakeLists.txt | 2 +- tests/unittests/sdap/sdap_rx_test.cpp | 2 +- tests/unittests/sdap/sdap_test.cpp | 2 +- tests/unittests/sdap/sdap_test.h | 2 +- tests/unittests/sdap/sdap_tx_test.cpp | 2 +- tests/unittests/security/CMakeLists.txt | 2 +- tests/unittests/security/security_test.cpp | 2 +- tests/unittests/srslog/CMakeLists.txt | 2 +- tests/unittests/srslog/any_test.cpp | 2 +- tests/unittests/srslog/benchmarks/frontend_latency.cpp | 2 +- tests/unittests/srslog/context_test.cpp | 2 +- tests/unittests/srslog/event_trace_test.cpp | 2 +- tests/unittests/srslog/file_sink_test.cpp | 2 +- tests/unittests/srslog/file_test_utils.h | 2 +- tests/unittests/srslog/file_utils_test.cpp | 2 +- tests/unittests/srslog/json_formatter_test.cpp | 2 +- tests/unittests/srslog/log_backend_test.cpp | 2 +- tests/unittests/srslog/log_channel_test.cpp | 2 +- tests/unittests/srslog/logger_test.cpp | 2 +- tests/unittests/srslog/srslog_test.cpp | 2 +- tests/unittests/srslog/syslog_sink_test.cpp | 2 +- tests/unittests/srslog/test_dummies.h | 2 +- tests/unittests/srslog/testing_helpers.h | 2 +- tests/unittests/srslog/text_formatter_test.cpp | 2 +- tests/unittests/srsvec/CMakeLists.txt | 2 +- tests/unittests/srsvec/srsvec_add_test.cpp | 2 +- tests/unittests/srsvec/srsvec_aligned_test.cpp | 2 +- tests/unittests/srsvec/srsvec_binary_test.cpp | 2 +- tests/unittests/srsvec/srsvec_bit_test.cpp | 2 +- tests/unittests/srsvec/srsvec_clipping_test.cpp | 2 +- tests/unittests/srsvec/srsvec_compare_test.cpp | 2 +- tests/unittests/srsvec/srsvec_convert_test.cpp | 2 +- tests/unittests/srsvec/srsvec_convolution_test.cpp | 2 +- tests/unittests/srsvec/srsvec_division_test.cpp | 2 +- tests/unittests/srsvec/srsvec_dot_prod_test.cpp | 2 +- tests/unittests/srsvec/srsvec_modulus_square_test.cpp | 2 +- tests/unittests/srsvec/srsvec_prod_test.cpp | 2 +- tests/unittests/srsvec/srsvec_sc_prod_test.cpp | 2 +- tests/unittests/support/CMakeLists.txt | 2 +- tests/unittests/support/async_event_observer_test.cpp | 2 +- tests/unittests/support/async_event_test.cpp | 2 +- tests/unittests/support/async_exec_test.cpp | 2 +- tests/unittests/support/async_queue_test.cpp | 2 +- tests/unittests/support/async_task_test.cpp | 2 +- tests/unittests/support/backtrace_test.cpp | 2 +- tests/unittests/support/bit_encoding_test.cpp | 2 +- tests/unittests/support/complex_normal_random_test.cpp | 2 +- tests/unittests/support/config/validator_helpers_test.cpp | 2 +- tests/unittests/support/event_tracer_test.cpp | 2 +- tests/unittests/support/executors/CMakeLists.txt | 2 +- tests/unittests/support/executors/strand_executor_test.cpp | 2 +- .../support/executors/task_execution_manager_test.cpp | 2 +- tests/unittests/support/executors/task_worker_test.cpp | 2 +- tests/unittests/support/fifo_async_task_scheduler_test.cpp | 2 +- tests/unittests/support/fixed_size_memory_pool_test.cpp | 2 +- tests/unittests/support/function_signature_test.cpp | 2 +- tests/unittests/support/lockfree_object_pool_test.cpp | 2 +- tests/unittests/support/memory_block_list_test.cpp | 2 +- tests/unittests/support/network/CMakeLists.txt | 2 +- tests/unittests/support/network/io_broker_epoll_test.cpp | 2 +- .../support/network/transport_layer_address_test.cpp | 2 +- tests/unittests/support/protocol_transaction_manager_test.cpp | 2 +- tests/unittests/support/ring_buffer_pool_test.cpp | 2 +- tests/unittests/support/stats_test.cpp | 2 +- tests/unittests/support/task_executor_test_doubles.h | 2 +- tests/unittests/support/timer_test.cpp | 2 +- tests/unittests/support/unique_thread_test.cpp | 2 +- tests/unittests/support/units_test.cpp | 2 +- utils/CMakeLists.txt | 2 +- utils/trx_srsran/CMakeLists.txt | 2 +- utils/trx_srsran/trx_srsran.cpp | 2 +- utils/trx_srsran/trx_srsran_test.cpp | 2 +- 3230 files changed, 3231 insertions(+), 3231 deletions(-) diff --git a/.gdbinit b/.gdbinit index 9b3495bc31..ba115581de 100644 --- a/.gdbinit +++ b/.gdbinit @@ -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/.gitlab/ci/e2e/.env b/.gitlab/ci/e2e/.env index 72a8ea09cc..48da88df92 100644 --- a/.gitlab/ci/e2e/.env +++ b/.gitlab/ci/e2e/.env @@ -5,5 +5,5 @@ AMARISOFT_VERSION=2023-03-17 SRSUE_VERSION=23.11 OPEN5GS_VERSION=2.5.6 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin -METRICS_SERVER_VERSION=1.5.0 +METRICS_SERVER_VERSION=1.5.1 DPDK_VERSION=23.07 diff --git a/.gitlab/ci/release/auto_merge.sh b/.gitlab/ci/release/auto_merge.sh index 8826acfbf3..0b21b29a31 100755 --- a/.gitlab/ci/release/auto_merge.sh +++ b/.gitlab/ci/release/auto_merge.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# 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/.gitlab/ci/release/update_headers.sh b/.gitlab/ci/release/update_headers.sh index 65b4305cba..07e17e1765 100755 --- a/.gitlab/ci/release/update_headers.sh +++ b/.gitlab/ci/release/update_headers.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# 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/CMakeLists.txt b/CMakeLists.txt index 7f42fdcd99..98dbf88fb2 100644 --- a/CMakeLists.txt +++ b/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/COPYRIGHT b/COPYRIGHT index 3d6c288b7f..d13bbdfbb9 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,5 +1,5 @@ Files: * -Copyright: 2021-2023, Software Radio Systems Limited. +Copyright: 2021-2024, Software Radio Systems Limited. License: See LICENSE file @@ -7,7 +7,7 @@ The following files are used within srsRAN: Files: docs/doxygen-awesome-sidebar-only.css docs/doxygen-awesome.css -Copyright: 2021-2022 jothepro +Copyright: 2021-2024 jothepro License: MIT diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 148d021e0b..ecaf53da53 100644 --- a/apps/CMakeLists.txt +++ b/apps/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/apps/examples/CMakeLists.txt b/apps/examples/CMakeLists.txt index e0527df76c..9d2d091ed6 100644 --- a/apps/examples/CMakeLists.txt +++ b/apps/examples/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/apps/examples/du/CMakeLists.txt b/apps/examples/du/CMakeLists.txt index 533079cb39..48db2ad32b 100644 --- a/apps/examples/du/CMakeLists.txt +++ b/apps/examples/du/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/apps/examples/du/du_example.cpp b/apps/examples/du/du_example.cpp index fa057473b1..5d7b13e6f5 100644 --- a/apps/examples/du/du_example.cpp +++ b/apps/examples/du/du_example.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/apps/examples/du/fapi_factory.cpp b/apps/examples/du/fapi_factory.cpp index a636e8bdc5..9d7421102f 100644 --- a/apps/examples/du/fapi_factory.cpp +++ b/apps/examples/du/fapi_factory.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/apps/examples/du/fapi_factory.h b/apps/examples/du/fapi_factory.h index 4938ebd03c..b205934fd3 100644 --- a/apps/examples/du/fapi_factory.h +++ b/apps/examples/du/fapi_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/apps/examples/du/phy_factory.cpp b/apps/examples/du/phy_factory.cpp index 3581dfda02..83033bbf0f 100644 --- a/apps/examples/du/phy_factory.cpp +++ b/apps/examples/du/phy_factory.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/apps/examples/du/phy_factory.h b/apps/examples/du/phy_factory.h index 24bbc8d1aa..b590341087 100644 --- a/apps/examples/du/phy_factory.h +++ b/apps/examples/du/phy_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/apps/examples/du/radio_notifier_sample.h b/apps/examples/du/radio_notifier_sample.h index 3c9d443160..e9f408d3bc 100644 --- a/apps/examples/du/radio_notifier_sample.h +++ b/apps/examples/du/radio_notifier_sample.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/apps/examples/phy/CMakeLists.txt b/apps/examples/phy/CMakeLists.txt index 55b53e21fd..c6bbd666c2 100644 --- a/apps/examples/phy/CMakeLists.txt +++ b/apps/examples/phy/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/apps/examples/phy/lower_phy_example_factory.cpp b/apps/examples/phy/lower_phy_example_factory.cpp index 148b7003d7..f1c4ec3e2d 100644 --- a/apps/examples/phy/lower_phy_example_factory.cpp +++ b/apps/examples/phy/lower_phy_example_factory.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/apps/examples/phy/lower_phy_example_factory.h b/apps/examples/phy/lower_phy_example_factory.h index dab5436552..4ae0897e72 100644 --- a/apps/examples/phy/lower_phy_example_factory.h +++ b/apps/examples/phy/lower_phy_example_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/apps/examples/phy/radio_ssb.cpp b/apps/examples/phy/radio_ssb.cpp index ac2c49a2b9..5ae7544087 100644 --- a/apps/examples/phy/radio_ssb.cpp +++ b/apps/examples/phy/radio_ssb.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/apps/examples/phy/rx_symbol_handler_example.h b/apps/examples/phy/rx_symbol_handler_example.h index cf03b31a45..03cd7dc6f2 100644 --- a/apps/examples/phy/rx_symbol_handler_example.h +++ b/apps/examples/phy/rx_symbol_handler_example.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/apps/examples/phy/upper_phy_ssb_example.cpp b/apps/examples/phy/upper_phy_ssb_example.cpp index 10b14baac1..f5ab354964 100644 --- a/apps/examples/phy/upper_phy_ssb_example.cpp +++ b/apps/examples/phy/upper_phy_ssb_example.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/apps/examples/phy/upper_phy_ssb_example.h b/apps/examples/phy/upper_phy_ssb_example.h index fa7215beff..d50325b7c9 100644 --- a/apps/examples/phy/upper_phy_ssb_example.h +++ b/apps/examples/phy/upper_phy_ssb_example.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/apps/examples/radio/CMakeLists.txt b/apps/examples/radio/CMakeLists.txt index 831b814d57..638b0fef0c 100644 --- a/apps/examples/radio/CMakeLists.txt +++ b/apps/examples/radio/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/apps/examples/radio/radio_notifier_sample.h b/apps/examples/radio/radio_notifier_sample.h index 16f96422f7..83660f4282 100644 --- a/apps/examples/radio/radio_notifier_sample.h +++ b/apps/examples/radio/radio_notifier_sample.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/apps/examples/radio/radio_util_sample.cpp b/apps/examples/radio/radio_util_sample.cpp index ff30d73c61..d1ca041704 100644 --- a/apps/examples/radio/radio_util_sample.cpp +++ b/apps/examples/radio/radio_util_sample.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/apps/gnb/CMakeLists.txt b/apps/gnb/CMakeLists.txt index 9124f96495..89a719e949 100644 --- a/apps/gnb/CMakeLists.txt +++ b/apps/gnb/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/apps/gnb/adapters/e1ap_gateway_local_connector.cpp b/apps/gnb/adapters/e1ap_gateway_local_connector.cpp index e81f7215d8..f45ebcc06c 100644 --- a/apps/gnb/adapters/e1ap_gateway_local_connector.cpp +++ b/apps/gnb/adapters/e1ap_gateway_local_connector.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/apps/gnb/adapters/e1ap_gateway_local_connector.h b/apps/gnb/adapters/e1ap_gateway_local_connector.h index f757d66aba..f69ae1f5fd 100644 --- a/apps/gnb/adapters/e1ap_gateway_local_connector.h +++ b/apps/gnb/adapters/e1ap_gateway_local_connector.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/apps/gnb/adapters/e2_gateway_remote_connector.cpp b/apps/gnb/adapters/e2_gateway_remote_connector.cpp index cfa5604664..a65e567ec1 100644 --- a/apps/gnb/adapters/e2_gateway_remote_connector.cpp +++ b/apps/gnb/adapters/e2_gateway_remote_connector.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/apps/gnb/adapters/e2_gateway_remote_connector.h b/apps/gnb/adapters/e2_gateway_remote_connector.h index 27e066e217..06708f1e63 100644 --- a/apps/gnb/adapters/e2_gateway_remote_connector.h +++ b/apps/gnb/adapters/e2_gateway_remote_connector.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/apps/gnb/adapters/e2ap_adapter.h b/apps/gnb/adapters/e2ap_adapter.h index aa2050a6da..570eb28ef4 100644 --- a/apps/gnb/adapters/e2ap_adapter.h +++ b/apps/gnb/adapters/e2ap_adapter.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/apps/gnb/adapters/f1c_gateway_local_connector.cpp b/apps/gnb/adapters/f1c_gateway_local_connector.cpp index ce680cf178..7733763ec8 100644 --- a/apps/gnb/adapters/f1c_gateway_local_connector.cpp +++ b/apps/gnb/adapters/f1c_gateway_local_connector.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/apps/gnb/adapters/f1c_gateway_local_connector.h b/apps/gnb/adapters/f1c_gateway_local_connector.h index 3e21cda730..04441765a9 100644 --- a/apps/gnb/adapters/f1c_gateway_local_connector.h +++ b/apps/gnb/adapters/f1c_gateway_local_connector.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/apps/gnb/adapters/ngap_adapter.h b/apps/gnb/adapters/ngap_adapter.h index 3fadd827b6..fd0fdba415 100644 --- a/apps/gnb/adapters/ngap_adapter.h +++ b/apps/gnb/adapters/ngap_adapter.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/apps/gnb/gnb.cpp b/apps/gnb/gnb.cpp index a2ad69709f..579edd2f14 100644 --- a/apps/gnb/gnb.cpp +++ b/apps/gnb/gnb.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/apps/gnb/gnb_appconfig.h b/apps/gnb/gnb_appconfig.h index 91496e6a5d..11a60ef7cd 100644 --- a/apps/gnb/gnb_appconfig.h +++ b/apps/gnb/gnb_appconfig.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/apps/gnb/gnb_appconfig_cli11_schema.cpp b/apps/gnb/gnb_appconfig_cli11_schema.cpp index 7ceb7ba3e5..2e2e0ca1e8 100644 --- a/apps/gnb/gnb_appconfig_cli11_schema.cpp +++ b/apps/gnb/gnb_appconfig_cli11_schema.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/apps/gnb/gnb_appconfig_cli11_schema.h b/apps/gnb/gnb_appconfig_cli11_schema.h index 4b64faa234..35a35c7e60 100644 --- a/apps/gnb/gnb_appconfig_cli11_schema.h +++ b/apps/gnb/gnb_appconfig_cli11_schema.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/apps/gnb/gnb_appconfig_translators.cpp b/apps/gnb/gnb_appconfig_translators.cpp index 5dfe0bf25a..d087b9f3ed 100644 --- a/apps/gnb/gnb_appconfig_translators.cpp +++ b/apps/gnb/gnb_appconfig_translators.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/apps/gnb/gnb_appconfig_translators.h b/apps/gnb/gnb_appconfig_translators.h index 0b9e647ec6..112b762a45 100644 --- a/apps/gnb/gnb_appconfig_translators.h +++ b/apps/gnb/gnb_appconfig_translators.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/apps/gnb/gnb_appconfig_validators.cpp b/apps/gnb/gnb_appconfig_validators.cpp index 0ef51e1b07..ee211777b0 100644 --- a/apps/gnb/gnb_appconfig_validators.cpp +++ b/apps/gnb/gnb_appconfig_validators.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/apps/gnb/gnb_appconfig_validators.h b/apps/gnb/gnb_appconfig_validators.h index b64216d7b7..b8fa7a704d 100644 --- a/apps/gnb/gnb_appconfig_validators.h +++ b/apps/gnb/gnb_appconfig_validators.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/apps/gnb/gnb_du_factory.cpp b/apps/gnb/gnb_du_factory.cpp index de741dc2d6..9a3f800797 100644 --- a/apps/gnb/gnb_du_factory.cpp +++ b/apps/gnb/gnb_du_factory.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/apps/gnb/gnb_du_factory.h b/apps/gnb/gnb_du_factory.h index 626ca00cc4..9e6701a0e2 100644 --- a/apps/gnb/gnb_du_factory.h +++ b/apps/gnb/gnb_du_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/apps/gnb/gnb_e2_metric_connector_manager.cpp b/apps/gnb/gnb_e2_metric_connector_manager.cpp index 14eeb28824..9a493a0945 100644 --- a/apps/gnb/gnb_e2_metric_connector_manager.cpp +++ b/apps/gnb/gnb_e2_metric_connector_manager.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/apps/gnb/gnb_e2_metric_connector_manager.h b/apps/gnb/gnb_e2_metric_connector_manager.h index b6f3f7c26d..cbf4a584a3 100644 --- a/apps/gnb/gnb_e2_metric_connector_manager.h +++ b/apps/gnb/gnb_e2_metric_connector_manager.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/apps/gnb/gnb_os_sched_affinity_manager.h b/apps/gnb/gnb_os_sched_affinity_manager.h index b004cf9af3..aed19ce19e 100644 --- a/apps/gnb/gnb_os_sched_affinity_manager.h +++ b/apps/gnb/gnb_os_sched_affinity_manager.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/apps/gnb/gnb_worker_manager.cpp b/apps/gnb/gnb_worker_manager.cpp index 3d2dee4347..dca933f9f5 100644 --- a/apps/gnb/gnb_worker_manager.cpp +++ b/apps/gnb/gnb_worker_manager.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/apps/gnb/gnb_worker_manager.h b/apps/gnb/gnb_worker_manager.h index e5cc496b01..b81533e519 100644 --- a/apps/gnb/gnb_worker_manager.h +++ b/apps/gnb/gnb_worker_manager.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/apps/gnb/helpers/gnb_console_helper.cpp b/apps/gnb/helpers/gnb_console_helper.cpp index ff8af94ff4..26ce7749b8 100644 --- a/apps/gnb/helpers/gnb_console_helper.cpp +++ b/apps/gnb/helpers/gnb_console_helper.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/apps/gnb/helpers/gnb_console_helper.h b/apps/gnb/helpers/gnb_console_helper.h index 8ab8f5a259..a2d207f1f5 100644 --- a/apps/gnb/helpers/gnb_console_helper.h +++ b/apps/gnb/helpers/gnb_console_helper.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/apps/gnb/helpers/metrics_hub.cpp b/apps/gnb/helpers/metrics_hub.cpp index 925cc0e4f6..97609fdaf4 100644 --- a/apps/gnb/helpers/metrics_hub.cpp +++ b/apps/gnb/helpers/metrics_hub.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/apps/gnb/helpers/metrics_hub.h b/apps/gnb/helpers/metrics_hub.h index 9efebb48a7..31c9be592d 100644 --- a/apps/gnb/helpers/metrics_hub.h +++ b/apps/gnb/helpers/metrics_hub.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/apps/gnb/helpers/metrics_plotter_json.cpp b/apps/gnb/helpers/metrics_plotter_json.cpp index 4ad01c9cfd..c907630de3 100644 --- a/apps/gnb/helpers/metrics_plotter_json.cpp +++ b/apps/gnb/helpers/metrics_plotter_json.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/apps/gnb/helpers/metrics_plotter_json.h b/apps/gnb/helpers/metrics_plotter_json.h index f0fb4d305b..a2e05561bc 100644 --- a/apps/gnb/helpers/metrics_plotter_json.h +++ b/apps/gnb/helpers/metrics_plotter_json.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/apps/gnb/helpers/metrics_plotter_stdout.cpp b/apps/gnb/helpers/metrics_plotter_stdout.cpp index 73b982e713..1649101e93 100644 --- a/apps/gnb/helpers/metrics_plotter_stdout.cpp +++ b/apps/gnb/helpers/metrics_plotter_stdout.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/apps/gnb/helpers/metrics_plotter_stdout.h b/apps/gnb/helpers/metrics_plotter_stdout.h index a3a603aeba..f6ee37b4df 100644 --- a/apps/gnb/helpers/metrics_plotter_stdout.h +++ b/apps/gnb/helpers/metrics_plotter_stdout.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/apps/gnb/helpers/rlc_metrics_plotter_json.cpp b/apps/gnb/helpers/rlc_metrics_plotter_json.cpp index 2b7b20fce0..c2de41c81c 100644 --- a/apps/gnb/helpers/rlc_metrics_plotter_json.cpp +++ b/apps/gnb/helpers/rlc_metrics_plotter_json.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/apps/gnb/helpers/rlc_metrics_plotter_json.h b/apps/gnb/helpers/rlc_metrics_plotter_json.h index 4a4a64bd58..249f3b5eed 100644 --- a/apps/gnb/helpers/rlc_metrics_plotter_json.h +++ b/apps/gnb/helpers/rlc_metrics_plotter_json.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/apps/gnb/helpers/string_helpers.h b/apps/gnb/helpers/string_helpers.h index ef1477c8db..2fb4d2bd57 100644 --- a/apps/gnb/helpers/string_helpers.h +++ b/apps/gnb/helpers/string_helpers.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/apps/gnb/radio_notifier_sample.h b/apps/gnb/radio_notifier_sample.h index a7b8f5658a..0c6224a08b 100644 --- a/apps/gnb/radio_notifier_sample.h +++ b/apps/gnb/radio_notifier_sample.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/cmake/modules/FindDPDK.cmake b/cmake/modules/FindDPDK.cmake index 58e4b2ec96..4298f2b99c 100644 --- a/cmake/modules/FindDPDK.cmake +++ b/cmake/modules/FindDPDK.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/cmake/modules/FindFFTW3F.cmake b/cmake/modules/FindFFTW3F.cmake index f106bf3813..85f8736add 100644 --- a/cmake/modules/FindFFTW3F.cmake +++ b/cmake/modules/FindFFTW3F.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/cmake/modules/FindMbedTLS.cmake b/cmake/modules/FindMbedTLS.cmake index 0d7c7f543b..e6862f4051 100644 --- a/cmake/modules/FindMbedTLS.cmake +++ b/cmake/modules/FindMbedTLS.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/cmake/modules/FindSCTP.cmake b/cmake/modules/FindSCTP.cmake index db8e763935..73d9999c84 100644 --- a/cmake/modules/FindSCTP.cmake +++ b/cmake/modules/FindSCTP.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/cmake/modules/FindSSE.cmake b/cmake/modules/FindSSE.cmake index af8df95f49..771114a253 100644 --- a/cmake/modules/FindSSE.cmake +++ b/cmake/modules/FindSSE.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/cmake/modules/FindTRX_DRIVER.cmake b/cmake/modules/FindTRX_DRIVER.cmake index 17358ed96e..a3d61e58fa 100644 --- a/cmake/modules/FindTRX_DRIVER.cmake +++ b/cmake/modules/FindTRX_DRIVER.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/cmake/modules/FindUHD.cmake b/cmake/modules/FindUHD.cmake index 2ca86630b0..4ec9e4025d 100644 --- a/cmake/modules/FindUHD.cmake +++ b/cmake/modules/FindUHD.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/cmake/modules/FindYAMLCPP.cmake b/cmake/modules/FindYAMLCPP.cmake index 3cedcff28e..2b6a72b11c 100644 --- a/cmake/modules/FindYAMLCPP.cmake +++ b/cmake/modules/FindYAMLCPP.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/cmake/modules/FindZeroMQ.cmake b/cmake/modules/FindZeroMQ.cmake index 2de48f22a9..c4659f7d56 100644 --- a/cmake/modules/FindZeroMQ.cmake +++ b/cmake/modules/FindZeroMQ.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/cmake/modules/version.cmake b/cmake/modules/version.cmake index dbedcdec76..1194e2cbb4 100644 --- a/cmake/modules/version.cmake +++ b/cmake/modules/version.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/configs/CMakeLists.txt b/configs/CMakeLists.txt index 0b474722dd..e2671ec64a 100644 --- a/configs/CMakeLists.txt +++ b/configs/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/docker/Dockerfile b/docker/Dockerfile index 696a6ee3f1..f7ffb0befd 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -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/docker/docker-compose.yml b/docker/docker-compose.yml index ed15a13e2c..df9e91e95b 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.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/docker/metrics_server/Dockerfile b/docker/metrics_server/Dockerfile index 4d19e61154..c7f25bf9d3 100644 --- a/docker/metrics_server/Dockerfile +++ b/docker/metrics_server/Dockerfile @@ -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/docker/metrics_server/pyproject.toml b/docker/metrics_server/pyproject.toml index 07cd0f4deb..6794911493 100644 --- a/docker/metrics_server/pyproject.toml +++ b/docker/metrics_server/pyproject.toml @@ -23,7 +23,7 @@ description = "srsRAN Metrics Server" name = "srs_metrics_server" readme = "README.md" requires-python = ">=3.7" -version = "1.5.0" +version = "1.5.1" [project.scripts] metrics-server = "metrics_server.__main__:main" diff --git a/docker/open5gs/Dockerfile b/docker/open5gs/Dockerfile index a4c710d980..720466919f 100644 --- a/docker/open5gs/Dockerfile +++ b/docker/open5gs/Dockerfile @@ -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/docs/CMakeLists.txt b/docs/CMakeLists.txt index c26724bcbb..845875f757 100644 --- a/docs/CMakeLists.txt +++ b/docs/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/docs/acronyms.dox b/docs/acronyms.dox index f259d764c5..bfc182d3c4 100644 --- a/docs/acronyms.dox +++ b/docs/acronyms.dox @@ -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/docs/fail.html b/docs/fail.html index fbea944770..6ef9cc3a8b 100644 --- a/docs/fail.html +++ b/docs/fail.html @@ -1,5 +1,5 @@