diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 57b0a83cf6..44f2f840d5 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -6,8 +6,6 @@ on: pull_request: # The branches below must be a subset of the branches above branches: [ "main" ] - schedule: - - cron: '38 10 * * 2' jobs: analyze: diff --git a/.gitlab/ci/e2e.yml b/.gitlab/ci/e2e.yml index bea8bde808..5a8d0c5eb1 100644 --- a/.gitlab/ci/e2e.yml +++ b/.gitlab/ci/e2e.yml @@ -280,18 +280,21 @@ rf: variables: KEYWORDS: "not iperf" E2E_LOG_LEVEL: "info" + allow_failure: true rf-iperf-udp: extends: .rf variables: KEYWORDS: "iperf and udp" E2E_LOG_LEVEL: "info" + allow_failure: true rf-iperf-tcp: extends: .rf variables: KEYWORDS: "iperf and tcp" E2E_LOG_LEVEL: "info" + allow_failure: true rf-tsan: extends: .rf @@ -301,6 +304,7 @@ rf-tsan: - job: "smoke tsan update cache" artifacts: true - *retina-needs + retry: 2 rf-asan: extends: .rf diff --git a/CHANGELOG b/CHANGELOG index 0246ff61ec..4ebca2e22c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,15 @@ Change Log for Releases ======================= +## 23.10 + * Added downlink MIMO (up to 4 layers) + * Added Open Fronthaul (OFH) interface for split 7.2 ORAN radio units (optionally using DPDK) + * Added E2 interface including KPM and RAN control (RC) service model + * Added Timing Advance support + * Added Docker files + * Expose many more config parameters + * Other bug-fixes and improved stability and performance in all parts + ## 23.5 * Updated ASN.1 of RRC/NGAP/F1AP/E1AP to 3GPP Release 17.4 * Add UE capability transfer procedure diff --git a/apps/gnb/gnb.cpp b/apps/gnb/gnb.cpp index 955b1cb476..d29d0fb8a9 100644 --- a/apps/gnb/gnb.cpp +++ b/apps/gnb/gnb.cpp @@ -561,6 +561,9 @@ int main(int argc, char** argv) // Stop CU-UP activity. cu_up_obj->stop(); + // Stop CU-CP activity. + cu_cp_obj->stop(); + if (not gnb_cfg.amf_cfg.no_core) { gnb_logger.info("Closing network connections..."); ngap_adapter->disconnect_gateway(); diff --git a/apps/gnb/gnb_appconfig.h b/apps/gnb/gnb_appconfig.h index 2c85c849ce..b538369dcb 100644 --- a/apps/gnb/gnb_appconfig.h +++ b/apps/gnb/gnb_appconfig.h @@ -496,7 +496,7 @@ struct cell_appconfig { /// RLC UM TX configuration struct rlc_tx_um_appconfig { uint16_t sn_field_length; ///< Number of bits used for sequence number - int32_t t_reassembly; ///< Timer used by rx to detect PDU loss (ms) + uint32_t queue_size; ///< RLC SDU queue size }; /// RLC UM RX configuration @@ -519,6 +519,7 @@ struct rlc_tx_am_appconfig { int32_t poll_pdu; ///< Insert poll bit after this many PDUs int32_t poll_byte; ///< Insert poll bit after this much data (bytes) uint32_t max_window = 0; ///< Custom parameter to limit the maximum window size for memory reasons. 0 means no limit. + uint32_t queue_size = 4096; ///< RLC SDU queue size }; /// RLC UM RX configuration @@ -668,6 +669,10 @@ struct cu_cp_appconfig { security_appconfig security_config; }; +struct cu_up_appconfig { + unsigned gtpu_queue_size = 2048; +}; + struct log_appconfig { std::string filename = "/tmp/gnb.log"; // Path to write log file or "stdout" to print to console. std::string all_level = "warning"; // Default log level for all layers. @@ -753,7 +758,7 @@ struct expert_upper_phy_appconfig { /// Higher values increase the downlink processing pipeline length, which improves performance and stability for /// demanding cell configurations, such as using large bandwidths or higher order MIMO. Higher values also increase /// the round trip latency of the radio link. - unsigned max_processing_delay_slots = 2U; + unsigned max_processing_delay_slots = 5U; /// Number of PUSCH LDPC decoder iterations. unsigned pusch_decoder_max_iterations = 6; /// Set to true to enable the PUSCH LDPC decoder early stop. @@ -899,6 +904,8 @@ struct ru_ofh_cell_appconfig { ru_ofh_base_cell_appconfig cell; /// Ethernet network interface name. std::string network_interface = "enp1s0f0"; + /// Promiscuous mode flag. + bool enable_promiscuous_mode = true; /// Radio Unit MAC address. std::string ru_mac_address = "70:b3:d5:e1:5b:06"; /// Distributed Unit MAC address. @@ -974,15 +981,6 @@ struct upper_phy_threads_appconfig { /// Lower PHY thread configuration fo the gNB. struct lower_phy_threads_appconfig { - lower_phy_threads_appconfig() - { - // Set the lower PHY thread profile according to the number of CPU cores. - if (srsran::compute_host_nof_hardware_threads() >= 8U) { - execution_profile = lower_phy_thread_profile::quad; - } else { - execution_profile = lower_phy_thread_profile::dual; - } - } /// \brief Lower physical layer thread profile. /// /// If not configured, a default value is selected based on the number of available CPU cores. @@ -996,6 +994,41 @@ struct ofh_threads_appconfig { /// Expert threads configuration of the gNB app. struct expert_threads_appconfig { + expert_threads_appconfig() + { + unsigned nof_threads = compute_host_nof_hardware_threads(); + + 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; + 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; + 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; + 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; + lower_threads.execution_profile = lower_phy_thread_profile::quad; + ofh_threads.is_downlink_parallelized = true; + } + } + /// Upper PHY thread configuration of the gNB app. upper_phy_threads_appconfig upper_threads; /// Lower PHY thread configuration of the gNB app. @@ -1036,6 +1069,8 @@ struct gnb_appconfig { amf_appconfig amf_cfg; /// CU-CP configuration. cu_cp_appconfig cu_cp_cfg; + /// CU-CP configuration. + cu_up_appconfig cu_up_cfg; /// \brief E2 configuration. e2_appconfig e2_cfg; /// Radio Unit configuration. diff --git a/apps/gnb/gnb_appconfig_cli11_schema.cpp b/apps/gnb/gnb_appconfig_cli11_schema.cpp index c4b14af1c9..206f8e6c30 100644 --- a/apps/gnb/gnb_appconfig_cli11_schema.cpp +++ b/apps/gnb/gnb_appconfig_cli11_schema.cpp @@ -22,6 +22,7 @@ #include "gnb_appconfig_cli11_schema.h" #include "gnb_appconfig.h" +#include "srsran/ran/duplex_mode.h" #include "srsran/ran/pdsch/pdsch_mcs.h" #include "srsran/support/cli11_utils.h" #include "srsran/support/config_parsers.h" @@ -388,6 +389,11 @@ static void configure_cli11_cu_cp_args(CLI::App& app, cu_cp_appconfig& cu_cp_par configure_cli11_security_args(*security_subcmd, cu_cp_params.security_config); } +static void configure_cli11_cu_up_args(CLI::App& app, cu_up_appconfig& cu_up_params) +{ + app.add_option("--gtpu_queue_size", cu_up_params.gtpu_queue_size, "GTP-U queue size, in PDUs")->capture_default_str(); +} + static void configure_cli11_expert_phy_args(CLI::App& app, expert_upper_phy_appconfig& expert_phy_params) { auto pusch_sinr_method_check = [](const std::string& value) -> std::string { @@ -1288,6 +1294,8 @@ static void configure_cli11_rlc_um_args(CLI::App& app, rlc_um_appconfig& rlc_um_ { CLI::App* rlc_tx_um_subcmd = app.add_subcommand("tx", "UM TX parameters"); rlc_tx_um_subcmd->add_option("--sn", rlc_um_params.tx.sn_field_length, "RLC UM TX SN")->capture_default_str(); + rlc_tx_um_subcmd->add_option("--queue-size", rlc_um_params.tx.queue_size, "RLC UM TX SDU queue size") + ->capture_default_str(); CLI::App* rlc_rx_um_subcmd = app.add_subcommand("rx", "UM TX parameters"); rlc_rx_um_subcmd->add_option("--sn", rlc_um_params.rx.sn_field_length, "RLC UM RX SN")->capture_default_str(); rlc_rx_um_subcmd->add_option("--t-reassembly", rlc_um_params.rx.t_reassembly, "RLC UM t-Reassembly") @@ -1304,11 +1312,12 @@ static void configure_cli11_rlc_am_args(CLI::App& app, rlc_am_appconfig& rlc_am_ ->capture_default_str(); rlc_tx_am_subcmd->add_option("--poll-pdu", rlc_am_params.tx.poll_pdu, "RLC AM TX PollPdu")->capture_default_str(); rlc_tx_am_subcmd->add_option("--poll-byte", rlc_am_params.tx.poll_byte, "RLC AM TX PollByte")->capture_default_str(); - rlc_tx_am_subcmd - ->add_option("--max_window", - rlc_am_params.tx.max_window, - "Non-standard parameter that limits the tx window size. Can be used for limiting memory usage with " - "large windows. 0 means no limits other than the SN size (i.e. 2^[sn_size-1]).") + rlc_tx_am_subcmd->add_option( + "--max_window", + rlc_am_params.tx.max_window, + "Non-standard parameter that limits the tx window size. Can be used for limiting memory usage with " + "large windows. 0 means no limits other than the SN size (i.e. 2^[sn_size-1])."); + rlc_tx_am_subcmd->add_option("--queue-size", rlc_am_params.tx.queue_size, "RLC AM TX SDU queue size") ->capture_default_str(); CLI::App* rlc_rx_am_subcmd = app.add_subcommand("rx", "AM RX parameters"); rlc_rx_am_subcmd->add_option("--sn", rlc_am_params.rx.sn_field_length, "RLC AM RX SN")->capture_default_str(); @@ -1656,6 +1665,8 @@ static void configure_cli11_ru_ofh_cells_args(CLI::App& app, ru_ofh_cell_appconf { configure_cli11_ru_ofh_base_cell_args(app, config.cell); app.add_option("--network_interface", config.network_interface, "Network interface")->capture_default_str(); + app.add_option("--enable_promiscuous", config.enable_promiscuous_mode, "Promiscuous mode flag") + ->capture_default_str(); app.add_option("--ru_mac_addr", config.ru_mac_address, "Radio Unit MAC address")->capture_default_str(); app.add_option("--du_mac_addr", config.du_mac_address, "Distributed Unit MAC address")->capture_default_str(); app.add_option("--vlan_tag", config.vlan_tag, "V-LAN identifier")->capture_default_str()->check(CLI::Range(1, 4094)); @@ -1986,6 +1997,47 @@ static void manage_hal_optional(CLI::App& app, gnb_appconfig& gnb_cfg) } } +static void manage_expert_execution_threads(CLI::App& app, gnb_appconfig& gnb_cfg) +{ + 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_phy_threads_appconfig& upper = gnb_cfg.expert_execution_cfg.threads.upper_threads; + upper.nof_pdsch_threads = 1; + 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; + } +} + +static void manage_processing_delay(CLI::App& app, gnb_appconfig& gnb_cfg) +{ + // If max proc delay property is present in the config, do nothing. + CLI::App* expert_cmd = app.get_subcommand("expert_phy"); + if (expert_cmd->count_all() >= 1 && expert_cmd->count("--max_proc_delay") >= 1) { + return; + } + + // As processing delay is not cell related, use the first cell to update the value. + const auto& cell = gnb_cfg.cells_cfg.front().cell; + nr_band band = cell.band ? cell.band.value() : band_helper::get_band_from_dl_arfcn(cell.dl_arfcn); + + switch (band_helper::get_duplex_mode(band)) { + case duplex_mode::TDD: + gnb_cfg.expert_phy_cfg.max_processing_delay_slots = 5; + break; + case duplex_mode::FDD: + gnb_cfg.expert_phy_cfg.max_processing_delay_slots = 2; + break; + default: + break; + } +} + void srsran::configure_cli11_with_gnb_appconfig_schema(CLI::App& app, gnb_appconfig& gnb_cfg) { app.add_option("--gnb_id", gnb_cfg.gnb_id, "gNodeB identifier")->capture_default_str(); @@ -2018,6 +2070,10 @@ void srsran::configure_cli11_with_gnb_appconfig_schema(CLI::App& app, gnb_appcon CLI::App* cu_cp_subcmd = app.add_subcommand("cu_cp", "CU-CP parameters")->configurable(); configure_cli11_cu_cp_args(*cu_cp_subcmd, gnb_cfg.cu_cp_cfg); + // CU-UP section + CLI::App* cu_up_subcmd = app.add_subcommand("cu_up", "CU-CP parameters")->configurable(); + configure_cli11_cu_up_args(*cu_up_subcmd, gnb_cfg.cu_up_cfg); + // NOTE: CLI11 needs that the life of the variable lasts longer than the call of this function. As both options need // to be added and a variant is used to store the Radio Unit configuration, the configuration is parsed in a helper // variable, but as it is requested later, the variable needs to be static. @@ -2121,5 +2177,7 @@ void srsran::configure_cli11_with_gnb_appconfig_schema(CLI::App& app, gnb_appcon app.callback([&]() { manage_ru_variant(app, gnb_cfg, sdr_cfg, ofh_cfg); manage_hal_optional(app, gnb_cfg); + manage_expert_execution_threads(app, gnb_cfg); + manage_processing_delay(app, gnb_cfg); }); } diff --git a/apps/gnb/gnb_appconfig_translators.cpp b/apps/gnb/gnb_appconfig_translators.cpp index 06c27f6514..afe9335cc6 100644 --- a/apps/gnb/gnb_appconfig_translators.cpp +++ b/apps/gnb/gnb_appconfig_translators.cpp @@ -877,6 +877,7 @@ std::map srsran::generate_du_qos_config(const gnb_appc if (!from_number(out_rlc.um.tx.sn_field_length, qos.rlc.um.tx.sn_field_length)) { report_error("Invalid RLC UM TX SN: 5QI={}, SN={}\n", qos.five_qi, qos.rlc.um.tx.sn_field_length); } + out_rlc.um.tx.queue_size = qos.rlc.um.tx.queue_size; } else if (out_rlc.mode == rlc_mode::am) { // AM Config //< TX SN @@ -888,6 +889,7 @@ std::map srsran::generate_du_qos_config(const gnb_appc out_rlc.am.tx.poll_pdu = qos.rlc.am.tx.poll_pdu; out_rlc.am.tx.poll_byte = qos.rlc.am.tx.poll_byte; out_rlc.am.tx.max_window = qos.rlc.am.tx.max_window; + out_rlc.am.tx.queue_size = qos.rlc.am.tx.queue_size; //< RX SN if (!from_number(out_rlc.am.rx.sn_field_length, qos.rlc.am.rx.sn_field_length)) { report_error("Invalid RLC AM RX SN: 5QI={}, SN={}\n", qos.five_qi, qos.rlc.am.rx.sn_field_length); @@ -1169,7 +1171,8 @@ generate_ru_ofh_config(ru_ofh_configuration& out_cfg, const gnb_appconfig& confi out_cfg.sector_configs.emplace_back(); ru_ofh_sector_configuration& sector_cfg = out_cfg.sector_configs.back(); - sector_cfg.interface = cell_cfg.network_interface; + sector_cfg.interface = cell_cfg.network_interface; + sector_cfg.is_promiscuous_mode_enabled = cell_cfg.enable_promiscuous_mode; if (!parse_mac_address(cell_cfg.du_mac_address, sector_cfg.mac_src_address)) { srsran_terminate("Invalid Distributed Unit MAC address"); } @@ -1284,6 +1287,14 @@ std::vector srsran::generate_du_low_config(const gnb_appconfig // Maximum number of HARQ processes for a PUSCH HARQ process. static constexpr unsigned max_nof_pusch_harq = 16; + // Maximum concurrent PUSCH processing. If there are no dedicated threads for PUSCH decoding, set the maximum + // concurrency to one. Otherwise, assume every possible PUSCH transmission for the maximum number of HARQ could be + // enqueued. + unsigned max_pusch_concurrency = config.common_cell_cfg.pusch_cfg.max_puschs_per_slot * max_nof_pusch_harq; + if (config.expert_execution_cfg.threads.upper_threads.nof_pusch_decoder_threads == 0) { + max_pusch_concurrency = 1; + } + cfg.log_level = srslog::str_to_basic_level(config.log_cfg.phy_level); cfg.enable_logging_broadcast = config.log_cfg.broadcast_enabled; cfg.rx_symbol_printer_filename = config.log_cfg.phy_rx_symbols_filename; @@ -1298,7 +1309,7 @@ std::vector srsran::generate_du_low_config(const gnb_appconfig cfg.nof_slots_ul_rg = ul_pipeline_depth; cfg.nof_ul_processors = ul_pipeline_depth; cfg.max_ul_thread_concurrency = config.expert_execution_cfg.threads.upper_threads.nof_ul_threads + 1; - cfg.max_pusch_concurrency = MAX_UE_PDUS_PER_SLOT * max_nof_pusch_harq; + cfg.max_pusch_concurrency = max_pusch_concurrency; cfg.nof_pusch_decoder_threads = config.expert_execution_cfg.threads.upper_threads.nof_pusch_decoder_threads + config.expert_execution_cfg.threads.upper_threads.nof_ul_threads; cfg.nof_prach_buffer = prach_pipeline_depth * nof_slots_per_subframe; @@ -1446,18 +1457,13 @@ static void derive_cell_auto_params(base_cell_appconfig& cell_cfg) cell_cfg.tdd_ul_dl_cfg->pattern1.nof_ul_symbols = 0; } - // If PRACH configuration Index not set, derive a valid one. + // If PRACH configuration Index not set, a default one is assigned. if (not cell_cfg.prach_cfg.prach_config_index.has_value()) { if (band_helper::get_duplex_mode(cell_cfg.band.value()) == duplex_mode::FDD) { - cell_cfg.prach_cfg.prach_config_index = 1; + cell_cfg.prach_cfg.prach_config_index = 16; } else { - // TDD case. Ensure the PRACH falls in UL slots. - optional index_found = prach_helper::find_valid_prach_config_index( - cell_cfg.common_scs, generate_tdd_pattern(cell_cfg.common_scs, cell_cfg.tdd_ul_dl_cfg.value())); - if (not index_found.has_value()) { - report_error("Failed to auto-derive PRACH configuration index"); - } - cell_cfg.prach_cfg.prach_config_index = *index_found; + // Valid for TDD period of 5 ms. And, PRACH index 159 is well tested. + cell_cfg.prach_cfg.prach_config_index = 159; } } } diff --git a/apps/gnb/gnb_appconfig_validators.cpp b/apps/gnb/gnb_appconfig_validators.cpp index af31cb0fd7..cb7130afed 100644 --- a/apps/gnb/gnb_appconfig_validators.cpp +++ b/apps/gnb/gnb_appconfig_validators.cpp @@ -218,7 +218,7 @@ static bool validate_pucch_cell_app_config(const base_cell_appconfig& config) /// 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) { - srsran_assert(config.prach_config_index.has_value(), "The PRACH configuration index must be set or auto-derived."); + srsran_assert(config.prach_config_index.has_value(), "The PRACH configuration index must be set."); auto code = prach_helper::prach_config_index_is_valid(config.prach_config_index.value(), band_helper::get_duplex_mode(band)); diff --git a/apps/gnb/gnb_worker_manager.cpp b/apps/gnb/gnb_worker_manager.cpp index d2cd4950b5..8ba68f3dba 100644 --- a/apps/gnb/gnb_worker_manager.cpp +++ b/apps/gnb/gnb_worker_manager.cpp @@ -134,7 +134,7 @@ void worker_manager::create_du_cu_executors(const gnb_appconfig& appcfg) {{concurrent_queue_policy::lockfree_mpmc, task_worker_queue_size}, {concurrent_queue_policy::lockfree_mpmc, task_worker_queue_size}, // The IO-broker is currently single threaded, so we can use a SPSC. - {concurrent_queue_policy::lockfree_spsc, task_worker_queue_size}}, + {concurrent_queue_policy::lockfree_spsc, appcfg.cu_up_cfg.gtpu_queue_size}}, std::chrono::microseconds{200}, {{"ue_up_ctrl_exec", task_priority::max}, {"ue_ul_exec", task_priority::max - 1, false}, diff --git a/cmake/modules/version.cmake b/cmake/modules/version.cmake index 28c3f43dc9..f67674e784 100644 --- a/cmake/modules/version.cmake +++ b/cmake/modules/version.cmake @@ -19,6 +19,6 @@ # set(SRSRAN_VERSION_MAJOR 23) -set(SRSRAN_VERSION_MINOR 5) +set(SRSRAN_VERSION_MINOR 10) set(SRSRAN_VERSION_PATCH 0) set(SRSRAN_VERSION_STRING "${SRSRAN_VERSION_MAJOR}.${SRSRAN_VERSION_MINOR}.${SRSRAN_VERSION_PATCH}") \ No newline at end of file diff --git a/configs/gnb_ru_picocom_scb_tdd_n78_20mhz.yml b/configs/gnb_ru_picocom_scb_tdd_n78_20mhz.yml index 1ea45b73b8..a40a8f03b9 100644 --- a/configs/gnb_ru_picocom_scb_tdd_n78_20mhz.yml +++ b/configs/gnb_ru_picocom_scb_tdd_n78_20mhz.yml @@ -20,7 +20,7 @@ ru_ofh: compr_bitwidth_dl: 9 # Downlink IQ samples bitwidth after compression. compr_method_prach: bfp # PRACH compression method. compr_bitwidth_prach: 9 # PRACH IQ samples bitwidth after compression. - iq_scaling: 1.0 # IQ samples scaling factor applied before compression, should be a positive value smaller than 1. + iq_scaling: 1.0 # IQ samples scaling factor applied before compression, should be a positive value smaller than 10. cells: - network_interface: enp1s0f0 # Ethernet interface name used to communicate with the RU. ru_mac_addr: ce:fc:6c:09:a6:cd # RU MAC address. diff --git a/configs/gnb_ru_ran550_tdd_n78_100mhz_2x2.yml b/configs/gnb_ru_ran550_tdd_n78_100mhz_2x2.yml index 4a2fd99d0d..37cd0ca795 100644 --- a/configs/gnb_ru_ran550_tdd_n78_100mhz_2x2.yml +++ b/configs/gnb_ru_ran550_tdd_n78_100mhz_2x2.yml @@ -23,7 +23,7 @@ ru_ofh: compr_bitwidth_prach: 9 # PRACH IQ samples bitwidth after compression. enable_ul_static_compr_hdr: true # Configures if the compression header is present for uplink User-Plane messages (false) or not present (true). enable_dl_static_compr_hdr: true # Configures if the compression header is present for downlink User-Plane messages (false) or not present (true). - iq_scaling: 0.10 # IQ samples scaling factor applied before compression, should be a positive value smaller than 1. + iq_scaling: 5.5 # IQ samples scaling factor applied before compression, should be a positive value smaller than 10. cells: - network_interface: enp1s0f0 # Ethernet interface name used to communicate with the RU. ru_mac_addr: 70:b3:d5:e1:5b:06 # RU MAC address. diff --git a/configs/gnb_ru_ran550_tdd_n78_20mhz.yml b/configs/gnb_ru_ran550_tdd_n78_20mhz.yml index 16dfb8784e..7991292553 100644 --- a/configs/gnb_ru_ran550_tdd_n78_20mhz.yml +++ b/configs/gnb_ru_ran550_tdd_n78_20mhz.yml @@ -24,7 +24,7 @@ ru_ofh: compr_bitwidth_dl: 9 # Downlink IQ samples bitwidth after compression. enable_ul_static_compr_hdr: true # Configures if the compression header is present for uplink User-Plane messages (false) or not present (true). enable_dl_static_compr_hdr: true # Configures if the compression header is present for downlink User-Plane messages (false) or not present (true). - iq_scaling: 0.27 # IQ samples scaling factor applied before compression, should be a positive value smaller than 1. + iq_scaling: 5.5 # IQ samples scaling factor applied before compression, should be a positive value smaller than 10. cells: - network_interface: enp1s0f0 # Ethernet interface name used to communicate with the RU. ru_mac_addr: 70:b3:d5:e1:5b:06 # RU MAC address. diff --git a/configs/gnb_ru_rpqn4800e_tdd_n78_20mhz.yml b/configs/gnb_ru_rpqn4800e_tdd_n78_20mhz.yml index 638ca89b42..c7a69839e7 100644 --- a/configs/gnb_ru_rpqn4800e_tdd_n78_20mhz.yml +++ b/configs/gnb_ru_rpqn4800e_tdd_n78_20mhz.yml @@ -27,7 +27,7 @@ ru_ofh: compr_bitwidth_prach: 9 # PRACH IQ samples bitwidth after compression. enable_ul_static_compr_hdr: false # Configures if the compression header is present for uplink User-Plane messages (false) or not present (true). enable_dl_static_compr_hdr: false # Configures if the compression header is present for downlink User-Plane messages (false) or not present (true). - iq_scaling: 1.0 # IQ samples scaling factor applied before compression, should be a positive value smaller than 1. + iq_scaling: 0.8 # IQ samples scaling factor applied before compression, should be a positive value smaller than 10. cells: - network_interface: enp1s0f1 # Ethernet interface name used to communicate with the RU. ru_mac_addr: 6c:ad:ad:00:08:c4 # RU MAC address. diff --git a/docker/README.md b/docker/README.md index 48dc77105a..8e72362dc8 100644 --- a/docker/README.md +++ b/docker/README.md @@ -45,7 +45,7 @@ where service is either `gnb` for the srsRAN Project gNB or `5gc` for Open5GS. For a more advanced parametrization of the Open5GS container, e.g. to load subscriber data from a csv-file the `open5gs.env` file in `srsgnb/docker/open5gs` can be used by running: ```bash -docker compose -f docker/docker-compose.yml --env_file open5gs/open5gs.env up +docker compose -f docker/docker-compose.yml --env-file docker/open5gs/open5gs.env up ``` In [open5gs.env](open5gs/open5gs.env) the following parameters can be set: diff --git a/include/srsran/cu_cp/cu_cp.h b/include/srsran/cu_cp/cu_cp.h index b4d3439153..b8a0942ec1 100644 --- a/include/srsran/cu_cp/cu_cp.h +++ b/include/srsran/cu_cp/cu_cp.h @@ -92,6 +92,7 @@ class cu_cp_interface : public cu_cp_ngap_connection_interface, virtual cu_cp_cu_up_connection_interface& get_cu_cp_cu_up_connection_interface() = 0; virtual void start() = 0; + virtual void stop() = 0; }; } // namespace srs_cu_cp diff --git a/include/srsran/du/du_cell_config_helpers.h b/include/srsran/du/du_cell_config_helpers.h index feb3cc3777..192dabda31 100644 --- a/include/srsran/du/du_cell_config_helpers.h +++ b/include/srsran/du/du_cell_config_helpers.h @@ -142,6 +142,7 @@ inline std::map make_default_du_qos_config_list(int rl cfg.rlc.um.tx.sn_field_length = rlc_um_sn_size::size12bits; cfg.rlc.um.rx.sn_field_length = rlc_um_sn_size::size12bits; cfg.rlc.um.rx.t_reassembly = 100; + cfg.rlc.um.tx.queue_size = 4096; cfg.rlc.metrics_period = std::chrono::milliseconds(rlc_metrics_report); // F1-U cfg.f1u.t_notify = 10; @@ -154,13 +155,15 @@ inline std::map make_default_du_qos_config_list(int rl // RLC cfg.rlc.mode = rlc_mode::am; cfg.rlc.am.tx.sn_field_length = rlc_am_sn_size::size18bits; - cfg.rlc.am.tx.t_poll_retx = 100; + cfg.rlc.am.tx.t_poll_retx = 20; cfg.rlc.am.tx.poll_pdu = 16; - cfg.rlc.am.tx.poll_byte = 6500; - cfg.rlc.am.tx.max_retx_thresh = 16; + cfg.rlc.am.tx.poll_byte = -1; + cfg.rlc.am.tx.max_retx_thresh = 32; + cfg.rlc.am.tx.max_window = 0; + cfg.rlc.am.tx.queue_size = 4096; cfg.rlc.am.rx.sn_field_length = rlc_am_sn_size::size18bits; - cfg.rlc.am.rx.t_reassembly = 40; - cfg.rlc.am.rx.t_status_prohibit = 50; + cfg.rlc.am.rx.t_reassembly = 20; + cfg.rlc.am.rx.t_status_prohibit = 10; cfg.rlc.metrics_period = std::chrono::milliseconds(rlc_metrics_report); // F1-U cfg.f1u.t_notify = 10; diff --git a/include/srsran/ofh/ethernet/ethernet_factories.h b/include/srsran/ofh/ethernet/ethernet_factories.h index f0eadb58dd..4b03d2c46d 100644 --- a/include/srsran/ofh/ethernet/ethernet_factories.h +++ b/include/srsran/ofh/ethernet/ethernet_factories.h @@ -43,6 +43,7 @@ std::unique_ptr create_gateway(const gw_config& config, srslog::basic_l /// Creates an Ethernet receiver. std::unique_ptr create_receiver(const std::string& interface, + bool is_promiscuous_mode_enabled, task_executor& executor, frame_notifier& notifier, srslog::basic_logger& logger); diff --git a/include/srsran/ofh/ethernet/ethernet_gw_config.h b/include/srsran/ofh/ethernet/ethernet_gw_config.h index 93613917d5..93cba0c339 100644 --- a/include/srsran/ofh/ethernet/ethernet_gw_config.h +++ b/include/srsran/ofh/ethernet/ethernet_gw_config.h @@ -31,6 +31,8 @@ namespace ether { struct gw_config { /// Interface name. std::string interface; + /// Promiscuous mode flag. + bool is_promiscuous_mode_enabled; /// Destination MAC address. mac_address mac_dst_address; }; diff --git a/include/srsran/ofh/ofh_sector_config.h b/include/srsran/ofh/ofh_sector_config.h index 49b45fbf37..8610612b80 100644 --- a/include/srsran/ofh/ofh_sector_config.h +++ b/include/srsran/ofh/ofh_sector_config.h @@ -54,6 +54,8 @@ struct sector_configuration { /// Ethernet interface name. std::string interface; + /// Promiscuous mode flag. + bool is_promiscuous_mode_enabled; /// Destination MAC address, corresponds to the Radio Unit MAC address. ether::mac_address mac_dst_address; /// Source MAC address, corresponds to the Distributed Unit MAC address. diff --git a/include/srsran/phy/upper/uplink_processor.h b/include/srsran/phy/upper/uplink_processor.h index cacc5f547f..4a585188ad 100644 --- a/include/srsran/phy/upper/uplink_processor.h +++ b/include/srsran/phy/upper/uplink_processor.h @@ -52,8 +52,8 @@ class uplink_processor struct pusch_pdu { /// HARQ process number. unsigned harq_id; - /// Transport block size in bytes. - unsigned tb_size; + /// Transport block size. + units::bytes tb_size; /// PUSCH processor PDU. pusch_processor::pdu_t pdu; }; diff --git a/include/srsran/phy/upper/uplink_slot_pdu_repository.h b/include/srsran/phy/upper/uplink_slot_pdu_repository.h index 93a25fe1be..140dba3bc2 100644 --- a/include/srsran/phy/upper/uplink_slot_pdu_repository.h +++ b/include/srsran/phy/upper/uplink_slot_pdu_repository.h @@ -22,6 +22,7 @@ #pragma once +#include "srsran/adt/variant.h" #include "srsran/phy/upper/uplink_processor.h" #include "srsran/ran/slot_pdu_capacity_constants.h" #include @@ -29,18 +30,7 @@ namespace srsran { /// Defines an entry of the uplink slot PDU repository. -struct uplink_slot_pdu_entry { - /// Labels for the supported PDU types. - enum class pdu_type { PUSCH, PUCCH }; - - /// PDU type. - pdu_type type; - // :TODO: convert this to variant. - /// PUSCH PDU. - uplink_processor::pusch_pdu pusch; - /// PUCCH PDU. - uplink_processor::pucch_pdu pucch; -}; +using uplink_slot_pdu_entry = variant; /// \brief Uplink slot PDU repository. /// @@ -59,23 +49,13 @@ class uplink_slot_pdu_repository /// Adds the given PUSCH PDU to the repository at the given slot. void add_pusch_pdu(slot_point slot, const uplink_processor::pusch_pdu& pdu) { - uplink_slot_pdu_entry entry; - entry.type = uplink_slot_pdu_entry::pdu_type::PUSCH; - entry.pusch = pdu; - entry.pucch = {}; - - repository[slot.to_uint() % nof_slots].push_back(entry); + repository[slot.to_uint() % nof_slots].push_back(pdu); } /// Adds the given PUCCH PDU to the repository at the given slot. void add_pucch_pdu(slot_point slot, const uplink_processor::pucch_pdu& pdu) { - uplink_slot_pdu_entry entry; - entry.type = uplink_slot_pdu_entry::pdu_type::PUCCH; - entry.pucch = pdu; - entry.pusch = {}; - - repository[slot.to_uint() % nof_slots].push_back(entry); + repository[slot.to_uint() % nof_slots].push_back(pdu); } /// Clears the given slot of the registry. diff --git a/include/srsran/ran/prach/prach_helper.h b/include/srsran/ran/prach/prach_helper.h index 23c588452e..191290c375 100644 --- a/include/srsran/ran/prach/prach_helper.h +++ b/include/srsran/ran/prach/prach_helper.h @@ -50,7 +50,9 @@ error_type> prach_fits_in_tdd_pattern(subcarrier_spacing pusch_scs, uint8_t prach_cfg_idx, const tdd_ul_dl_config_common& tdd_cfg); /// \brief Finds a PRACH configuration index that ensures that PRACH falls in an TDD UL slot. -optional find_valid_prach_config_index(subcarrier_spacing pusch_scs, const tdd_ul_dl_config_common& tdd_cfg); +optional find_valid_prach_config_index(subcarrier_spacing pusch_scs, + uint8_t zero_correlation_zone, + const tdd_ul_dl_config_common& tdd_cfg); } // namespace prach_helper -} // namespace srsran \ No newline at end of file +} // namespace srsran diff --git a/include/srsran/rlc/rlc_config.h b/include/srsran/rlc/rlc_config.h index 8cde9ee0a9..b6fcc4c610 100644 --- a/include/srsran/rlc/rlc_config.h +++ b/include/srsran/rlc/rlc_config.h @@ -168,6 +168,7 @@ struct rlc_tx_am_config { int32_t poll_byte; ///< Insert poll bit after this much data (bytes) // Custom non-standard parameters + uint32_t queue_size; ///< SDU queue size uint32_t max_window; ///< Custom parameter to limit the maximum window size for memory reasons. 0 means no limit. }; @@ -189,6 +190,7 @@ struct rlc_rx_um_config { /// Ref: 3GPP TS 38.322 v15.3.0 Section 7 struct rlc_tx_um_config { rlc_um_sn_size sn_field_length; ///< Number of bits used for sequence number + uint32_t queue_size; ///< SDU queue size }; /// \brief Configurable parameters for RLC UM @@ -315,7 +317,7 @@ struct formatter { template auto format(srsran::rlc_tx_um_config cfg, FormatContext& ctx) -> decltype(std::declval().out()) { - return format_to(ctx.out(), "tx_sn_size={}", cfg.sn_field_length); + return format_to(ctx.out(), "tx_sn_size={}, queue_size={}", cfg.sn_field_length, cfg.queue_size); } }; @@ -364,12 +366,13 @@ struct formatter { auto format(srsran::rlc_tx_am_config cfg, FormatContext& ctx) -> decltype(std::declval().out()) { return format_to(ctx.out(), - "tx_sn_size={} t_poll_retx={} max_retx={} poll_pdu={} poll_byte={} max_window={}", + "tx_sn_size={} t_poll_retx={} max_retx={} poll_pdu={} poll_byte={} queue_size={} max_window={}", cfg.sn_field_length, cfg.t_poll_retx, cfg.max_retx_thresh, cfg.poll_pdu, cfg.poll_byte, + cfg.queue_size, cfg.max_window); } }; diff --git a/include/srsran/ru/ru_ofh_configuration.h b/include/srsran/ru/ru_ofh_configuration.h index 05bf0af081..ed14342651 100644 --- a/include/srsran/ru/ru_ofh_configuration.h +++ b/include/srsran/ru/ru_ofh_configuration.h @@ -80,6 +80,8 @@ struct ru_ofh_sector_configuration { /// Ethernet interface name. std::string interface; + /// Promiscuous mode flag. + bool is_promiscuous_mode_enabled; /// Destination MAC address, corresponds to Radio Unit MAC address. ether::mac_address mac_dst_address; /// Source MAC address, corresponds to Distributed Unit MAC address. diff --git a/lib/cu_cp/cu_cp_impl.cpp b/lib/cu_cp/cu_cp_impl.cpp index edb115ae2e..59465b6bc7 100644 --- a/lib/cu_cp/cu_cp_impl.cpp +++ b/lib/cu_cp/cu_cp_impl.cpp @@ -124,7 +124,35 @@ void cu_cp_impl::start() } } -void cu_cp_impl::stop() {} +void cu_cp_impl::stop() +{ + bool already_stopped = stopped.exchange(true); + if (already_stopped) { + return; + } + + logger.info("Stopping CU-CP..."); + std::promise p; + std::future fut = p.get_future(); + + // Shut down components from within CU-CP executor. + while (not cfg.cu_cp_executor->execute([this, &p]() { + // Stop statistics gathering. + statistics_report_timer.stop(); + + // Signal back that CU-CP is stopped. + p.set_value(); + })) { + logger.debug("Failed to dispatch CU-CP stop task. Retrying..."); + // Keep dispatching until the task is accepted. + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + + // Block waiting for CU-CP stop to complete. + fut.wait(); + + logger.info("CU-CP stopped successfully."); +} size_t cu_cp_impl::get_nof_cu_ups() const { diff --git a/lib/cu_cp/cu_cp_impl.h b/lib/cu_cp/cu_cp_impl.h index 6fc4f13f3a..00f673c7ec 100644 --- a/lib/cu_cp/cu_cp_impl.h +++ b/lib/cu_cp/cu_cp_impl.h @@ -51,10 +51,10 @@ class cu_cp_impl final : public cu_cp_interface, public cu_cp_impl_interface { public: explicit cu_cp_impl(const cu_cp_configuration& config_); - ~cu_cp_impl(); + ~cu_cp_impl() override; void start() override; - void stop(); + void stop() override; // CU-CP CU-UP interface size_t get_nof_cu_ups() const override; @@ -182,6 +182,8 @@ class cu_cp_impl final : public cu_cp_interface, public cu_cp_impl_interface std::atomic amf_connected = {false}; unique_timer statistics_report_timer; + + std::atomic stopped{false}; }; } // namespace srs_cu_cp diff --git a/lib/du_high/mac_test_mode_adapter.cpp b/lib/du_high/mac_test_mode_adapter.cpp index 37b6eef242..6fe8cc4aa1 100644 --- a/lib/du_high/mac_test_mode_adapter.cpp +++ b/lib/du_high/mac_test_mode_adapter.cpp @@ -91,6 +91,7 @@ class test_cell_adapter : public mac_cell_control_information_handler // It is not the test UE. continue; } + srsran_assert(ue_cfg_req.cells.has_value(), "CRC received for test mode which is not yet created"); // Force CRC=OK for test UE. crc.tb_crc_success = true; @@ -113,6 +114,7 @@ class test_cell_adapter : public mac_cell_control_information_handler // It is not the test UE. continue; } + srsran_assert(ue_cfg_req.cells.has_value(), "UCI received for test mode which is not yet created"); // In case of test UE, set HARQ-Info always equal to ACK. if (variant_holds_alternative(uci.pdu)) { @@ -207,7 +209,7 @@ class test_cell_adapter : public mac_cell_control_information_handler mac_cell_control_information_handler& adapted; mac_pdu_handler& pdu_handler; std::function dl_bs_notifier; - sched_ue_config_request ue_cfg_req; + const sched_ue_config_request& ue_cfg_req; bool msg4_rx_flag = false; }; @@ -269,22 +271,25 @@ mac_test_mode_adapter::adapt_bearers(const std::vector mac_test_mode_adapter::handle_ue_create_request(const mac_ue_create_request& cfg) { - mac_ue_create_request cfg_adapted = cfg; - if (cfg_adapted.crnti == test_ue.rnti) { + if (cfg.crnti == test_ue.rnti) { // It is the test UE. + mac_ue_create_request cfg_copy = cfg; // Save UE index. - test_ue_index = cfg_adapted.ue_index; + test_ue_index = cfg_copy.ue_index; // Add adapters to the UE config bearers before passing it to MAC. - cfg_adapted.bearers = adapt_bearers(cfg.bearers); + cfg_copy.bearers = adapt_bearers(cfg.bearers); // Save config of test mode UE. - test_ue_cfg = cfg_adapted.sched_cfg; + test_ue_cfg = cfg_copy.sched_cfg; + + // Forward test UE creation request to MAC. + return mac_adapted->get_ue_configurator().handle_ue_create_request(cfg_copy); } - // Forward UE creation request to MAC. - return mac_adapted->get_ue_configurator().handle_ue_create_request(cfg_adapted); + // Forward normal UE creation request to MAC. + return mac_adapted->get_ue_configurator().handle_ue_create_request(cfg); } async_task diff --git a/lib/du_manager/converters/rlc_config_helpers.cpp b/lib/du_manager/converters/rlc_config_helpers.cpp index 5dd97305f9..2cdd7b4909 100644 --- a/lib/du_manager/converters/rlc_config_helpers.cpp +++ b/lib/du_manager/converters/rlc_config_helpers.cpp @@ -34,6 +34,7 @@ rlc_config srsran::srs_du::make_default_srb_rlc_config() cfg.am.tx.poll_pdu = -1; cfg.am.tx.poll_byte = -1; cfg.am.tx.max_retx_thresh = 8; + cfg.am.tx.queue_size = 256; cfg.am.rx.sn_field_length = rlc_am_sn_size::size12bits; cfg.am.rx.t_reassembly = 35; cfg.am.rx.t_status_prohibit = 0; diff --git a/lib/fapi_adaptor/phy/messages/pusch.cpp b/lib/fapi_adaptor/phy/messages/pusch.cpp index ab24a0b10f..14b8cacf82 100644 --- a/lib/fapi_adaptor/phy/messages/pusch.cpp +++ b/lib/fapi_adaptor/phy/messages/pusch.cpp @@ -38,7 +38,7 @@ static void fill_codeword(uplink_processor::pusch_pdu& pdu, const fapi::ul_pusch cw.new_data = fapi_pdu.pusch_data.new_data; pdu.harq_id = fapi_pdu.pusch_data.harq_process_id; - pdu.tb_size = fapi_pdu.pusch_data.tb_size.value(); + pdu.tb_size = fapi_pdu.pusch_data.tb_size; pdu.pdu.codeword = optional(std::move(cw)); } diff --git a/lib/ofh/ethernet/dpdk/dpdk_ethernet_factories.cpp b/lib/ofh/ethernet/dpdk/dpdk_ethernet_factories.cpp index 69bf3c2657..4e009a5bec 100644 --- a/lib/ofh/ethernet/dpdk/dpdk_ethernet_factories.cpp +++ b/lib/ofh/ethernet/dpdk/dpdk_ethernet_factories.cpp @@ -27,9 +27,9 @@ using namespace srsran; using namespace ether; -std::unique_ptr srsran::ether::create_dpdk_gateway(srslog::basic_logger& logger) +std::unique_ptr srsran::ether::create_dpdk_gateway(const gw_config& config, srslog::basic_logger& logger) { - return std::make_unique(logger); + return std::make_unique(config, logger); } std::unique_ptr diff --git a/lib/ofh/ethernet/dpdk/dpdk_ethernet_factories.h b/lib/ofh/ethernet/dpdk/dpdk_ethernet_factories.h index 4bc60e0288..2f728a135e 100644 --- a/lib/ofh/ethernet/dpdk/dpdk_ethernet_factories.h +++ b/lib/ofh/ethernet/dpdk/dpdk_ethernet_factories.h @@ -34,9 +34,10 @@ class task_executor; namespace ether { class frame_notifier; +struct gw_config; /// Creates a DPDK Ethernet gateway. -std::unique_ptr create_dpdk_gateway(srslog::basic_logger& logger); +std::unique_ptr create_dpdk_gateway(const gw_config& config, srslog::basic_logger& logger); /// Creates a DPDK Ethernet receiver. std::unique_ptr diff --git a/lib/ofh/ethernet/dpdk/dpdk_ethernet_transmitter.cpp b/lib/ofh/ethernet/dpdk/dpdk_ethernet_transmitter.cpp index bc9d9e68c4..1d5b7ab9e9 100644 --- a/lib/ofh/ethernet/dpdk/dpdk_ethernet_transmitter.cpp +++ b/lib/ofh/ethernet/dpdk/dpdk_ethernet_transmitter.cpp @@ -22,6 +22,7 @@ #include "dpdk_ethernet_transmitter.h" #include "srsran/adt/static_vector.h" +#include "srsran/ofh/ethernet/ethernet_gw_config.h" #include using namespace srsran; @@ -36,7 +37,7 @@ static constexpr unsigned TX_RING_SIZE = 1024; static constexpr unsigned NUM_MBUFS = 8191; /// DPDK port initialization routine. -static bool port_init(::rte_mempool* mbuf_pool, unsigned port) +static bool port_init(const gw_config& config, ::rte_mempool* mbuf_pool, unsigned port) { uint16_t nb_rxd = RX_RING_SIZE; uint16_t nb_txd = TX_RING_SIZE; @@ -96,16 +97,18 @@ static bool port_init(::rte_mempool* mbuf_pool, unsigned port) } // Enable RX in promiscuous mode for the Ethernet device. - if (::rte_eth_promiscuous_enable(port) != 0) { - fmt::print("Error enabling promiscuous mode\n"); - return false; + if (config.is_promiscuous_mode_enabled) { + if (::rte_eth_promiscuous_enable(port) != 0) { + fmt::print("Error enabling promiscuous mode\n"); + return false; + } } return true; } /// Configures an Ethernet port using DPDK. -static void dpdk_port_configure(::rte_mempool*& mbuf_pool) +static void dpdk_port_configure(const gw_config& config, ::rte_mempool*& mbuf_pool) { if (::rte_eth_dev_count_avail() != 1) { ::rte_exit(EXIT_FAILURE, "Error: number of ports must be one\n"); @@ -122,7 +125,7 @@ static void dpdk_port_configure(::rte_mempool*& mbuf_pool) unsigned portid; RTE_ETH_FOREACH_DEV(portid) { - if (!port_init(mbuf_pool, portid)) { + if (!port_init(config, mbuf_pool, portid)) { ::rte_exit(EXIT_FAILURE, "Cannot init port\n"); } } @@ -155,7 +158,7 @@ void dpdk_transmitter_impl::send(span> frames) ::rte_eth_tx_burst(port_id, 0, mbufs.data(), mbufs.size()); } -dpdk_transmitter_impl::dpdk_transmitter_impl(srslog::basic_logger& logger_) : logger(logger_) +dpdk_transmitter_impl::dpdk_transmitter_impl(const gw_config& config, srslog::basic_logger& logger_) : logger(logger_) { - dpdk_port_configure(mbuf_pool); + dpdk_port_configure(config, mbuf_pool); } diff --git a/lib/ofh/ethernet/dpdk/dpdk_ethernet_transmitter.h b/lib/ofh/ethernet/dpdk/dpdk_ethernet_transmitter.h index 3abe55c1e1..ef746dcc0b 100644 --- a/lib/ofh/ethernet/dpdk/dpdk_ethernet_transmitter.h +++ b/lib/ofh/ethernet/dpdk/dpdk_ethernet_transmitter.h @@ -30,11 +30,13 @@ struct rte_mempool; namespace srsran { namespace ether { +struct gw_config; + /// DPDK Ethernet transmitter implementation. class dpdk_transmitter_impl : public gateway { public: - explicit dpdk_transmitter_impl(srslog::basic_logger& logger_); + explicit dpdk_transmitter_impl(const gw_config& config, srslog::basic_logger& logger_); // See interface for documentation. void send(span> frames) override; diff --git a/lib/ofh/ethernet/ethernet_factories.cpp b/lib/ofh/ethernet/ethernet_factories.cpp index 8576d1c52c..881de4a4c5 100644 --- a/lib/ofh/ethernet/ethernet_factories.cpp +++ b/lib/ofh/ethernet/ethernet_factories.cpp @@ -35,11 +35,12 @@ std::unique_ptr srsran::ether::create_gateway(const gw_config& config, } std::unique_ptr srsran::ether::create_receiver(const std::string& interface, + bool is_promiscuous_mode_enabled, task_executor& executor, frame_notifier& notifier, srslog::basic_logger& logger) { - return std::make_unique(interface, executor, notifier, logger); + return std::make_unique(interface, is_promiscuous_mode_enabled, executor, notifier, logger); } std::unique_ptr srsran::ether::create_vlan_frame_builder() diff --git a/lib/ofh/ethernet/ethernet_receiver_impl.cpp b/lib/ofh/ethernet/ethernet_receiver_impl.cpp index fbae1734bd..ebfdd31bb8 100644 --- a/lib/ofh/ethernet/ethernet_receiver_impl.cpp +++ b/lib/ofh/ethernet/ethernet_receiver_impl.cpp @@ -35,6 +35,7 @@ using namespace srsran; using namespace ether; receiver_impl::receiver_impl(const std::string& interface, + bool is_promiscuous_mode_enabled, task_executor& executor_, frame_notifier& notifier_, srslog::basic_logger& logger_) : @@ -45,15 +46,17 @@ receiver_impl::receiver_impl(const std::string& interface, report_error("Unable to open socket for Ethernet receiver"); } - // Set interface to promiscuous mode. - ::ifreq if_opts; - ::strncpy(if_opts.ifr_name, interface.c_str(), IFNAMSIZ - 1); - if (::ioctl(socket_fd, SIOCGIFFLAGS, &if_opts) < 0) { - report_error("Unable to get flags for NIC interface in the Ethernet receiver"); - } - if_opts.ifr_flags |= IFF_PROMISC; - if (::ioctl(socket_fd, SIOCSIFFLAGS, &if_opts) < 0) { - report_error("Unable to set flags for NIC interface in the Ethernet receiver"); + if (is_promiscuous_mode_enabled) { + // Set interface to promiscuous mode. + ::ifreq if_opts; + ::strncpy(if_opts.ifr_name, interface.c_str(), IFNAMSIZ - 1); + if (::ioctl(socket_fd, SIOCGIFFLAGS, &if_opts) < 0) { + report_error("Unable to get flags for NIC interface in the Ethernet receiver"); + } + if_opts.ifr_flags |= IFF_PROMISC; + if (::ioctl(socket_fd, SIOCSIFFLAGS, &if_opts) < 0) { + report_error("Unable to set flags for NIC interface in the Ethernet receiver"); + } } // Bind to device. diff --git a/lib/ofh/ethernet/ethernet_receiver_impl.h b/lib/ofh/ethernet/ethernet_receiver_impl.h index 40190dd249..a28c3a457b 100644 --- a/lib/ofh/ethernet/ethernet_receiver_impl.h +++ b/lib/ofh/ethernet/ethernet_receiver_impl.h @@ -38,6 +38,7 @@ class receiver_impl : public receiver { public: receiver_impl(const std::string& interface, + bool is_promiscuous_mode_enabled, task_executor& executor_, frame_notifier& notifier_, srslog::basic_logger& logger_); diff --git a/lib/ofh/ofh_factories.cpp b/lib/ofh/ofh_factories.cpp index 338f9413bf..5014b525b3 100644 --- a/lib/ofh/ofh_factories.cpp +++ b/lib/ofh/ofh_factories.cpp @@ -310,11 +310,12 @@ resolve_transmitter_dependencies(const sector_configuration& *sector_cfg.downlink_executors.front()); ether::gw_config eth_cfg; - eth_cfg.interface = sector_cfg.interface; - eth_cfg.mac_dst_address = sector_cfg.mac_dst_address; + eth_cfg.interface = sector_cfg.interface; + eth_cfg.is_promiscuous_mode_enabled = sector_cfg.is_promiscuous_mode_enabled; + eth_cfg.mac_dst_address = sector_cfg.mac_dst_address; #ifdef DPDK_FOUND if (sector_cfg.uses_dpdk) { - dependencies.eth_gateway = ether::create_dpdk_gateway(*sector_cfg.logger); + dependencies.eth_gateway = ether::create_dpdk_gateway(eth_cfg, *sector_cfg.logger); } else { dependencies.eth_gateway = ether::create_gateway(eth_cfg, *sector_cfg.logger); } @@ -350,12 +351,16 @@ std::unique_ptr srsran::ofh::create_ofh_sector(const sector_configuratio receiver->get_ethernet_frame_notifier(), *sector_cfg.logger) : ether::create_receiver(sector_cfg.interface, + sector_cfg.is_promiscuous_mode_enabled, *sector_cfg.receiver_executor, receiver->get_ethernet_frame_notifier(), *sector_cfg.logger); #else - auto eth_receiver = ether::create_receiver( - sector_cfg.interface, *sector_cfg.receiver_executor, receiver->get_ethernet_frame_notifier(), *sector_cfg.logger); + auto eth_receiver = ether::create_receiver(sector_cfg.interface, + sector_cfg.is_promiscuous_mode_enabled, + *sector_cfg.receiver_executor, + receiver->get_ethernet_frame_notifier(), + *sector_cfg.logger); #endif return std::make_unique(std::move(receiver), diff --git a/lib/phy/upper/channel_modulation/evm_calculator_generic_impl.cpp b/lib/phy/upper/channel_modulation/evm_calculator_generic_impl.cpp index d742e4baf0..4d3d212a3b 100644 --- a/lib/phy/upper/channel_modulation/evm_calculator_generic_impl.cpp +++ b/lib/phy/upper/channel_modulation/evm_calculator_generic_impl.cpp @@ -31,15 +31,43 @@ float evm_calculator_generic_impl::calculate(span so span symbols, modulation_scheme modulation) { - // Perform hard-decision. - bit_buffer hard_bits = temp_hard_bits.first(soft_bits.size()); - hard_decision(hard_bits, soft_bits); + // Get modulation order. + unsigned bits_per_symbol = get_bits_per_symbol(modulation); - // Modulate. - span modulated = temp_modulated.first(symbols.size()); - modulator->modulate(modulated, hard_bits, modulation); + // Verify that soft bits and symbols dimensions are consistent. + srsran_assert(soft_bits.size() == symbols.size() * bits_per_symbol, + "The number of soft bits (i.e., {}) is not consistent with the number of symbols (i.e., {}) and " + "modulation (i.e., {}).", + soft_bits.size(), + symbols.size(), + to_string(modulation)); - // Calculate EVM. - srsvec::subtract(modulated, symbols, modulated); - return std::sqrt(srsvec::average_power(modulated)); + unsigned nof_symbols = symbols.size(); + float avg_power = 0.0; + + while (!soft_bits.empty()) { + unsigned block_nof_symbols = + std::min(static_cast(symbols.size()), static_cast(MAX_NOF_SYMBOLS)); + unsigned block_nof_bits = block_nof_symbols * bits_per_symbol; + + // Perform hard-decision. + bit_buffer hard_bits = temp_hard_bits.first(block_nof_bits); + hard_decision(hard_bits, soft_bits.first(block_nof_bits)); + + // Modulate. + span modulated = temp_modulated.first(block_nof_symbols); + modulator->modulate(modulated, hard_bits, modulation); + + // Calculate EVM. + srsvec::subtract(modulated, symbols.first(block_nof_symbols), modulated); + + // Accumulate power. + avg_power += std::real(srsvec::dot_prod(modulated, modulated)); + + // Pop bits and symbols. + symbols = symbols.last(symbols.size() - block_nof_symbols); + soft_bits = soft_bits.last(soft_bits.size() - block_nof_bits); + } + + return std::sqrt(avg_power / static_cast(nof_symbols)); } diff --git a/lib/phy/upper/channel_modulation/evm_calculator_generic_impl.h b/lib/phy/upper/channel_modulation/evm_calculator_generic_impl.h index 0309f0aa36..a2b567c62a 100644 --- a/lib/phy/upper/channel_modulation/evm_calculator_generic_impl.h +++ b/lib/phy/upper/channel_modulation/evm_calculator_generic_impl.h @@ -45,9 +45,9 @@ class evm_calculator_generic_impl : public evm_calculator modulation_scheme modulation) override; private: - /// Maximum number of symbols assuming 156 RE/RB, 275 RB and 4 layers. - static constexpr unsigned MAX_NOF_SYMBOLS = 156 * 275 * 4; - /// Maximum number of bits. + /// Maximum processing block size in number of symbols. + static constexpr unsigned MAX_NOF_SYMBOLS = 4096; + /// Maximum processing block size in number of bits. static constexpr unsigned MAX_NOF_BITS = MAX_NOF_SYMBOLS * 8; /// Internal modulator. std::unique_ptr modulator; diff --git a/lib/phy/upper/channel_processors/channel_processor_factories.cpp b/lib/phy/upper/channel_processors/channel_processor_factories.cpp index 2f26a8da18..85b0a5c189 100644 --- a/lib/phy/upper/channel_processors/channel_processor_factories.cpp +++ b/lib/phy/upper/channel_processors/channel_processor_factories.cpp @@ -317,32 +317,16 @@ class pdsch_processor_factory_sw : public pdsch_processor_factory class pdsch_processor_concurrent_factory_sw : public pdsch_processor_factory { -private: - std::shared_ptr crc_factory; - std::shared_ptr encoder_factory; - std::shared_ptr rate_matcher_factory; - std::shared_ptr prg_factory; - std::shared_ptr modulator_factory; - std::shared_ptr dmrs_factory; - task_executor& executor; - std::shared_ptr cb_processor_pool; - public: - pdsch_processor_concurrent_factory_sw(std::shared_ptr crc_factory_, - std::shared_ptr encoder_factory_, - std::shared_ptr rate_matcher_factory_, + pdsch_processor_concurrent_factory_sw(std::shared_ptr crc_factory, + std::shared_ptr encoder_factory, + std::shared_ptr rate_matcher_factory, std::shared_ptr prg_factory_, - std::shared_ptr modulator_factory_, - std::shared_ptr dmrs_factory_, + std::shared_ptr modulator_factory, + std::shared_ptr dmrs_factory, task_executor& executor_, unsigned nof_concurrent_threads) : - crc_factory(std::move(crc_factory_)), - encoder_factory(std::move(encoder_factory_)), - rate_matcher_factory(std::move(rate_matcher_factory_)), - prg_factory(std::move(prg_factory_)), - modulator_factory(std::move(modulator_factory_)), - dmrs_factory(std::move(dmrs_factory_)), - executor(executor_) + prg_factory(std::move(prg_factory_)), executor(executor_) { srsran_assert(crc_factory, "Invalid CRC calculator factory."); srsran_assert(encoder_factory, "Invalid encoder factory."); @@ -368,18 +352,34 @@ class pdsch_processor_concurrent_factory_sw : public pdsch_processor_factory // Create pool of codeblock processors. It is common for all PDSCH processors. cb_processor_pool = std::make_shared(std::move(cb_processors)); + + // Create vector of PDSCH DM-RS generators. + std::vector> dmrs_generators; + for (unsigned i_encoder = 0; i_encoder != nof_concurrent_threads; ++i_encoder) { + dmrs_generators.emplace_back(dmrs_factory->create()); + } + + // Create pool of PDSCH DM-RS generators. It is common for all PDSCH processors. + dmrs_generator_pool = + std::make_shared(std::move(dmrs_generators)); } std::unique_ptr create() override { return std::make_unique( - cb_processor_pool, prg_factory->create(), dmrs_factory->create(), executor); + cb_processor_pool, prg_factory->create(), dmrs_generator_pool, executor); } std::unique_ptr create_validator() override { return std::make_unique(); } + +private: + std::shared_ptr prg_factory; + task_executor& executor; + std::shared_ptr cb_processor_pool; + std::shared_ptr dmrs_generator_pool; }; class pdsch_processor_lite_factory_sw : public pdsch_processor_factory 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 3cd8bf9dfd..c0d4baba58 100644 --- a/lib/phy/upper/channel_processors/pdsch_processor_concurrent_impl.cpp +++ b/lib/phy/upper/channel_processors/pdsch_processor_concurrent_impl.cpp @@ -394,7 +394,7 @@ void pdsch_processor_concurrent_impl::process_dmrs() dmrs_config.precoding = config.precoding; // Put DM-RS. - dmrs->map(*mapper, dmrs_config); + dmrs_generator_pool->get().map(*mapper, dmrs_config); // 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 9c25b740c4..ed1674d5bf 100644 --- a/lib/phy/upper/channel_processors/pdsch_processor_concurrent_impl.h +++ b/lib/phy/upper/channel_processors/pdsch_processor_concurrent_impl.h @@ -39,6 +39,8 @@ class pdsch_processor_concurrent_impl : public pdsch_processor public: /// Codeblock processor pool type. using codeblock_processor_pool = concurrent_thread_local_object_pool; + /// PDSCH DM-RS generator pool type. + using pdsch_dmrs_generator_pool = concurrent_thread_local_object_pool; /// \brief Creates a concurrent PDSCH processor with all the dependencies. /// \param[in] segmenter_ LDPC transmitter segmenter. @@ -46,19 +48,19 @@ class pdsch_processor_concurrent_impl : public pdsch_processor /// \param[in] scrambler_ Scrambling pseudo-random generator. /// \param[in] dmrs_ DM-RS for PDSCH generator. /// \param[in] executor_ Asynchronous task executor. - pdsch_processor_concurrent_impl(std::shared_ptr cb_processor_pool_, - std::unique_ptr scrambler_, - std::unique_ptr dmrs_, - task_executor& executor_) : + pdsch_processor_concurrent_impl(std::shared_ptr cb_processor_pool_, + std::unique_ptr scrambler_, + std::shared_ptr dmrs_generator_pool_, + task_executor& executor_) : scrambler(std::move(scrambler_)), cb_processor_pool(std::move(cb_processor_pool_)), - dmrs(std::move(dmrs_)), + dmrs_generator_pool(std::move(dmrs_generator_pool_)), executor(executor_), temp_codeword(pdsch_constants::CODEWORD_MAX_SYMBOLS) { - srsran_assert(scrambler != nullptr, "Invalid scrambler pointer."); - srsran_assert(cb_processor_pool != nullptr, "Invalid CB processor pool pointer."); - srsran_assert(dmrs != nullptr, "Invalid DM-RS pointer."); + srsran_assert(scrambler, "Invalid scrambler pointer."); + srsran_assert(cb_processor_pool, "Invalid CB processor pool pointer."); + srsran_assert(dmrs_generator_pool, "Invalid DM-RS pointer."); } // See interface for documentation. @@ -103,7 +105,7 @@ class pdsch_processor_concurrent_impl : public pdsch_processor /// Pool of code block processors. std::shared_ptr cb_processor_pool; /// DM-RS processor. - std::unique_ptr dmrs; + std::shared_ptr dmrs_generator_pool; /// Asynchronous task executor. task_executor& executor; 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 a0f5741382..0a530444ed 100644 --- a/lib/phy/upper/upper_phy_rx_symbol_handler_impl.cpp +++ b/lib/phy/upper/upper_phy_rx_symbol_handler_impl.cpp @@ -78,9 +78,14 @@ void upper_phy_rx_symbol_handler_impl::handle_rx_symbol(const upper_phy_rx_symbo } const uplink_slot_pdu_entry& first_entry = pdus.front(); - unsigned nof_symbols = - get_nsymb_per_slot((first_entry.type == uplink_slot_pdu_entry::pdu_type::PUSCH) ? first_entry.pusch.pdu.cp - : get_cp(first_entry.pucch)); + unsigned nof_symbols = 0; + if (variant_holds_alternative(first_entry)) { + const uplink_processor::pusch_pdu& pdu = variant_get(first_entry); + nof_symbols = get_nsymb_per_slot(pdu.pdu.cp); + } else { + const uplink_processor::pucch_pdu& pdu = variant_get(first_entry); + nof_symbols = get_nsymb_per_slot(get_cp(pdu)); + } unsigned last_symbol_id = nof_symbols - 1U; // Process the PDUs when all symbols of the slot have been received. @@ -93,13 +98,12 @@ void upper_phy_rx_symbol_handler_impl::handle_rx_symbol(const upper_phy_rx_symbo // Process all the PDUs from the pool. for (const auto& pdu : pdus) { - switch (pdu.type) { - case uplink_slot_pdu_entry::pdu_type::PUSCH: - process_pusch(pdu.pusch, ul_processor, grid, context.slot); - break; - case uplink_slot_pdu_entry::pdu_type::PUCCH: - ul_processor.process_pucch(rx_results_notifier, grid, pdu.pucch); - break; + if (variant_holds_alternative(pdu)) { + const uplink_processor::pusch_pdu& pusch_pdu = variant_get(pdu); + process_pusch(pusch_pdu, ul_processor, grid, context.slot); + } else if (variant_holds_alternative(pdu)) { + const uplink_processor::pucch_pdu& pucch_pdu = variant_get(pdu); + ul_processor.process_pucch(rx_results_notifier, grid, pucch_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 8af3af4d16..e7ef9a6ba6 100644 --- a/lib/phy/upper/upper_phy_rx_symbol_handler_impl.h +++ b/lib/phy/upper/upper_phy_rx_symbol_handler_impl.h @@ -39,21 +39,22 @@ class upper_phy_rx_results_notifier; class rx_payload_buffer_pool { /// Maximum number of payloads contained by the pool. - static const size_t MAX_NUM_PAYLOAD = 4096U; - static const size_t MAX_BUFFER_SIZE = MAX_RB * 156 * 8; + static constexpr size_t MAX_NUM_PAYLOAD = 4096U; + static constexpr units::bits MAX_BUFFER_SIZE = units::bits(MAX_RB * 156 * 8); public: /// Returns the next available buffer from the pool. - span acquire_payload_buffer(size_t size) + span acquire_payload_buffer(units::bytes size) { - srsran_assert(size <= MAX_BUFFER_SIZE, "Buffer size (i.e., {}) exceeds maximum {}.", size, pool[index].size()); + srsran_assert( + size.value() <= pool[index].size(), "Buffer size (i.e., {}) exceeds maximum {}.", size, pool[index].size()); unsigned i = index++ % MAX_NUM_PAYLOAD; - return span(pool[i]).first(size); + return span(pool[i]).first(size.value()); } private: /// Buffer pool. - circular_array, MAX_NUM_PAYLOAD> pool; + circular_array, MAX_NUM_PAYLOAD> pool; /// Index used to retrieve the next container. unsigned index = 0; }; diff --git a/lib/ran/prach/prach_helper.cpp b/lib/ran/prach/prach_helper.cpp index 70ee6fba80..04d64d675f 100644 --- a/lib/ran/prach/prach_helper.cpp +++ b/lib/ran/prach/prach_helper.cpp @@ -66,7 +66,7 @@ error_type srsran::prach_helper::zero_correlation_zone_is_valid(uin if ((prach_config.format == prach_format_type::B4) && (zero_correlation_zone != 0) && (zero_correlation_zone != 14)) { return fmt::format( - "PRACH Zero Correlation Zone index (i.e., {}) with Format B4 is not supported for FDD. Use 0 or 14.\n", + "PRACH Zero Correlation Zone index (i.e., {}) with Format B4 is not supported for TDD. Use 0 or 14.\n", zero_correlation_zone); } } @@ -105,7 +105,8 @@ error_type> srsran::prach_helper::prach_fits_in_tdd_pattern(su return {}; } -optional srsran::prach_helper::find_valid_prach_config_index(subcarrier_spacing pusch_scs, +optional srsran::prach_helper::find_valid_prach_config_index(subcarrier_spacing pusch_scs, + uint8_t zero_correlation_zone, const tdd_ul_dl_config_common& tdd_cfg) { static constexpr size_t NOF_PRACH_CONFIG_INDEXES = 256; @@ -113,6 +114,7 @@ optional srsran::prach_helper::find_valid_prach_config_index(subcarrier // Iterate over different PRACH configuration indexes until a valid one is found. for (unsigned prach_cfg_idx = 0; prach_cfg_idx != NOF_PRACH_CONFIG_INDEXES; ++prach_cfg_idx) { if (prach_config_index_is_valid(prach_cfg_idx, duplex_mode::TDD).has_value() and + zero_correlation_zone_is_valid(zero_correlation_zone, prach_cfg_idx, duplex_mode::TDD).has_value() and prach_fits_in_tdd_pattern(pusch_scs, prach_cfg_idx, tdd_cfg).has_value()) { return prach_cfg_idx; } diff --git a/lib/rlc/rlc_tx_am_entity.cpp b/lib/rlc/rlc_tx_am_entity.cpp index 89acfbd884..32c3258a6b 100644 --- a/lib/rlc/rlc_tx_am_entity.cpp +++ b/lib/rlc/rlc_tx_am_entity.cpp @@ -41,6 +41,7 @@ rlc_tx_am_entity::rlc_tx_am_entity(du_ue_index_t du_index task_executor& ue_executor_) : rlc_tx_entity(du_index, rb_id, upper_dn_, upper_cn_, lower_dn_), cfg(config), + sdu_queue(cfg.queue_size), retx_queue(window_size(to_number(cfg.sn_field_length))), 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_tx_um_entity.cpp b/lib/rlc/rlc_tx_um_entity.cpp index 2ccef0bc76..64b2a86804 100644 --- a/lib/rlc/rlc_tx_um_entity.cpp +++ b/lib/rlc/rlc_tx_um_entity.cpp @@ -35,6 +35,7 @@ rlc_tx_um_entity::rlc_tx_um_entity(du_ue_index_t du_index task_executor& pcell_executor_) : rlc_tx_entity(du_index, rb_id, upper_dn_, upper_cn_, lower_dn_), cfg(config), + sdu_queue(cfg.queue_size), mod(cardinality(to_number(cfg.sn_field_length))), head_len_full(rlc_um_pdu_header_size_complete_sdu), head_len_first(rlc_um_pdu_header_size_no_so(cfg.sn_field_length)), diff --git a/lib/ru/ofh/ru_ofh_factory.cpp b/lib/ru/ofh/ru_ofh_factory.cpp index b425d56ec3..5804ee528c 100644 --- a/lib/ru/ofh/ru_ofh_factory.cpp +++ b/lib/ru/ofh/ru_ofh_factory.cpp @@ -39,21 +39,22 @@ static ofh::sector_configuration generate_sector_configuration(const ru_ofh_conf // Prepare sector configuration. ofh::sector_configuration ofh_sector_config; - ofh_sector_config.logger = config.logger; - ofh_sector_config.transmitter_executor = sector_cfg.transmitter_executor; - ofh_sector_config.receiver_executor = sector_cfg.receiver_executor; - ofh_sector_config.downlink_executors = sector_cfg.downlink_executors; - ofh_sector_config.notifier = notifier; - ofh_sector_config.interface = sector_cfg.interface; - ofh_sector_config.mac_dst_address = sector_cfg.mac_dst_address; - ofh_sector_config.mac_src_address = sector_cfg.mac_src_address; - ofh_sector_config.tci = sector_cfg.tci; - ofh_sector_config.tx_window_timing_params = sector_cfg.tx_window_timing_params; - ofh_sector_config.rx_window_timing_params = sector_cfg.rx_window_timing_params; - ofh_sector_config.cp = sector_cfg.cp; - ofh_sector_config.scs = sector_cfg.scs; - ofh_sector_config.bw = sector_cfg.bw; - ofh_sector_config.nof_antennas_ul = sector_cfg.nof_antennas_ul; + ofh_sector_config.logger = config.logger; + ofh_sector_config.transmitter_executor = sector_cfg.transmitter_executor; + ofh_sector_config.receiver_executor = sector_cfg.receiver_executor; + ofh_sector_config.downlink_executors = sector_cfg.downlink_executors; + ofh_sector_config.notifier = notifier; + ofh_sector_config.interface = sector_cfg.interface; + ofh_sector_config.is_promiscuous_mode_enabled = sector_cfg.is_promiscuous_mode_enabled; + ofh_sector_config.mac_dst_address = sector_cfg.mac_dst_address; + ofh_sector_config.mac_src_address = sector_cfg.mac_src_address; + ofh_sector_config.tci = sector_cfg.tci; + ofh_sector_config.tx_window_timing_params = sector_cfg.tx_window_timing_params; + ofh_sector_config.rx_window_timing_params = sector_cfg.rx_window_timing_params; + ofh_sector_config.cp = sector_cfg.cp; + ofh_sector_config.scs = sector_cfg.scs; + ofh_sector_config.bw = sector_cfg.bw; + ofh_sector_config.nof_antennas_ul = sector_cfg.nof_antennas_ul; ofh_sector_config.ru_operating_bw = sector_cfg.ru_operating_bw ? sector_cfg.ru_operating_bw.value() : sector_cfg.bw; ofh_sector_config.prach_eaxc = sector_cfg.prach_eaxc; ofh_sector_config.dl_eaxc = sector_cfg.dl_eaxc; diff --git a/lib/scheduler/config/serving_cell_config_factory.cpp b/lib/scheduler/config/serving_cell_config_factory.cpp index 48101ddb05..468a8e03c9 100644 --- a/lib/scheduler/config/serving_cell_config_factory.cpp +++ b/lib/scheduler/config/serving_cell_config_factory.cpp @@ -350,10 +350,13 @@ srsran::config_helpers::make_default_ul_config_common(const cell_config_builder_ cfg.freq_info_ul.freq_band_list.back().band = *params.band; cfg.init_ul_bwp.generic_params = make_default_init_bwp(params); cfg.init_ul_bwp.rach_cfg_common.emplace(); - cfg.init_ul_bwp.rach_cfg_common->rach_cfg_generic.prach_config_index = 1; + cfg.init_ul_bwp.rach_cfg_common->rach_cfg_generic.zero_correlation_zone_config = 15; + cfg.init_ul_bwp.rach_cfg_common->rach_cfg_generic.prach_config_index = 16; if (band_helper::get_duplex_mode(params.band.value()) == duplex_mode::TDD) { - optional idx_found = - prach_helper::find_valid_prach_config_index(params.scs_common, *params.tdd_ul_dl_cfg_common); + optional idx_found = prach_helper::find_valid_prach_config_index( + params.scs_common, + cfg.init_ul_bwp.rach_cfg_common->rach_cfg_generic.zero_correlation_zone_config, + *params.tdd_ul_dl_cfg_common); srsran_assert(idx_found.has_value(), "Unable to find a PRACH config index for the given TDD pattern"); cfg.init_ul_bwp.rach_cfg_common->rach_cfg_generic.prach_config_index = idx_found.value(); } @@ -377,8 +380,8 @@ srsran::config_helpers::make_default_ul_config_common(const cell_config_builder_ cfg.init_ul_bwp.rach_cfg_common->msg3_transform_precoder = false; cfg.init_ul_bwp.rach_cfg_common->rach_cfg_generic.msg1_fdm = 1; // Add +3 PRBS to the MSG1 frequency start, which act as a guardband between the PUCCH and PRACH. - cfg.init_ul_bwp.rach_cfg_common->rach_cfg_generic.msg1_frequency_start = 6; - cfg.init_ul_bwp.rach_cfg_common->rach_cfg_generic.zero_correlation_zone_config = 15; + cfg.init_ul_bwp.rach_cfg_common->rach_cfg_generic.msg1_frequency_start = 6; + cfg.init_ul_bwp.rach_cfg_common->rach_cfg_generic.ra_resp_window = 10U << to_numerology_value(params.scs_common); cfg.init_ul_bwp.rach_cfg_common->rach_cfg_generic.preamble_rx_target_pw = -100; cfg.init_ul_bwp.pusch_cfg_common.emplace(); diff --git a/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp b/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp index b99bcb9267..031cd87518 100644 --- a/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp +++ b/lib/scheduler/uci_scheduling/uci_allocator_impl.cpp @@ -244,9 +244,11 @@ uci_allocation uci_allocator_impl::alloc_uci_harq_ue(cell_resource_allocator& } if (csi_helper::is_csi_reporting_slot(ue_cell_cfg.cfg_dedicated(), uci_slot)) { - // NOTE: For TX with more than 2 antenna, the reported CSI is 11 bit, so we avoid multiplexing HARQ-ACK with CSI - // in the slots for CSI. - if (cell_cfg.dl_carrier.nof_ant > 2U) { + // NOTE: For TX with more than 1 antenna, we avoid multiplexing HARQ-ACK with CSI in the slots for CSI for the + // following reasons: + // - The multiplexing does not work well with the current implementation of PUCCH allocator. + // - For MIMO 4x4, the CSI report is 11 bit, and the current PUCCH F2 capacity is exactly 11 bits. + if (cell_cfg.dl_carrier.nof_ant > 1U) { continue; } // NOTE: This is only to avoid allocating more than 2 HARQ bits in PUCCH that are expected to carry CSI reporting. diff --git a/tests/unittests/fapi_adaptor/phy/messages/ul_pusch_pdu_test.cpp b/tests/unittests/fapi_adaptor/phy/messages/ul_pusch_pdu_test.cpp index ac63531904..9afc15cc9b 100644 --- a/tests/unittests/fapi_adaptor/phy/messages/ul_pusch_pdu_test.cpp +++ b/tests/unittests/fapi_adaptor/phy/messages/ul_pusch_pdu_test.cpp @@ -98,6 +98,6 @@ TEST(fapi_phy_ul_pusch_adaptor_test, valid_pdu_pass) ASSERT_EQ(fapi_pdu.pusch_data.rv_index, phy_pdu.codeword.value().rv); ASSERT_EQ(fapi_pdu.pusch_data.new_data, phy_pdu.codeword.value().new_data); ASSERT_EQ(fapi_pdu.pusch_maintenance_v3.ldpc_base_graph, phy_pdu.codeword.value().ldpc_base_graph); - ASSERT_EQ(fapi_pdu.pusch_data.tb_size.value(), pdu.tb_size); + ASSERT_EQ(fapi_pdu.pusch_data.tb_size.value(), pdu.tb_size.value()); ASSERT_EQ(fapi_pdu.pusch_data.harq_process_id, pdu.harq_id); } diff --git a/tests/unittests/rlc/rlc_tx_am_test.cpp b/tests/unittests/rlc/rlc_tx_am_test.cpp index 00c998ea27..457522bccb 100644 --- a/tests/unittests/rlc/rlc_tx_am_test.cpp +++ b/tests/unittests/rlc/rlc_tx_am_test.cpp @@ -100,6 +100,7 @@ class rlc_tx_am_test : public ::testing::Test, public ::testing::WithParamInterf config.poll_pdu = 4; config.poll_byte = 25; config.max_window = 0; + config.queue_size = 4096; // Create test frame tester = std::make_unique(config.sn_field_length); diff --git a/tests/unittests/rlc/rlc_um_test.cpp b/tests/unittests/rlc/rlc_um_test.cpp index f62387f53d..8bfda09877 100644 --- a/tests/unittests/rlc/rlc_um_test.cpp +++ b/tests/unittests/rlc/rlc_um_test.cpp @@ -92,6 +92,7 @@ class rlc_um_test : public ::testing::Test, public ::testing::WithParamInterface // Set Tx config config.tx.sn_field_length = sn_size; + config.tx.queue_size = 4096; // Create RLC entities rlc1 = std::make_unique(du_ue_index_t::MIN_DU_UE_INDEX,