From e70b8c247219a7a4d3cf42f5181637337d13f2ef Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 23 Jun 2021 18:11:11 +0100 Subject: [PATCH 01/43] sched,bugfix: fix SI scheduler logging --- srsenb/src/stack/mac/sched_carrier.cc | 4 ++-- .../src/stack/mac/sched_phy_ch/sched_dci.cc | 23 ++++++++++--------- srsenb/src/stack/rrc/rrc.cc | 2 +- srsenb/src/stack/rrc/rrc_nr.cc | 4 +++- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/srsenb/src/stack/mac/sched_carrier.cc b/srsenb/src/stack/mac/sched_carrier.cc index f4b79efa6..ab13122e7 100644 --- a/srsenb/src/stack/mac/sched_carrier.cc +++ b/srsenb/src/stack/mac/sched_carrier.cc @@ -124,8 +124,8 @@ void bc_sched::alloc_sibs(sf_sched* tti_sched) } } if (ret != alloc_result::success) { - logger.warning("SCHED: Could not allocate SIB=%d, len=%d. Cause: %s", - sib_idx + 1, + logger.warning("SCHED: Could not allocate SI message, idx=%d, len=%d. Cause: %s", + sib_idx, cc_cfg->cfg.sibs[sib_idx].len, to_string(ret)); } diff --git a/srsenb/src/stack/mac/sched_phy_ch/sched_dci.cc b/srsenb/src/stack/mac/sched_phy_ch/sched_dci.cc index 3756b9438..3e964082b 100644 --- a/srsenb/src/stack/mac/sched_phy_ch/sched_dci.cc +++ b/srsenb/src/stack/mac/sched_phy_ch/sched_dci.cc @@ -334,17 +334,18 @@ void log_broadcast_allocation(const sched_interface::dl_sched_bc_t& bc, fmt::format_to(str_buffer, "{}", rbg_range); if (bc.type == sched_interface::dl_sched_bc_t::bc_type::BCCH) { - get_mac_logger().debug("SCHED: SIB%d, cc=%d, rbgs=(%d,%d), dci=(%d,%d), rv=%d, len=%d, period=%d, mcs=%d", - bc.index + 1, - cell_params.enb_cc_idx, - rbg_range.start(), - rbg_range.stop(), - bc.dci.location.L, - bc.dci.location.ncce, - bc.dci.tb[0].rv, - cell_params.cfg.sibs[bc.index].len, - cell_params.cfg.sibs[bc.index].period_rf, - bc.dci.tb[0].mcs_idx); + get_mac_logger().debug( + "SCHED: SI message, cc=%d, idx=%d, rbgs=(%d,%d), dci=(%d,%d), rv=%d, len=%d, period=%d, mcs=%d", + bc.index, + cell_params.enb_cc_idx, + rbg_range.start(), + rbg_range.stop(), + bc.dci.location.L, + bc.dci.location.ncce, + bc.dci.tb[0].rv, + cell_params.cfg.sibs[bc.index].len, + cell_params.cfg.sibs[bc.index].period_rf, + bc.dci.tb[0].mcs_idx); } else { get_mac_logger().info("SCHED: PCH, cc=%d, rbgs=%s, dci=(%d,%d), tbs=%d, mcs=%d", cell_params.enb_cc_idx, diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index a82cde2d0..9eb276698 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -756,7 +756,7 @@ uint32_t rrc::generate_sibs() if (msg[msg_index].msg.c1().type().value != asn1::rrc::bcch_dl_sch_msg_type_c::c1_c_::types_opts::sib_type1) { msg_str = msg[msg_index].msg.c1().sys_info().crit_exts.type().to_string(); } - fmt::format_to(membuf, "{}, cc={}", msg_str, cc_idx); + fmt::format_to(membuf, "{}, cc={}, idx={}", msg_str, cc_idx, msg_index); log_broadcast_rrc_message(SRSRAN_SIRNTI, *cell_ctxt->sib_buffer.back(), msg[msg_index], srsran::to_c_str(membuf)); } diff --git a/srsenb/src/stack/rrc/rrc_nr.cc b/srsenb/src/stack/rrc/rrc_nr.cc index 143edd1a4..b8c0f407d 100644 --- a/srsenb/src/stack/rrc/rrc_nr.cc +++ b/srsenb/src/stack/rrc/rrc_nr.cc @@ -264,7 +264,9 @@ int32_t rrc_nr::generate_sibs() sib_buffer.push_back(std::move(sib)); // Log SIBs in JSON format - log_rrc_message("SIB payload", Tx, sib_buffer.back().get(), msg[msg_index]); + fmt::memory_buffer strbuf; + fmt::format_to(strbuf, "SI message={} payload", msg_index); + log_rrc_message(fmt::to_string(strbuf), Tx, sib_buffer.back().get(), msg[msg_index]); } nof_si_messages = sib_buffer.size() - 1; From e2c496d8254ba0cda777e5828c8a0571b4cb7c3c Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 23 Jun 2021 10:56:31 +0200 Subject: [PATCH 02/43] srsue,mac: fix race between PHY and MAC when stopping UE the issue let to unwanted log warning at the end of the UE execution when the PHY was still pushing DL PDUs while MAC was already stopped. This fixes #3003 --- srsue/hdr/stack/mac/mac.h | 2 +- srsue/src/stack/mac/mac.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/srsue/hdr/stack/mac/mac.h b/srsue/hdr/stack/mac/mac.h index 044e5a478..66bd0c0ca 100644 --- a/srsue/hdr/stack/mac/mac.h +++ b/srsue/hdr/stack/mac/mac.h @@ -158,7 +158,7 @@ private: mac_metrics_t metrics[SRSRAN_MAX_CARRIERS] = {}; - bool initialized = false; + std::atomic initialized = {false}; const uint8_t PCELL_CC_IDX = 0; }; diff --git a/srsue/src/stack/mac/mac.cc b/srsue/src/stack/mac/mac.cc index dcd504949..ecd283490 100644 --- a/srsue/src/stack/mac/mac.cc +++ b/srsue/src/stack/mac/mac.cc @@ -473,11 +473,11 @@ void mac::process_pdus() // dispatch work to stack thread auto ret = stack_task_dispatch_queue.try_push([this]() { bool have_data = true; - while (initialized and have_data) { + while (initialized.load(std::memory_order_relaxed) and have_data) { have_data = demux_unit.process_pdus(); } }); - if (ret.is_error()) { + if (ret.is_error() && initialized.load(std::memory_order_relaxed)) { Warning("Failed to dispatch mac::%s task to stack thread", __func__); } } From d1d8500ce5df66111e711059c76e21c8bc7997e4 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Wed, 5 May 2021 15:41:12 +0200 Subject: [PATCH 03/43] Add testcase for reconfiguration --- .../srsran/interfaces/ue_rrc_interfaces.h | 4 +- lib/src/asn1/rrc_nr_utils.cc | 2 +- lib/src/upper/rlc.cc | 2 + srsue/hdr/stack/rrc/rrc_nr.h | 27 ++- srsue/src/stack/rrc/rrc_nr.cc | 30 +-- srsue/src/stack/rrc/test/rrc_meas_test.cc | 4 +- srsue/src/stack/rrc/test/ue_rrc_nr_test.cc | 181 +++++++++++++++++- 7 files changed, 212 insertions(+), 38 deletions(-) diff --git a/lib/include/srsran/interfaces/ue_rrc_interfaces.h b/lib/include/srsran/interfaces/ue_rrc_interfaces.h index f26d98ae4..c4f20d2c8 100644 --- a/lib/include/srsran/interfaces/ue_rrc_interfaces.h +++ b/lib/include/srsran/interfaces/ue_rrc_interfaces.h @@ -100,8 +100,8 @@ public: class rrc_nr_interface_rrc { public: - virtual void get_eutra_nr_capabilities(srsran::byte_buffer_t* eutra_nr_caps) = 0; - virtual void get_nr_capabilities(srsran::byte_buffer_t* nr_cap) = 0; + virtual int get_eutra_nr_capabilities(srsran::byte_buffer_t* eutra_nr_caps) = 0; + virtual int get_nr_capabilities(srsran::byte_buffer_t* nr_cap) = 0; virtual void phy_set_cells_to_meas(uint32_t carrier_freq_r15) = 0; virtual void phy_meas_stop() = 0; virtual bool rrc_reconfiguration(bool endc_release_and_add_r15, diff --git a/lib/src/asn1/rrc_nr_utils.cc b/lib/src/asn1/rrc_nr_utils.cc index 71746d106..ca5021b80 100644 --- a/lib/src/asn1/rrc_nr_utils.cc +++ b/lib/src/asn1/rrc_nr_utils.cc @@ -111,7 +111,7 @@ rlc_config_t make_rlc_config_t(const rlc_cfg_c& asn1_type) case rlc_cfg_c::types_opts::um_uni_dir_dl: case rlc_cfg_c::types_opts::um_uni_dir_ul: rlc_cfg.rlc_mode = rlc_mode_t::um; - rlc_cfg.um_nr.t_reassembly_ms = asn1_type.um_bi_dir().dl_um_rlc.t_reassembly.value; + rlc_cfg.um_nr.t_reassembly_ms = asn1_type.um_bi_dir().dl_um_rlc.t_reassembly.value.to_number(); rlc_cfg.um_nr.sn_field_length = (rlc_um_nr_sn_size_t)asn1_type.um_bi_dir().dl_um_rlc.sn_field_len.value; rlc_cfg.um_nr.mod = (rlc_cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size6bits) ? 64 : 4096; rlc_cfg.um_nr.UM_Window_Size = (rlc_cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size6bits) ? 32 : 2048; diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index d24dae789..8f71b0fa0 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -464,6 +464,8 @@ void rlc::add_bearer(uint32_t lcid, const rlc_config_t& cnfg) logger.info("Added %s radio bearer with LCID %d in %s", to_string(cnfg.rat), lcid, to_string(cnfg.rlc_mode)); rlc_entity = NULL; + } else { + logger.info("LCID %d already exists", lcid); } // configure and add to array diff --git a/srsue/hdr/stack/rrc/rrc_nr.h b/srsue/hdr/stack/rrc/rrc_nr.h index 6cd4db138..5e4f3e6ff 100644 --- a/srsue/hdr/stack/rrc/rrc_nr.h +++ b/srsue/hdr/stack/rrc/rrc_nr.h @@ -62,16 +62,16 @@ public: rrc_nr(srsran::task_sched_handle task_sched_); ~rrc_nr(); - void init(phy_interface_rrc_nr* phy_, - mac_interface_rrc_nr* mac_, - rlc_interface_rrc* rlc_, - pdcp_interface_rrc* pdcp_, - gw_interface_rrc* gw_, - rrc_eutra_interface_rrc_nr* rrc_eutra_, - usim_interface_rrc_nr* usim_, - srsran::timer_handler* timers_, - stack_interface_rrc* stack_, - const rrc_nr_args_t& args_); + int init(phy_interface_rrc_nr* phy_, + mac_interface_rrc_nr* mac_, + rlc_interface_rrc* rlc_, + pdcp_interface_rrc* pdcp_, + gw_interface_rrc* gw_, + rrc_eutra_interface_rrc_nr* rrc_eutra_, + usim_interface_rrc_nr* usim_, + srsran::timer_handler* timers_, + stack_interface_rrc* stack_, + const rrc_nr_args_t& args_); void stop(); void init_core_less(); @@ -118,8 +118,8 @@ public: void notify_pdcp_integrity_error(uint32_t lcid) final; // RRC (LTE) interface - void get_eutra_nr_capabilities(srsran::byte_buffer_t* eutra_nr_caps); - void get_nr_capabilities(srsran::byte_buffer_t* eutra_nr_caps); + int get_eutra_nr_capabilities(srsran::byte_buffer_t* eutra_nr_caps); + int get_nr_capabilities(srsran::byte_buffer_t* eutra_nr_caps); void phy_meas_stop(); void phy_set_cells_to_meas(uint32_t carrier_freq_r15); bool rrc_reconfiguration(bool endc_release_and_add_r15, @@ -175,9 +175,6 @@ private: rrc_nr_args_t args = {}; - // RRC constants and timers - srsran::timer_handler* timers = nullptr; - const char* get_rb_name(uint32_t lcid) final; bool add_lcid_drb(uint32_t lcid, uint32_t drb_id); diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index ad9ddebba..01a5bb5c5 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -35,16 +35,16 @@ rrc_nr::rrc_nr(srsran::task_sched_handle task_sched_) : rrc_nr::~rrc_nr() = default; -void rrc_nr::init(phy_interface_rrc_nr* phy_, - mac_interface_rrc_nr* mac_, - rlc_interface_rrc* rlc_, - pdcp_interface_rrc* pdcp_, - gw_interface_rrc* gw_, - rrc_eutra_interface_rrc_nr* rrc_eutra_, - usim_interface_rrc_nr* usim_, - srsran::timer_handler* timers_, - stack_interface_rrc* stack_, - const rrc_nr_args_t& args_) +int rrc_nr::init(phy_interface_rrc_nr* phy_, + mac_interface_rrc_nr* mac_, + rlc_interface_rrc* rlc_, + pdcp_interface_rrc* pdcp_, + gw_interface_rrc* gw_, + rrc_eutra_interface_rrc_nr* rrc_eutra_, + usim_interface_rrc_nr* usim_, + srsran::timer_handler* timers_, + stack_interface_rrc* stack_, + const rrc_nr_args_t& args_) { phy = phy_; rlc = rlc_; @@ -53,12 +53,12 @@ void rrc_nr::init(phy_interface_rrc_nr* phy_, mac = mac_; rrc_eutra = rrc_eutra_; usim = usim_; - timers = timers_; stack = stack_; args = args_; running = true; sim_measurement_timer = task_sched.get_unique_timer(); + return SRSRAN_SUCCESS; } void rrc_nr::stop() @@ -208,7 +208,7 @@ void rrc_nr::write_pdu_pcch(srsran::unique_byte_buffer_t pdu) {} void rrc_nr::write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) {} void rrc_nr::notify_pdcp_integrity_error(uint32_t lcid) {} -void rrc_nr::get_eutra_nr_capabilities(srsran::byte_buffer_t* eutra_nr_caps_pdu) +int rrc_nr::get_eutra_nr_capabilities(srsran::byte_buffer_t* eutra_nr_caps_pdu) { struct ue_mrdc_cap_s mrdc_cap; @@ -334,7 +334,7 @@ void rrc_nr::get_eutra_nr_capabilities(srsran::byte_buffer_t* eutra_nr_caps_pdu) logger.debug( eutra_nr_caps_pdu->msg, eutra_nr_caps_pdu->N_bytes, "EUTRA-NR capabilities (%u B)", eutra_nr_caps_pdu->N_bytes); - return; + return SRSRAN_SUCCESS; } bool rrc_nr::rrc_reconfiguration(bool endc_release_and_add_r15, @@ -361,7 +361,7 @@ bool rrc_nr::rrc_reconfiguration(bool endc_release_and_add_r15, return true; } -void rrc_nr::get_nr_capabilities(srsran::byte_buffer_t* nr_caps_pdu) +int rrc_nr::get_nr_capabilities(srsran::byte_buffer_t* nr_caps_pdu) { struct ue_nr_cap_s nr_cap; @@ -404,7 +404,7 @@ void rrc_nr::get_nr_capabilities(srsran::byte_buffer_t* nr_caps_pdu) #endif logger.debug(nr_caps_pdu->msg, nr_caps_pdu->N_bytes, "NR capabilities (%u B)", nr_caps_pdu->N_bytes); - return; + return SRSRAN_SUCCESS; }; void rrc_nr::phy_meas_stop() diff --git a/srsue/src/stack/rrc/test/rrc_meas_test.cc b/srsue/src/stack/rrc/test/rrc_meas_test.cc index 60ae59593..7c3756d58 100644 --- a/srsue/src/stack/rrc/test/rrc_meas_test.cc +++ b/srsue/src/stack/rrc/test/rrc_meas_test.cc @@ -167,8 +167,8 @@ class rrc_nr_test final : public srsue::rrc_nr_interface_rrc { public: ~rrc_nr_test() = default; - void get_eutra_nr_capabilities(srsran::byte_buffer_t* eutra_nr_caps) override{}; - void get_nr_capabilities(srsran::byte_buffer_t* nr_cap) override{}; + int get_eutra_nr_capabilities(srsran::byte_buffer_t* eutra_nr_caps) override { return SRSRAN_SUCCESS; }; + int get_nr_capabilities(srsran::byte_buffer_t* nr_cap) override { return SRSRAN_SUCCESS; }; void phy_set_cells_to_meas(uint32_t carrier_freq_r15) override{}; void phy_meas_stop() override{}; bool rrc_reconfiguration(bool endc_release_and_add_r15, diff --git a/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc b/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc index 7539d4369..001589824 100644 --- a/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc +++ b/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc @@ -11,26 +11,201 @@ */ #include "srsran/common/test_common.h" +#include "srsran/interfaces/ue_gw_interfaces.h" +#include "srsran/interfaces/ue_interfaces.h" +#include "srsran/interfaces/ue_pdcp_interfaces.h" +#include "srsran/interfaces/ue_rlc_interfaces.h" +#include "srsran/interfaces/ue_usim_interfaces.h" #include "srsue/hdr/stack/rrc/rrc_nr.h" using namespace srsue; +class dummy_phy : public phy_interface_rrc_nr +{ + bool set_config(const srsran::phy_cfg_nr_t& cfg) { return true; } +}; + +class dummy_mac : public mac_interface_rrc_nr +{ + int setup_lcid(const srsran::logical_channel_config_t& config) { return SRSRAN_SUCCESS; } + int set_config(const srsran::bsr_cfg_nr_t& bsr_cfg) { return SRSRAN_SUCCESS; } + int set_config(const srsran::sr_cfg_nr_t& sr_cfg) { return SRSRAN_SUCCESS; } + int set_config(const srsran::dl_harq_cfg_nr_t& dl_hrq_cfg) { return SRSRAN_SUCCESS; } + void set_config(const srsran::rach_nr_cfg_t& rach_cfg) {} + int add_tag_config(const srsran::tag_cfg_nr_t& tag_cfg) { return SRSRAN_SUCCESS; } + int set_config(const srsran::phr_cfg_nr_t& phr_cfg) { return SRSRAN_SUCCESS; } + int remove_tag_config(const uint32_t tag_id) { return SRSRAN_SUCCESS; } + + void start_ra_procedure() {} + + void set_contention_id(const uint64_t ue_identity){}; + + bool set_crnti(const uint16_t crnti) { return true; }; +}; + +class dummy_rlc : public rlc_interface_rrc +{ + void reset() {} + void reestablish() {} + void reestablish(uint32_t lcid) {} + void add_bearer(uint32_t lcid, const srsran::rlc_config_t& cnfg) {} + void add_bearer_mrb(uint32_t lcid) {} + void del_bearer(uint32_t lcid) {} + void suspend_bearer(uint32_t lcid) {} + void resume_bearer(uint32_t lcid) {} + void change_lcid(uint32_t old_lcid, uint32_t new_lcid) {} + bool has_bearer(uint32_t lcid) { return true; } + bool has_data(const uint32_t lcid) { return true; } + bool is_suspended(const uint32_t lcid) { return true; } + void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) {} +}; + +class dummy_pdcp : public pdcp_interface_rrc +{ + void reestablish(){}; + void reestablish(uint32_t lcid){}; + void reset(){}; + void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu, int sn = -1){}; + void add_bearer(uint32_t lcid, srsran::pdcp_config_t cnfg){}; + void del_bearer(uint32_t lcid){}; + void change_lcid(uint32_t old_lcid, uint32_t new_lcid){}; + void config_security(uint32_t lcid, const srsran::as_security_config_t& sec_cfg){}; + void config_security_all(const srsran::as_security_config_t& sec_cfg){}; + void enable_integrity(uint32_t lcid, srsran::srsran_direction_t direction){}; + void enable_encryption(uint32_t lcid, + srsran::srsran_direction_t direction = srsran::srsran_direction_t::DIRECTION_TXRX){}; + void send_status_report(){}; + void send_status_report(uint32_t lcid){}; +}; + +class dummy_gw : public gw_interface_rrc +{ + void add_mch_port(uint32_t lcid, uint32_t port){}; + int update_lcid(uint32_t eps_bearer_id, uint32_t new_lcid) { return SRSRAN_SUCCESS; }; + bool is_running() { return true; }; +}; + +class dummy_eutra : public rrc_eutra_interface_rrc_nr +{ + void new_cell_meas_nr(const std::vector& meas){}; + void nr_rrc_con_reconfig_complete(bool status){}; + void nr_notify_reconfiguration_failure(){}; + void nr_scg_failure_information(const srsran::scg_failure_cause_t cause){}; +}; + +class dummy_sim : public usim_interface_rrc_nr +{ + bool generate_nr_context(uint16_t sk_counter, srsran::as_security_config_t* sec_cfg) { return true; } + bool update_nr_context(srsran::as_security_config_t* sec_cfg) { return true; } +}; + +class dummy_stack : public stack_interface_rrc +{ + srsran::tti_point get_current_tti() { return srsran::tti_point(); }; +}; + int rrc_nr_cap_request_test() { - srslog::basic_logger& logger = srslog::fetch_basic_logger("RRC"); + srslog::init(); + srslog::basic_logger& logger = srslog::fetch_basic_logger("RRC-NR"); logger.set_level(srslog::basic_levels::debug); logger.set_hex_dump_max_size(-1); srsran::task_scheduler task_sched{512, 100}; srsran::task_sched_handle task_sched_handle(&task_sched); rrc_nr rrc_nr(task_sched_handle); srsran::byte_buffer_t caps; - rrc_nr.get_eutra_nr_capabilities(&caps); - rrc_nr.get_nr_capabilities(&caps); + + dummy_phy dummy_phy; + dummy_mac dummy_mac; + dummy_rlc dummy_rlc; + dummy_pdcp dummy_pdcp; + dummy_gw dummy_gw; + dummy_eutra dummy_eutra; + dummy_sim dummy_sim; + dummy_stack dummy_stack; + rrc_nr_args_t rrc_nr_args; + + rrc_nr_args.supported_bands_eutra.push_back(7); + rrc_nr_args.supported_bands_nr.push_back(78); + + TESTASSERT(rrc_nr.init(&dummy_phy, + &dummy_mac, + &dummy_rlc, + &dummy_pdcp, + &dummy_gw, + &dummy_eutra, + &dummy_sim, + task_sched.get_timer_handler(), + &dummy_stack, + rrc_nr_args) == SRSRAN_SUCCESS); + + TESTASSERT(rrc_nr.get_eutra_nr_capabilities(&caps) == SRSRAN_SUCCESS); + TESTASSERT(rrc_nr.get_nr_capabilities(&caps) == SRSRAN_SUCCESS); + return SRSRAN_SUCCESS; +} + +int rrc_nr_reconfig_test() +{ + srslog::init(); + srslog::basic_logger& logger = srslog::fetch_basic_logger("RRC-NR"); + logger.set_level(srslog::basic_levels::debug); + logger.set_hex_dump_max_size(-1); + srsran::task_scheduler task_sched{512, 100}; + srsran::task_sched_handle task_sched_handle(&task_sched); + rrc_nr rrc_nr(task_sched_handle); + + dummy_phy dummy_phy; + dummy_mac dummy_mac; + dummy_rlc dummy_rlc; + dummy_pdcp dummy_pdcp; + dummy_gw dummy_gw; + dummy_eutra dummy_eutra; + dummy_sim dummy_sim; + dummy_stack dummy_stack; + rrc_nr_args_t rrc_nr_args; + TESTASSERT(rrc_nr.init(&dummy_phy, + &dummy_mac, + &dummy_rlc, + &dummy_pdcp, + &dummy_gw, + &dummy_eutra, + &dummy_sim, + task_sched.get_timer_handler(), + &dummy_stack, + rrc_nr_args) == SRSRAN_SUCCESS); + + uint8_t nr_secondary_cell_group_cfg_r15_bytes[] = { + 0x08, 0x81, 0x19, 0x5c, 0x40, 0xb1, 0x42, 0x7e, 0x08, 0x30, 0xf3, 0x20, 0x3e, 0x00, 0x80, 0x34, 0x1e, 0x00, 0x80, + 0x02, 0xe8, 0x5b, 0x98, 0xc0, 0x06, 0x93, 0x5a, 0x40, 0x04, 0xd2, 0x6b, 0x00, 0x00, 0x00, 0x00, 0xcd, 0x8d, 0xb2, + 0x45, 0xe2, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x1b, 0x82, 0x21, 0x00, 0x00, 0x44, 0x04, 0x00, 0xd0, + 0x1a, 0xe2, 0x00, 0x00, 0x01, 0x98, 0x71, 0xb6, 0x48, 0x95, 0x00, 0x20, 0x07, 0xb7, 0x25, 0x58, 0xf0, 0x00, 0x00, + 0x13, 0x8c, 0x21, 0xb8, 0x83, 0x69, 0x92, 0xa0, 0xb8, 0x75, 0x01, 0x08, 0x1c, 0x0c, 0x00, 0x30, 0x78, 0x00, 0x03, + 0x49, 0xa9, 0xe0, 0x07, 0xb7, 0x25, 0x58, 0x00, 0x25, 0x06, 0xa0, 0x00, 0x80, 0xe0, 0x12, 0xd8, 0x0c, 0x88, 0x03, + 0x70, 0x84, 0x20, 0x00, 0x11, 0x11, 0x6d, 0x00, 0x00, 0x00, 0x12, 0x08, 0x00, 0x00, 0x83, 0xa6, 0x02, 0x66, 0xaa, + 0xe9, 0x28, 0x38, 0x00, 0x20, 0x81, 0x84, 0x0a, 0x18, 0x39, 0x38, 0x81, 0x22, 0x85, 0x8c, 0x1a, 0x38, 0x78, 0xfc, + 0x00, 0x00, 0x66, 0x02, 0x18, 0x10, 0x00, 0xcc, 0x04, 0xb0, 0x40, 0x01, 0x98, 0x0a, 0x60, 0xc0, 0x03, 0x30, 0x16, + 0xc2, 0x00, 0x06, 0x60, 0x31, 0x85, 0x00, 0x0c, 0xc0, 0x6b, 0x0c, 0x00, 0x19, 0x80, 0xe6, 0x1c, 0x00, 0x33, 0x21, + 0x40, 0x31, 0x00, 0x01, 0x72, 0x58, 0x62, 0x40, 0x02, 0xe4, 0xb2, 0xc5, 0x00, 0x05, 0xc9, 0x69, 0x8b, 0x00, 0x0b, + 0x92, 0xdb, 0x18, 0x00, 0x17, 0x25, 0xc6, 0x34, 0x00, 0x2e, 0x4b, 0xac, 0x70, 0x00, 0x5c, 0x97, 0x98, 0xf0, 0x00, + 0xcd, 0x85, 0x07, 0x95, 0xe5, 0x79, 0x43, 0x01, 0xe4, 0x07, 0x23, 0x45, 0x67, 0x89, 0x7d, 0x42, 0x10, 0x84, 0x00, + 0x0c, 0xd0, 0x1a, 0x41, 0x07, 0x82, 0xb8, 0x03, 0x04, 0x28, 0x01, 0x63, 0xff, 0x4a, 0x52, 0x63, 0x18, 0xdc, 0xa0, + 0x50, 0x00, 0x08, 0x72, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x12, 0x00, 0x00, 0x00, 0x04, 0x8a, 0x80}; + + asn1::dyn_octstring nr_secondary_cell_group_cfg_r15; + nr_secondary_cell_group_cfg_r15.resize(sizeof(nr_secondary_cell_group_cfg_r15_bytes)); + memcpy(nr_secondary_cell_group_cfg_r15.data(), + nr_secondary_cell_group_cfg_r15_bytes, + sizeof(nr_secondary_cell_group_cfg_r15_bytes)); + + asn1::dyn_octstring nr_radio_bearer_cfg1_r15; + rrc_nr.rrc_reconfiguration(true, true, nr_secondary_cell_group_cfg_r15, false, 0, false, nr_radio_bearer_cfg1_r15); + task_sched.run_pending_tasks(); return SRSRAN_SUCCESS; } int main(int argc, char** argv) { TESTASSERT(rrc_nr_cap_request_test() == SRSRAN_SUCCESS); + TESTASSERT(rrc_nr_reconfig_test() == SRSRAN_SUCCESS); return SRSRAN_SUCCESS; } From 6d5391756cbbf57ef92487da85e75753ecd66f68 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Wed, 5 May 2021 13:06:52 +0200 Subject: [PATCH 04/43] Refactor build of RLC NR config --- lib/include/srsran/asn1/rrc_nr_utils.h | 2 +- .../srsran/interfaces/rlc_interface_types.h | 6 --- lib/include/srsran/upper/rlc_um_nr.h | 6 +++ lib/src/asn1/rrc_nr_utils.cc | 40 ++++++++++++++----- lib/src/upper/rlc_um_nr.cc | 30 ++++++-------- lib/test/asn1/rrc_nr_utils_test.cc | 4 +- srsue/src/stack/rrc/rrc_nr.cc | 13 +----- 7 files changed, 55 insertions(+), 46 deletions(-) diff --git a/lib/include/srsran/asn1/rrc_nr_utils.h b/lib/include/srsran/asn1/rrc_nr_utils.h index c3a3d6237..398f79f8c 100644 --- a/lib/include/srsran/asn1/rrc_nr_utils.h +++ b/lib/include/srsran/asn1/rrc_nr_utils.h @@ -120,7 +120,7 @@ bool make_mac_dl_harq_cfg_nr_t(const asn1::rrc_nr::pdsch_ser /*************************** * RLC Config **************************/ -rlc_config_t make_rlc_config_t(const asn1::rrc_nr::rlc_cfg_c& asn1_type); +int make_rlc_config_t(const asn1::rrc_nr::rlc_cfg_c& asn1_type, rlc_config_t* rlc_config_out); /*************************** * PDCP Config diff --git a/lib/include/srsran/interfaces/rlc_interface_types.h b/lib/include/srsran/interfaces/rlc_interface_types.h index 11c124ca5..e19766e0c 100644 --- a/lib/include/srsran/interfaces/rlc_interface_types.h +++ b/lib/include/srsran/interfaces/rlc_interface_types.h @@ -110,8 +110,6 @@ struct rlc_um_nr_config_t { ***************************************************************************/ rlc_um_nr_sn_size_t sn_field_length; // Number of bits used for sequence number - uint32_t UM_Window_Size; - uint32_t mod; // Rx/Tx counter modulus int32_t t_reassembly_ms; // Timer used by rx to detect PDU loss (ms) }; @@ -206,12 +204,8 @@ public: cnfg.rlc_mode = rlc_mode_t::um; if (sn_size == 6) { cnfg.um_nr.sn_field_length = rlc_um_nr_sn_size_t::size6bits; - cnfg.um_nr.UM_Window_Size = 32; - cnfg.um_nr.mod = 64; } else if (sn_size == 12) { cnfg.um_nr.sn_field_length = rlc_um_nr_sn_size_t::size12bits; - cnfg.um_nr.UM_Window_Size = 2048; - cnfg.um_nr.mod = 4096; } else { return {}; } diff --git a/lib/include/srsran/upper/rlc_um_nr.h b/lib/include/srsran/upper/rlc_um_nr.h index 6c5e4936e..11c6bd55c 100644 --- a/lib/include/srsran/upper/rlc_um_nr.h +++ b/lib/include/srsran/upper/rlc_um_nr.h @@ -62,6 +62,9 @@ private: uint32_t next_so = 0; // The segment offset for the next generated PDU + uint32_t UM_Window_Size; + uint32_t mod; // Rx counter modulus + static constexpr uint32_t head_len_full = 1; // full SDU header size is always uint32_t head_len_first = 0, head_len_segment = 0; // are computed during configure based on SN length @@ -96,6 +99,9 @@ private: uint32_t RX_Next_Highest = 0; // the SN following the SN of the UMD PDU with the highest SN among // received UMD PDUs. It serves as the higher edge of the reassembly window. + uint32_t UM_Window_Size; + uint32_t mod; // Rx counter modulus + // Rx window typedef struct { std::map segments; // Map of segments with SO as key diff --git a/lib/src/asn1/rrc_nr_utils.cc b/lib/src/asn1/rrc_nr_utils.cc index ca5021b80..d6cbd9165 100644 --- a/lib/src/asn1/rrc_nr_utils.cc +++ b/lib/src/asn1/rrc_nr_utils.cc @@ -100,26 +100,48 @@ rach_nr_cfg_t make_mac_rach_cfg(const rach_cfg_common_s& asn1_type) return rach_nr_cfg; }; -rlc_config_t make_rlc_config_t(const rlc_cfg_c& asn1_type) +int make_rlc_config_t(const rlc_cfg_c& asn1_type, rlc_config_t* cfg_out) { rlc_config_t rlc_cfg = rlc_config_t::default_rlc_um_nr_config(); rlc_cfg.rat = srsran_rat_t::nr; switch (asn1_type.type().value) { case rlc_cfg_c::types_opts::am: - break; + asn1::log_warning("NR RLC type %s is not supported", asn1_type.type().to_string()); + return SRSRAN_ERROR; case rlc_cfg_c::types_opts::um_bi_dir: - case rlc_cfg_c::types_opts::um_uni_dir_dl: - case rlc_cfg_c::types_opts::um_uni_dir_ul: rlc_cfg.rlc_mode = rlc_mode_t::um; - rlc_cfg.um_nr.t_reassembly_ms = asn1_type.um_bi_dir().dl_um_rlc.t_reassembly.value.to_number(); - rlc_cfg.um_nr.sn_field_length = (rlc_um_nr_sn_size_t)asn1_type.um_bi_dir().dl_um_rlc.sn_field_len.value; - rlc_cfg.um_nr.mod = (rlc_cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size6bits) ? 64 : 4096; - rlc_cfg.um_nr.UM_Window_Size = (rlc_cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size6bits) ? 32 : 2048; + rlc_cfg.um_nr.t_reassembly_ms = asn1_type.um_bi_dir().dl_um_rlc.t_reassembly.to_number(); + + if (asn1_type.um_bi_dir().dl_um_rlc.sn_field_len_present && + asn1_type.um_bi_dir().ul_um_rlc.sn_field_len_present && + asn1_type.um_bi_dir().dl_um_rlc.sn_field_len != asn1_type.um_bi_dir().ul_um_rlc.sn_field_len) { + asn1::log_warning("NR RLC sequence number length is not the same in uplink and downlink"); + return SRSRAN_ERROR; + } + + switch (asn1_type.um_bi_dir().dl_um_rlc.sn_field_len.value) { + case asn1::rrc_nr::sn_field_len_um_opts::options::size6: + rlc_cfg.um_nr.sn_field_length = rlc_um_nr_sn_size_t::size6bits; + break; + case asn1::rrc_nr::sn_field_len_um_opts::options::size12: + rlc_cfg.um_nr.sn_field_length = rlc_um_nr_sn_size_t::size12bits; + break; + default: + break; + } break; + case rlc_cfg_c::types_opts::um_uni_dir_dl: + asn1::log_warning("NR RLC type %s is not supported", asn1_type.type().to_string()); + return SRSRAN_ERROR; + case rlc_cfg_c::types_opts::um_uni_dir_ul: + asn1::log_warning("NR RLC type %s is not supported", asn1_type.type().to_string()); + return SRSRAN_ERROR; default: break; } - return rlc_cfg; + + *cfg_out = rlc_cfg; + return SRSRAN_SUCCESS; } srsran::pdcp_config_t make_drb_pdcp_config_t(const uint8_t bearer_id, bool is_ue, const pdcp_cfg_s& pdcp_cfg) diff --git a/lib/src/upper/rlc_um_nr.cc b/lib/src/upper/rlc_um_nr.cc index 1cf1aa4af..32fc1948d 100644 --- a/lib/src/upper/rlc_um_nr.cc +++ b/lib/src/upper/rlc_um_nr.cc @@ -14,7 +14,7 @@ #include "srsran/interfaces/ue_pdcp_interfaces.h" #include -#define RX_MOD_NR_BASE(x) (((x)-RX_Next_Highest - cfg.um_nr.UM_Window_Size) % cfg.um_nr.mod) +#define RX_MOD_NR_BASE(x) (((x)-RX_Next_Highest - UM_Window_Size) % mod) namespace srsran { @@ -94,10 +94,8 @@ bool rlc_um_nr::rlc_um_nr_tx::configure(const rlc_config_t& cnfg_, std::string r { cfg = cnfg_; - if (cfg.um_nr.mod == 0) { - logger.error("Error configuring %s RLC UM: tx_mod==0", rb_name.c_str()); - return false; - } + mod = (cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size6bits) ? 64 : 4096; + UM_Window_Size = (cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size6bits) ? 32 : 2048; // calculate header sizes for configured SN length rlc_um_nr_pdu_header_t header = {}; @@ -188,7 +186,7 @@ uint32_t rlc_um_nr::rlc_um_nr_tx::build_data_pdu(unique_byte_buffer_t pdu, uint8 // Update SN if needed if (header.si == rlc_nr_si_field_t::last_segment) { - TX_Next = (TX_Next + 1) % cfg.um_nr.mod; + TX_Next = (TX_Next + 1) % mod; next_so = 0; } @@ -229,10 +227,8 @@ rlc_um_nr::rlc_um_nr_rx::rlc_um_nr_rx(rlc_um_base* parent_) : bool rlc_um_nr::rlc_um_nr_rx::configure(const rlc_config_t& cnfg_, std::string rb_name_) { - if (cfg.um_nr.mod == 0) { - logger.error("Error configuring %s RLC UM: rx_mod==0", rb_name.c_str()); - return false; - } + mod = (cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size6bits) ? 64 : 4096; + UM_Window_Size = (cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size6bits) ? 32 : 2048; // check timer if (not reassembly_timer.is_valid()) { @@ -297,7 +293,7 @@ void rlc_um_nr::rlc_um_nr_rx::timer_expired(uint32_t timeout_id) // update RX_Next_Reassembly to the next SN that has not been reassembled yet RX_Next_Reassembly = RX_Timer_Trigger; while (RX_MOD_NR_BASE(RX_Next_Reassembly) < RX_MOD_NR_BASE(RX_Next_Highest)) { - RX_Next_Reassembly = (RX_Next_Reassembly + 1) % cfg.um_nr.mod; + RX_Next_Reassembly = (RX_Next_Reassembly + 1) % mod; debug_state(); } @@ -325,14 +321,14 @@ void rlc_um_nr::rlc_um_nr_rx::timer_expired(uint32_t timeout_id) // Sec 5.2.2.2.1 bool rlc_um_nr::rlc_um_nr_rx::sn_in_reassembly_window(const uint32_t sn) { - return (RX_MOD_NR_BASE(RX_Next_Highest - cfg.um_nr.UM_Window_Size) <= RX_MOD_NR_BASE(sn) && + return (RX_MOD_NR_BASE(RX_Next_Highest - UM_Window_Size) <= RX_MOD_NR_BASE(sn) && RX_MOD_NR_BASE(sn) < RX_MOD_NR_BASE(RX_Next_Highest)); } // Sec 5.2.2.2.2 bool rlc_um_nr::rlc_um_nr_rx::sn_invalid_for_rx_buffer(const uint32_t sn) { - return (RX_MOD_NR_BASE(RX_Next_Highest - cfg.um_nr.UM_Window_Size) <= RX_MOD_NR_BASE(sn) && + return (RX_MOD_NR_BASE(RX_Next_Highest - UM_Window_Size) <= RX_MOD_NR_BASE(sn) && RX_MOD_NR_BASE(sn) < RX_MOD_NR_BASE(RX_Next_Reassembly)); } @@ -414,9 +410,9 @@ void rlc_um_nr::rlc_um_nr_rx::handle_rx_buffer_update(const uint32_t sn) // find next SN in rx buffer if (sn == RX_Next_Reassembly) { - RX_Next_Reassembly = ((RX_Next_Reassembly + 1) % cfg.um_nr.mod); + RX_Next_Reassembly = ((RX_Next_Reassembly + 1) % mod); while (RX_MOD_NR_BASE(RX_Next_Reassembly) < RX_MOD_NR_BASE(RX_Next_Highest)) { - RX_Next_Reassembly = (RX_Next_Reassembly + 1) % cfg.um_nr.mod; + RX_Next_Reassembly = (RX_Next_Reassembly + 1) % mod; } logger.debug("Updating RX_Next_Reassembly=%d", RX_Next_Reassembly); } @@ -444,7 +440,7 @@ void rlc_um_nr::rlc_um_nr_rx::handle_rx_buffer_update(const uint32_t sn) logger.info("%s SN: %d outside rx window [%d:%d] - discarding", rb_name.c_str(), it->first, - RX_Next_Highest - cfg.um_nr.UM_Window_Size, + RX_Next_Highest - UM_Window_Size, RX_Next_Highest); it = rx_window.erase(it); metrics.num_lost_pdus++; @@ -456,7 +452,7 @@ void rlc_um_nr::rlc_um_nr_rx::handle_rx_buffer_update(const uint32_t sn) if (not sn_in_reassembly_window(RX_Next_Reassembly)) { // update RX_Next_Reassembly to first SN that has not been reassembled and delivered for (const auto& rx_pdu : rx_window) { - if (rx_pdu.first >= RX_MOD_NR_BASE(RX_Next_Highest - cfg.um_nr.UM_Window_Size)) { + if (rx_pdu.first >= RX_MOD_NR_BASE(RX_Next_Highest - UM_Window_Size)) { RX_Next_Reassembly = rx_pdu.first; logger.debug("Updating RX_Next_Reassembly=%d", RX_Next_Reassembly); break; diff --git a/lib/test/asn1/rrc_nr_utils_test.cc b/lib/test/asn1/rrc_nr_utils_test.cc index 7bea15aff..82c1431ff 100644 --- a/lib/test/asn1/rrc_nr_utils_test.cc +++ b/lib/test/asn1/rrc_nr_utils_test.cc @@ -34,10 +34,10 @@ int test_rlc_config() rlc_cfg_asn1.to_json(jw); srslog::fetch_basic_logger("RRC").info("RLC NR Config: \n %s", jw.to_string().c_str()); - rlc_config_t rlc_cfg = make_rlc_config_t(rlc_cfg_asn1); + rlc_config_t rlc_cfg; + TESTASSERT(make_rlc_config_t(rlc_cfg_asn1, &rlc_cfg) == SRSRAN_SUCCESS); TESTASSERT(rlc_cfg.rat == srsran_rat_t::nr); TESTASSERT(rlc_cfg.um_nr.sn_field_length == rlc_um_nr_sn_size_t::size12bits); - TESTASSERT(rlc_cfg.um_nr.UM_Window_Size == 2048); return SRSRAN_SUCCESS; } diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index 01a5bb5c5..18ee3375a 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -461,17 +461,8 @@ bool rrc_nr::apply_rlc_add_mod(const rlc_bearer_cfg_s& rlc_bearer_cfg) } if (rlc_bearer_cfg.rlc_cfg_present == true) { - rlc_cfg = srsran::make_rlc_config_t(rlc_bearer_cfg.rlc_cfg); - if (rlc_bearer_cfg.rlc_cfg.type() == asn1::rrc_nr::rlc_cfg_c::types::um_bi_dir) { - if (rlc_bearer_cfg.rlc_cfg.um_bi_dir().dl_um_rlc.sn_field_len_present && - rlc_bearer_cfg.rlc_cfg.um_bi_dir().ul_um_rlc.sn_field_len_present && - rlc_bearer_cfg.rlc_cfg.um_bi_dir().dl_um_rlc.sn_field_len != - rlc_bearer_cfg.rlc_cfg.um_bi_dir().ul_um_rlc.sn_field_len) { - logger.warning("NR RLC sequence number length is not the same in uplink and downlink"); - return false; - } - } else { - logger.warning("NR RLC type is not unacknowledged mode bidirectional"); + if (srsran::make_rlc_config_t(rlc_bearer_cfg.rlc_cfg, &rlc_cfg) != SRSRAN_SUCCESS) { + logger.warning("Failed to build RLC config"); return false; } } else { From 7113e55d53bfef6645156afbf5ce838d5f02776f Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 6 May 2021 15:24:05 +0200 Subject: [PATCH 05/43] rlc: refactor RLC entity to use smart pointers for holding bearers this patch mainly modernizes the bearer creation to use smart pointers. that allows to simplify the error handling. ue_stack is changed to match new interface. This commit compiles but doesn't work. --- .../srsran/interfaces/ue_rlc_interfaces.h | 4 +- lib/include/srsran/upper/rlc.h | 15 +- lib/src/upper/rlc.cc | 190 +++++++----------- srsue/src/stack/rrc/test/ue_rrc_nr_test.cc | 4 +- srsue/src/stack/ue_stack_lte.cc | 2 +- 5 files changed, 79 insertions(+), 136 deletions(-) diff --git a/lib/include/srsran/interfaces/ue_rlc_interfaces.h b/lib/include/srsran/interfaces/ue_rlc_interfaces.h index 4c6452138..bf937cd9c 100644 --- a/lib/include/srsran/interfaces/ue_rlc_interfaces.h +++ b/lib/include/srsran/interfaces/ue_rlc_interfaces.h @@ -24,8 +24,8 @@ public: virtual void reset() = 0; virtual void reestablish() = 0; virtual void reestablish(uint32_t lcid) = 0; - virtual void add_bearer(uint32_t lcid, const srsran::rlc_config_t& cnfg) = 0; - virtual void add_bearer_mrb(uint32_t lcid) = 0; + virtual int add_bearer(uint32_t lcid, const srsran::rlc_config_t& cnfg) = 0; + virtual int add_bearer_mrb(uint32_t lcid) = 0; virtual void del_bearer(uint32_t lcid) = 0; virtual void suspend_bearer(uint32_t lcid) = 0; virtual void resume_bearer(uint32_t lcid) = 0; diff --git a/lib/include/srsran/upper/rlc.h b/lib/include/srsran/upper/rlc.h index cb393a26e..6a93ef55e 100644 --- a/lib/include/srsran/upper/rlc.h +++ b/lib/include/srsran/upper/rlc.h @@ -39,12 +39,6 @@ public: srsue::rrc_interface_rlc* rrc_, srsran::timer_handler* timers_, uint32_t lcid_); - - void init(srsue::pdcp_interface_rlc* pdcp_, - srsue::rrc_interface_rlc* rrc_, - srsue::rrc_interface_rlc* rrc_nr_, - srsran::timer_handler* timers_, - uint32_t lcid_); void init(srsue::pdcp_interface_rlc* pdcp_, srsue::rrc_interface_rlc* rrc_, @@ -82,8 +76,8 @@ public: void reestablish(uint32_t lcid); void reset(); void empty_queue(); - void add_bearer(uint32_t lcid, const rlc_config_t& cnfg); - void add_bearer_mrb(uint32_t lcid); + int add_bearer(uint32_t lcid, const rlc_config_t& cnfg); + int add_bearer_mrb(uint32_t lcid); void del_bearer(uint32_t lcid); void del_bearer_mrb(uint32_t lcid); void suspend_bearer(uint32_t lcid); @@ -98,11 +92,10 @@ private: byte_buffer_pool* pool = nullptr; srsue::pdcp_interface_rlc* pdcp = nullptr; srsue::rrc_interface_rlc* rrc = nullptr; - srsue::rrc_interface_rlc* rrc_nr = nullptr; srsran::timer_handler* timers = nullptr; - typedef std::map rlc_map_t; - typedef std::pair rlc_map_pair_t; + typedef std::map > rlc_map_t; + typedef std::pair > rlc_map_pair_t; rlc_map_t rlc_array, rlc_array_mrb; pthread_rwlock_t rwlock; diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index 8f71b0fa0..b7a388428 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -19,42 +19,20 @@ namespace srsran { -rlc::rlc(const char* logname) : logger(srslog::fetch_basic_logger(logname)) +rlc::rlc(const char* logname) : logger(srslog::fetch_basic_logger(logname)), pool(byte_buffer_pool::get_instance()) { - pool = byte_buffer_pool::get_instance(); pthread_rwlock_init(&rwlock, NULL); } rlc::~rlc() { // destroy all remaining entities - { - rwlock_write_guard lock(rwlock); - - for (rlc_map_t::iterator it = rlc_array.begin(); it != rlc_array.end(); ++it) { - delete (it->second); - } - rlc_array.clear(); - - for (rlc_map_t::iterator it = rlc_array_mrb.begin(); it != rlc_array_mrb.end(); ++it) { - delete (it->second); - } - rlc_array_mrb.clear(); - } - + srsran::rwlock_write_guard lock(rwlock); + rlc_array.clear(); + rlc_array_mrb.clear(); pthread_rwlock_destroy(&rwlock); } -void rlc::init(srsue::pdcp_interface_rlc* pdcp_, - srsue::rrc_interface_rlc* rrc_, - srsue::rrc_interface_rlc* rrc_nr_, - srsran::timer_handler* timers_, - uint32_t lcid_) -{ - init(pdcp_, rrc_, timers_, lcid_); - rrc_nr = rrc_nr_; -} - void rlc::init(srsue::pdcp_interface_rlc* pdcp_, srsue::rrc_interface_rlc* rrc_, srsran::timer_handler* timers_, @@ -171,11 +149,6 @@ void rlc::reset() { { rwlock_write_guard lock(rwlock); - - for (rlc_map_t::iterator it = rlc_array.begin(); it != rlc_array.end(); ++it) { - it->second->stop(); - delete (it->second); - } rlc_array.clear(); // the multicast bearer (MRB) is not removed here because eMBMS services continue to be streamed in idle mode (3GPP // TS 23.246 version 14.1.0 Release 14 section 8) @@ -399,119 +372,98 @@ bool rlc::has_data(uint32_t lcid) } // Methods modifying the RLC array need to acquire the write-lock -void rlc::add_bearer(uint32_t lcid, const rlc_config_t& cnfg) +int rlc::add_bearer(uint32_t lcid, const rlc_config_t& cnfg) { rwlock_write_guard lock(rwlock); - rlc_common* rlc_entity = nullptr; - - // Check this for later rrc_nr pointer access - if (cnfg.rat == srsran::srsran_rat_t::nr && rrc_nr == nullptr) { - logger.error("Cannot add/modify RLC entity - missing rrc_nr parent pointer for rat type nr"); - return; - } - - if (cnfg.rlc_mode != rlc_mode_t::tm and rlc_array.find(lcid) != rlc_array.end()) { - if (rlc_array[lcid]->get_mode() != cnfg.rlc_mode) { - logger.info("Switching RLC entity type. Recreating it."); - rlc_array.erase(lcid); - } + if (valid_lcid(lcid)) { + logger.error("LCID %d already exists", lcid); + return SRSRAN_ERROR; + } + + std::unique_ptr rlc_entity; + + switch (cnfg.rlc_mode) { + case rlc_mode_t::tm: + rlc_entity = std::unique_ptr(new rlc_tm(logger, lcid, pdcp, rrc)); + break; + case rlc_mode_t::am: + switch (cnfg.rat) { + case srsran_rat_t::lte: + rlc_entity = std::unique_ptr(new rlc_am_lte(logger, lcid, pdcp, rrc, timers)); + break; + default: + logger.error("AM not supported for this RAT"); + return SRSRAN_ERROR; + } + break; + case rlc_mode_t::um: + switch (cnfg.rat) { + case srsran_rat_t::lte: + rlc_entity = std::unique_ptr(new rlc_um_lte(logger, lcid, pdcp, rrc, timers)); + break; + case srsran_rat_t::nr: + rlc_entity = std::unique_ptr(new rlc_um_nr(logger, lcid, pdcp, rrc, timers)); + break; + default: + logger.error("UM not supported for this RAT"); + return SRSRAN_ERROR; + } + break; + default: + logger.error("Cannot add RLC entity - invalid mode"); + return SRSRAN_ERROR; } - if (not valid_lcid(lcid)) { - switch (cnfg.rat) { - case srsran_rat_t::lte: - switch (cnfg.rlc_mode) { - case rlc_mode_t::tm: - rlc_entity = new rlc_tm(logger, lcid, pdcp, rrc); - break; - case rlc_mode_t::am: - rlc_entity = new rlc_am_lte(logger, lcid, pdcp, rrc, timers); - break; - case rlc_mode_t::um: - rlc_entity = new rlc_um_lte(logger, lcid, pdcp, rrc, timers); - break; - default: - logger.error("Cannot add RLC entity - invalid mode"); - return; - } - if (rlc_entity != nullptr) { - rlc_entity->set_bsr_callback(bsr_callback); - } - break; - case srsran_rat_t::nr: - switch (cnfg.rlc_mode) { - case rlc_mode_t::tm: - rlc_entity = new rlc_tm(logger, lcid, pdcp, rrc_nr); - break; - case rlc_mode_t::um: - rlc_entity = new rlc_um_nr(logger, lcid, pdcp, rrc_nr, timers); - break; - default: - logger.error("Cannot add RLC entity - invalid mode"); - return; - } - break; - default: - logger.error("RAT not supported"); - return; - } - - if (not rlc_array.insert(rlc_map_pair_t(lcid, rlc_entity)).second) { - logger.error("Error inserting RLC entity in to array."); - goto delete_and_exit; - } - - logger.info("Added %s radio bearer with LCID %d in %s", to_string(cnfg.rat), lcid, to_string(cnfg.rlc_mode)); - rlc_entity = NULL; - } else { - logger.info("LCID %d already exists", lcid); + // make sure entity has been created + if (rlc_entity == nullptr) { + logger.error("Couldn't allocate new RLC entity"); + return SRSRAN_ERROR; } - // configure and add to array - if (cnfg.rlc_mode != rlc_mode_t::tm and rlc_array.find(lcid) != rlc_array.end()) { - if (not rlc_array.at(lcid)->configure(cnfg)) { + // configure entity + if (cnfg.rlc_mode != rlc_mode_t::tm) { + if (not rlc_entity->configure(cnfg)) { logger.error("Error configuring RLC entity."); - goto delete_and_exit; + return SRSRAN_ERROR; } } - logger.info("Configured %s radio bearer with LCID %d in %s", to_string(cnfg.rat), lcid, to_string(cnfg.rlc_mode)); + rlc_entity->set_bsr_callback(bsr_callback); -delete_and_exit: - if (rlc_entity) { - delete (rlc_entity); + if (not rlc_array.insert(rlc_map_pair_t(lcid, std::move(rlc_entity))).second) { + logger.error("Error inserting RLC entity in to array."); + return SRSRAN_ERROR; } + + logger.info("Added %s radio bearer with LCID %d in %s", to_string(cnfg.rat), lcid, to_string(cnfg.rlc_mode)); + + return SRSRAN_SUCCESS; } -void rlc::add_bearer_mrb(uint32_t lcid) +int rlc::add_bearer_mrb(uint32_t lcid) { rwlock_write_guard lock(rwlock); - rlc_common* rlc_entity = NULL; - if (not valid_lcid_mrb(lcid)) { - rlc_entity = new rlc_um_lte(logger, lcid, pdcp, rrc, timers); + std::unique_ptr rlc_entity = + std::unique_ptr(new rlc_um_lte(logger, lcid, pdcp, rrc, timers)); // configure and add to array - if (not rlc_entity->configure(rlc_config_t::mch_config())) { + if (rlc_entity or rlc_entity->configure(rlc_config_t::mch_config()) == false) { logger.error("Error configuring RLC entity."); - goto delete_and_exit; + return SRSRAN_ERROR; } if (rlc_array_mrb.count(lcid) == 0) { - if (not rlc_array_mrb.insert(rlc_map_pair_t(lcid, rlc_entity)).second) { + if (not rlc_array_mrb.insert(rlc_map_pair_t(lcid, std::move(rlc_entity))).second) { logger.error("Error inserting RLC entity in to array."); - goto delete_and_exit; + return SRSRAN_ERROR; } } - logger.warning("Added bearer MRB%d with mode RLC_UM", lcid); - return; + logger.info("Added bearer MRB%d with mode RLC_UM", lcid); } else { logger.warning("Bearer MRB%d already created.", lcid); } -delete_and_exit: - if (rlc_entity != NULL) { - delete (rlc_entity); - } + return SRSRAN_SUCCESS; } void rlc::del_bearer(uint32_t lcid) @@ -521,7 +473,6 @@ void rlc::del_bearer(uint32_t lcid) if (valid_lcid(lcid)) { rlc_map_t::iterator it = rlc_array.find(lcid); it->second->stop(); - delete (it->second); rlc_array.erase(it); logger.info("Deleted RLC bearer with LCID %d", lcid); } else { @@ -536,9 +487,8 @@ void rlc::del_bearer_mrb(uint32_t lcid) if (valid_lcid_mrb(lcid)) { rlc_map_t::iterator it = rlc_array_mrb.find(lcid); it->second->stop(); - delete (it->second); rlc_array_mrb.erase(it); - logger.warning("Deleted RLC MRB bearer with LCID %d", lcid); + logger.info("Deleted RLC MRB bearer with LCID %d", lcid); } else { logger.error("Can't delete bearer with LCID %d. Bearer doesn't exist.", lcid); } @@ -552,8 +502,8 @@ void rlc::change_lcid(uint32_t old_lcid, uint32_t new_lcid) if (valid_lcid(old_lcid) && not valid_lcid(new_lcid)) { // insert old rlc entity into new LCID rlc_map_t::iterator it = rlc_array.find(old_lcid); - rlc_common* rlc_entity = it->second; - if (not rlc_array.insert(rlc_map_pair_t(new_lcid, rlc_entity)).second) { + std::unique_ptr rlc_entity = std::move(it->second); + if (not rlc_array.insert(rlc_map_pair_t(new_lcid, std::move(rlc_entity))).second) { logger.error("Error inserting RLC entity into array."); return; } diff --git a/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc b/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc index 001589824..a05d2813a 100644 --- a/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc +++ b/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc @@ -48,8 +48,8 @@ class dummy_rlc : public rlc_interface_rrc void reset() {} void reestablish() {} void reestablish(uint32_t lcid) {} - void add_bearer(uint32_t lcid, const srsran::rlc_config_t& cnfg) {} - void add_bearer_mrb(uint32_t lcid) {} + int add_bearer(uint32_t lcid, const srsran::rlc_config_t& cnfg) { return SRSRAN_SUCCESS; } + int add_bearer_mrb(uint32_t lcid) { return SRSRAN_SUCCESS; } void del_bearer(uint32_t lcid) {} void suspend_bearer(uint32_t lcid) {} void resume_bearer(uint32_t lcid) {} diff --git a/srsue/src/stack/ue_stack_lte.cc b/srsue/src/stack/ue_stack_lte.cc index e903a4a27..56cbd7b9a 100644 --- a/srsue/src/stack/ue_stack_lte.cc +++ b/srsue/src/stack/ue_stack_lte.cc @@ -201,7 +201,7 @@ int ue_stack_lte::init(const stack_args_t& args_) sync_task_queue = task_sched.make_task_queue(args.sync_queue_size); mac.init(phy, &rlc, &rrc); - rlc.init(&pdcp, &rrc, &rrc_nr, task_sched.get_timer_handler(), 0 /* RB_ID_SRB0 */); + rlc.init(&pdcp, &rrc, task_sched.get_timer_handler(), 0 /* RB_ID_SRB0 */); pdcp.init(&rlc, &rrc, &rrc_nr, gw); nas.init(usim.get(), &rrc, gw, args.nas); From 3f9c069ff7bf2becdc8bd127dfa09ad690251ab5 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 13 May 2021 09:31:12 +0200 Subject: [PATCH 06/43] ue_stack_lte: add RLC and PDCP entities for NR --- srsue/hdr/stack/ue_stack_lte.h | 6 +++++- srsue/src/stack/ue_stack_lte.cc | 12 +++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/srsue/hdr/stack/ue_stack_lte.h b/srsue/hdr/stack/ue_stack_lte.h index e83c9f9b9..493962ce6 100644 --- a/srsue/hdr/stack/ue_stack_lte.h +++ b/srsue/hdr/stack/ue_stack_lte.h @@ -191,9 +191,11 @@ private: srslog::basic_logger& usim_logger; srslog::basic_logger& nas_logger; - // UE nr stack logging + // UE NR stack logging srslog::basic_logger& mac_nr_logger; srslog::basic_logger& rrc_nr_logger; + srslog::basic_logger& rlc_nr_logger; + srslog::basic_logger& pdcp_nr_logger; // tracing srsran::mac_pcap mac_pcap; @@ -220,6 +222,8 @@ private: srsran::pdcp pdcp; srsue::rrc rrc; srsue::mac_nr mac_nr; + srsran::rlc rlc_nr; + srsran::pdcp pdcp_nr; srsue::rrc_nr rrc_nr; srsue::nas nas; std::unique_ptr usim; diff --git a/srsue/src/stack/ue_stack_lte.cc b/srsue/src/stack/ue_stack_lte.cc index 56cbd7b9a..0898c0c85 100644 --- a/srsue/src/stack/ue_stack_lte.cc +++ b/srsue/src/stack/ue_stack_lte.cc @@ -36,6 +36,8 @@ ue_stack_lte::ue_stack_lte() : nas_logger(srslog::fetch_basic_logger("NAS", false)), mac_nr_logger(srslog::fetch_basic_logger("MAC-NR")), rrc_nr_logger(srslog::fetch_basic_logger("RRC-NR", false)), + rlc_nr_logger(srslog::fetch_basic_logger("RLC-NR", false)), + pdcp_nr_logger(srslog::fetch_basic_logger("PDCP-NR", false)), mac_pcap(), mac_nr_pcap(), usim(nullptr), @@ -43,9 +45,11 @@ ue_stack_lte::ue_stack_lte() : rlc("RLC"), mac("MAC", &task_sched), rrc(this, &task_sched), + rlc_nr("RLC-NR"), mac_nr(&task_sched), rrc_nr(&task_sched), pdcp(&task_sched, "PDCP"), + pdcp_nr(&task_sched, "PDCP-NR"), nas(&task_sched), thread("STACK"), task_sched(512, 64), @@ -119,6 +123,10 @@ int ue_stack_lte::init(const stack_args_t& args_) mac_nr_logger.set_hex_dump_max_size(args.log.mac_hex_limit); rrc_nr_logger.set_level(srslog::str_to_basic_level(args.log.rrc_level)); rrc_nr_logger.set_hex_dump_max_size(args.log.rrc_hex_limit); + pdcp_nr_logger.set_level(srslog::str_to_basic_level(args.log.pdcp_level)); + pdcp_nr_logger.set_hex_dump_max_size(args.log.pdcp_hex_limit); + rlc_nr_logger.set_level(srslog::str_to_basic_level(args.log.rlc_level)); + rlc_nr_logger.set_hex_dump_max_size(args.log.rlc_hex_limit); // Set up pcap // parse pcap trace list @@ -202,11 +210,13 @@ int ue_stack_lte::init(const stack_args_t& args_) mac.init(phy, &rlc, &rrc); rlc.init(&pdcp, &rrc, task_sched.get_timer_handler(), 0 /* RB_ID_SRB0 */); - pdcp.init(&rlc, &rrc, &rrc_nr, gw); + pdcp.init(&rlc, &rrc, gw); nas.init(usim.get(), &rrc, gw, args.nas); mac_nr_args_t mac_nr_args = {}; mac_nr.init(mac_nr_args, phy_nr, &rlc, &rrc_nr); + rlc_nr.init(&pdcp_nr, &rrc_nr, task_sched.get_timer_handler(), 0 /* RB_ID_SRB0 */); + pdcp_nr.init(&rlc_nr, &rrc_nr, gw); rrc_nr.init(phy_nr, &mac_nr, &rlc, &pdcp, gw, &rrc, usim.get(), task_sched.get_timer_handler(), nullptr, args.rrc_nr); rrc.init(phy, &mac, &rlc, &pdcp, &nas, usim.get(), gw, &rrc_nr, args.rrc); From a4b2a065ff6bb21143ba0852ace7faf60e2e4dad Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 6 May 2021 15:32:46 +0200 Subject: [PATCH 07/43] pdcp: reword warning when dropping PDU --- lib/src/upper/pdcp.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/upper/pdcp.cc b/lib/src/upper/pdcp.cc index 9eec6080a..385b80051 100644 --- a/lib/src/upper/pdcp.cc +++ b/lib/src/upper/pdcp.cc @@ -277,7 +277,7 @@ void pdcp::write_pdu(uint32_t lcid, unique_byte_buffer_t pdu) if (valid_lcid(lcid)) { pdcp_array.at(lcid)->write_pdu(std::move(pdu)); } else { - logger.warning("Writing pdu: lcid=%d. Deallocating pdu", lcid); + logger.warning("Dropping PDU, lcid=%d doesnt exists", lcid); } } From 483a216bd5f2e254d5144839a9366db9d44bd55b Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 14 Jun 2021 13:23:56 +0200 Subject: [PATCH 08/43] ue,stack: refactor handling of radio bearears in UE stack this is a rather large commit that is hard to split because it touches quite a few components. It's a preparation patch for adding NR split bearers in the next step. We realized that managing RLC and PDCP bearers for both NR and LTE in the same entity doesn't work. This is because we use the LCID as a key for all accesses. With NR dual connectivity however we can have the same LCID active at the same time for both LTE and NR carriers. The patch solves that by creating a dedicated NR instance for RLC/PDCP in the stack. But then the question arises for UL traffic on, e.g. LCID 4 what PDCP instance the GW should use for pushing SDUs. It doesnt' know that. And in fact it doesn't need to. It just needs to know EPS bearer IDs. So the next change was to remove the knowledge of what LCIDs are from the GW. Make is agnostic and only work on EPS bearer IDs. The handling and mapping between EPS bearer IDs and LCIDs for LTE or NR (mainly PDCP for pushing data) is done in the Stack because it has access to both. The NAS also has a EPS bearer map but only knows about default and dedicated bearers. It doesn't know on which logical channels they are transmitted. --- .../srsran/interfaces/ue_gw_interfaces.h | 25 ++++-- lib/include/srsran/interfaces/ue_interfaces.h | 4 +- .../srsran/interfaces/ue_pdcp_interfaces.h | 16 ++-- .../srsran/interfaces/ue_rrc_interfaces.h | 1 - lib/include/srsran/test/ue_test_interfaces.h | 2 + lib/include/srsran/upper/pdcp.h | 10 +-- lib/src/upper/pdcp.cc | 70 ++++++++--------- lib/src/upper/rlc.cc | 2 +- srsenb/hdr/stack/gnb_stack_nr.h | 2 +- srsenb/src/stack/gnb_stack_nr.cc | 5 +- srsue/hdr/stack/bearer_manager.h | 70 +++++++++++++++++ srsue/hdr/stack/rrc/rrc.h | 3 +- srsue/hdr/stack/rrc/rrc_nr.h | 2 +- srsue/hdr/stack/ue_stack_lte.h | 10 ++- srsue/hdr/stack/ue_stack_nr.h | 6 +- srsue/hdr/stack/upper/gw.h | 13 ++-- srsue/hdr/stack/upper/nas.h | 3 + srsue/hdr/stack/upper/tft_packet_filter.h | 7 +- srsue/src/stack/CMakeLists.txt | 2 +- srsue/src/stack/bearer_manager.cc | 69 ++++++++++++++++ srsue/src/stack/rrc/rrc.cc | 33 +++++--- srsue/src/stack/rrc/rrc_nr.cc | 5 +- srsue/src/stack/rrc/test/ue_rrc_nr_test.cc | 5 +- srsue/src/stack/ue_stack_lte.cc | 51 +++++++++--- srsue/src/stack/ue_stack_nr.cc | 2 +- srsue/src/stack/upper/gw.cc | 78 ++++++++----------- srsue/src/stack/upper/nas.cc | 46 +++++++---- srsue/src/stack/upper/test/gw_test.cc | 13 ++-- srsue/src/stack/upper/test/nas_test.cc | 30 +++---- srsue/src/stack/upper/test/tft_test.cc | 13 ++-- srsue/src/stack/upper/tft_packet_filter.cc | 28 ++++--- srsue/src/test/ttcn3/hdr/ttcn3_ue.h | 11 +-- srsue/src/test/ttcn3/src/ttcn3_dut.cc | 5 ++ srsue/src/test/ttcn3/src/ttcn3_ue.cc | 44 +++++++---- 34 files changed, 446 insertions(+), 240 deletions(-) create mode 100644 srsue/hdr/stack/bearer_manager.h create mode 100644 srsue/src/stack/bearer_manager.cc diff --git a/lib/include/srsran/interfaces/ue_gw_interfaces.h b/lib/include/srsran/interfaces/ue_gw_interfaces.h index 057cef5d2..90fe4acfa 100644 --- a/lib/include/srsran/interfaces/ue_gw_interfaces.h +++ b/lib/include/srsran/interfaces/ue_gw_interfaces.h @@ -21,14 +21,24 @@ namespace srsue { class gw_interface_nas { public: - virtual int setup_if_addr(uint32_t eps_bearer_id, - uint32_t lcid, - uint8_t pdn_type, - uint32_t ip_addr, - uint8_t* ipv6_if_id, - char* err_str) = 0; + /** + * Informs GW about new EPS default bearer being created after attach accept + * along with the assigned IP address. + */ + virtual int + setup_if_addr(uint32_t eps_bearer_id, uint8_t pdn_type, uint32_t ip_addr, uint8_t* ipv6_if_id, char* err_str) = 0; + + /** + * Inform GW about the deactivation of a EPS bearer, e.g. during + * detach + */ + virtual int deactivate_eps_bearer(const uint32_t eps_bearer_id) = 0; + + /** + * Informs GW about new traffic flow templates and their associated EPS bearer ID + * All TFT are applied to a dedicated EPS bearer that has a linked default bearer + */ virtual int apply_traffic_flow_template(const uint8_t& eps_bearer_id, - const uint8_t& lcid, const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft) = 0; typedef enum { @@ -50,7 +60,6 @@ class gw_interface_rrc { public: virtual void add_mch_port(uint32_t lcid, uint32_t port) = 0; - virtual int update_lcid(uint32_t eps_bearer_id, uint32_t new_lcid) = 0; virtual bool is_running() = 0; }; diff --git a/lib/include/srsran/interfaces/ue_interfaces.h b/lib/include/srsran/interfaces/ue_interfaces.h index 4027b1458..b55a5266b 100644 --- a/lib/include/srsran/interfaces/ue_interfaces.h +++ b/lib/include/srsran/interfaces/ue_interfaces.h @@ -28,7 +28,9 @@ namespace srsue { class stack_interface_rrc { public: - virtual srsran::tti_point get_current_tti() = 0; + virtual srsran::tti_point get_current_tti() = 0; + virtual void add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) = 0; + virtual void remove_eps_bearer(uint8_t eps_bearer_id) = 0; }; // Combined interface for PHY to access stack (MAC and RRC) diff --git a/lib/include/srsran/interfaces/ue_pdcp_interfaces.h b/lib/include/srsran/interfaces/ue_pdcp_interfaces.h index 9c3968da0..bdcf4c40f 100644 --- a/lib/include/srsran/interfaces/ue_pdcp_interfaces.h +++ b/lib/include/srsran/interfaces/ue_pdcp_interfaces.h @@ -25,7 +25,7 @@ public: virtual void reestablish(uint32_t lcid) = 0; virtual void reset() = 0; virtual void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu, int sn = -1) = 0; - virtual void add_bearer(uint32_t lcid, srsran::pdcp_config_t cnfg) = 0; + virtual int add_bearer(uint32_t lcid, srsran::pdcp_config_t cnfg) = 0; virtual void del_bearer(uint32_t lcid) = 0; virtual void change_lcid(uint32_t old_lcid, uint32_t new_lcid) = 0; virtual void config_security(uint32_t lcid, const srsran::as_security_config_t& sec_cfg) = 0; @@ -50,19 +50,23 @@ public: virtual void notify_failure(uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sn) = 0; }; -class pdcp_interface_gw +// Data-plane interface for Stack after EPS bearer to LCID conversion +class pdcp_interface_stack { public: - virtual void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) = 0; - virtual bool is_lcid_enabled(uint32_t lcid) = 0; + virtual void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu, int sn = -1) = 0; + virtual bool is_lcid_enabled(uint32_t lcid) = 0; }; -// STACK interface for GW -class stack_interface_gw : public pdcp_interface_gw +// STACK interface for GW (based on EPS-bearer IDs) +class stack_interface_gw { public: virtual bool is_registered() = 0; virtual bool start_service_request() = 0; + virtual void write_sdu(uint32_t eps_bearer_id, srsran::unique_byte_buffer_t sdu) = 0; + ///< Allow GW to query if a radio bearer for a given EPS bearer ID is currently active + virtual bool has_active_radio_bearer(uint32_t eps_bearer_id) = 0; }; } // namespace srsue diff --git a/lib/include/srsran/interfaces/ue_rrc_interfaces.h b/lib/include/srsran/interfaces/ue_rrc_interfaces.h index c4f20d2c8..96071af1d 100644 --- a/lib/include/srsran/interfaces/ue_rrc_interfaces.h +++ b/lib/include/srsran/interfaces/ue_rrc_interfaces.h @@ -72,7 +72,6 @@ public: virtual bool is_connected() = 0; virtual void paging_completed(bool outcome) = 0; virtual const char* get_rb_name(uint32_t lcid) = 0; - virtual uint32_t get_lcid_for_eps_bearer(const uint32_t& eps_bearer_id) = 0; virtual bool has_nr_dc() = 0; }; diff --git a/lib/include/srsran/test/ue_test_interfaces.h b/lib/include/srsran/test/ue_test_interfaces.h index 0b7ad541f..3df9d9605 100644 --- a/lib/include/srsran/test/ue_test_interfaces.h +++ b/lib/include/srsran/test/ue_test_interfaces.h @@ -27,6 +27,8 @@ public: stack_test_dummy() {} srsran::tti_point get_current_tti() override { return srsran::tti_point{tti % 10240}; } + void add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) final{}; + void remove_eps_bearer(uint8_t eps_bearer_id) final{}; // Testing utility functions void run_tti() diff --git a/lib/include/srsran/upper/pdcp.h b/lib/include/srsran/upper/pdcp.h index ffa27897c..d7e1ff918 100644 --- a/lib/include/srsran/upper/pdcp.h +++ b/lib/include/srsran/upper/pdcp.h @@ -26,14 +26,10 @@ class pdcp : public srsue::pdcp_interface_rlc, public srsue::pdcp_interface_rrc public: pdcp(srsran::task_sched_handle task_sched_, const char* logname); virtual ~pdcp(); - void init(srsue::rlc_interface_pdcp* rlc_, - srsue::rrc_interface_pdcp* rrc_, - srsue::rrc_interface_pdcp* rrc_nr_, - srsue::gw_interface_pdcp* gw_); void init(srsue::rlc_interface_pdcp* rlc_, srsue::rrc_interface_pdcp* rrc_, srsue::gw_interface_pdcp* gw_); void stop(); - // GW interface + // Stack interface bool is_lcid_enabled(uint32_t lcid); // RRC interface @@ -42,7 +38,7 @@ public: void reset() override; void write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, int sn = -1) override; void write_sdu_mch(uint32_t lcid, unique_byte_buffer_t sdu); - void add_bearer(uint32_t lcid, pdcp_config_t cnfg) override; + int add_bearer(uint32_t lcid, pdcp_config_t cnfg) override; void add_bearer_mrb(uint32_t lcid, pdcp_config_t cnfg); void del_bearer(uint32_t lcid) override; void change_lcid(uint32_t old_lcid, uint32_t new_lcid) override; @@ -75,7 +71,6 @@ public: private: srsue::rlc_interface_pdcp* rlc = nullptr; srsue::rrc_interface_pdcp* rrc = nullptr; - srsue::rrc_interface_pdcp* rrc_nr = nullptr; srsue::gw_interface_pdcp* gw = nullptr; srsran::task_sched_handle task_sched; srslog::basic_logger& logger; @@ -95,4 +90,5 @@ private: }; } // namespace srsran + #endif // SRSRAN_PDCP_H diff --git a/lib/src/upper/pdcp.cc b/lib/src/upper/pdcp.cc index 385b80051..2c45a0de1 100644 --- a/lib/src/upper/pdcp.cc +++ b/lib/src/upper/pdcp.cc @@ -30,15 +30,6 @@ pdcp::~pdcp() pdcp_array_mrb.clear(); } -void pdcp::init(srsue::rlc_interface_pdcp* rlc_, - srsue::rrc_interface_pdcp* rrc_, - srsue::rrc_interface_pdcp* rrc_nr_, - srsue::gw_interface_pdcp* gw_) -{ - init(rlc_, rrc_, gw_); - rrc_nr = rrc_nr_; -} - void pdcp::init(srsue::rlc_interface_pdcp* rlc_, srsue::rrc_interface_pdcp* rrc_, srsue::gw_interface_pdcp* gw_) { rlc = rlc_; @@ -88,7 +79,7 @@ void pdcp::write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, int sn) if (valid_lcid(lcid)) { pdcp_array.at(lcid)->write_sdu(std::move(sdu), sn); } else { - logger.warning("Writing sdu: lcid=%d. Deallocating sdu", lcid); + logger.warning("LCID %d doesn't exist. Deallocating SDU", lcid); } } @@ -99,39 +90,40 @@ void pdcp::write_sdu_mch(uint32_t lcid, unique_byte_buffer_t sdu) } } -void pdcp::add_bearer(uint32_t lcid, pdcp_config_t cfg) +int pdcp::add_bearer(uint32_t lcid, pdcp_config_t cfg) { - if (not valid_lcid(lcid)) { - std::unique_ptr entity; - // For now we create an pdcp entity lte for nr due to it's maturity - if (cfg.rat == srsran::srsran_rat_t::lte) { - entity.reset(new pdcp_entity_lte{rlc, rrc, gw, task_sched, logger, lcid}); - } else if (cfg.rat == srsran::srsran_rat_t::nr) { - if (rrc_nr == nullptr) { - logger.warning("Cannot add PDCP entity - missing rrc_nr parent pointer"); - return; - } - entity.reset(new pdcp_entity_lte{rlc, rrc_nr, gw, task_sched, logger, lcid}); - } + if (valid_lcid(lcid)) { + logger.error("Bearer %s already configured.", rrc->get_rb_name(lcid)); + return SRSRAN_ERROR; + } - if (not entity->configure(cfg)) { - logger.error("Can not configure PDCP entity"); - return; - } + std::unique_ptr entity; - if (not pdcp_array.insert(std::make_pair(lcid, std::move(entity))).second) { - logger.error("Error inserting PDCP entity in to array."); - return; - } - logger.info( - "Add %s (lcid=%d, bearer_id=%d, sn_len=%dbits)", rrc->get_rb_name(lcid), lcid, cfg.bearer_id, cfg.sn_len); - { - std::lock_guard lock(cache_mutex); - valid_lcids_cached.insert(lcid); - } - } else { - logger.info("Bearer %s already configured.", rrc->get_rb_name(lcid)); + // For now we create an pdcp entity lte for nr due to it's maturity + if (cfg.rat == srsran::srsran_rat_t::lte) { + entity.reset(new pdcp_entity_lte{rlc, rrc, gw, task_sched, logger, lcid}); + } else if (cfg.rat == srsran::srsran_rat_t::nr) { + entity.reset(new pdcp_entity_lte{rlc, rrc, gw, task_sched, logger, lcid}); + } + + if (not entity->configure(cfg)) { + logger.error("Can not configure PDCP entity"); + return SRSRAN_ERROR; } + + if (not pdcp_array.insert(std::make_pair(lcid, std::move(entity))).second) { + logger.error("Error inserting PDCP entity in to array."); + return SRSRAN_ERROR; + } + + { + std::lock_guard lock(cache_mutex); + valid_lcids_cached.insert(lcid); + } + + logger.info("Add %s (lcid=%d, bearer_id=%d, sn_len=%dbits)", rrc->get_rb_name(lcid), lcid, cfg.bearer_id, cfg.sn_len); + + return SRSRAN_SUCCESS; } void pdcp::add_bearer_mrb(uint32_t lcid, pdcp_config_t cfg) diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index b7a388428..389130857 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -448,7 +448,7 @@ int rlc::add_bearer_mrb(uint32_t lcid) std::unique_ptr rlc_entity = std::unique_ptr(new rlc_um_lte(logger, lcid, pdcp, rrc, timers)); // configure and add to array - if (rlc_entity or rlc_entity->configure(rlc_config_t::mch_config()) == false) { + if (not rlc_entity or rlc_entity->configure(rlc_config_t::mch_config()) == false) { logger.error("Error configuring RLC entity."); return SRSRAN_ERROR; } diff --git a/srsenb/hdr/stack/gnb_stack_nr.h b/srsenb/hdr/stack/gnb_stack_nr.h index 931891e1d..a53b37fc6 100644 --- a/srsenb/hdr/stack/gnb_stack_nr.h +++ b/srsenb/hdr/stack/gnb_stack_nr.h @@ -64,7 +64,7 @@ public: // Temporary GW interface void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu); - bool is_lcid_enabled(uint32_t lcid); + bool has_active_radio_bearer(uint32_t eps_bearer_id); bool switch_on(); void run_tti(uint32_t tti); diff --git a/srsenb/src/stack/gnb_stack_nr.cc b/srsenb/src/stack/gnb_stack_nr.cc index 223798334..9f3d93f06 100644 --- a/srsenb/src/stack/gnb_stack_nr.cc +++ b/srsenb/src/stack/gnb_stack_nr.cc @@ -86,7 +86,6 @@ int gnb_stack_nr::init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rr m_gw->init(args.coreless.gw_args, this); char* err_str = nullptr; if (m_gw->setup_if_addr(5, - args.coreless.drb_lcid, LIBLTE_MME_PDN_TYPE_IPV4, htonl(inet_addr(args.coreless.ip_addr.c_str())), nullptr, @@ -179,9 +178,9 @@ void gnb_stack_nr::write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) m_pdcp->write_sdu(args.coreless.rnti, lcid, std::move(sdu)); } -bool gnb_stack_nr::is_lcid_enabled(uint32_t lcid) +bool gnb_stack_nr::has_active_radio_bearer(uint32_t eps_bearer_id) { - return (lcid == args.coreless.drb_lcid); + return (eps_bearer_id == args.coreless.drb_lcid); } } // namespace srsenb diff --git a/srsue/hdr/stack/bearer_manager.h b/srsue/hdr/stack/bearer_manager.h new file mode 100644 index 000000000..b954bd6e8 --- /dev/null +++ b/srsue/hdr/stack/bearer_manager.h @@ -0,0 +1,70 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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. + * + */ + +#ifndef SRSUE_BEARER_MANAGER_H +#define SRSUE_BEARER_MANAGER_H + +#include "srsran/common/common.h" +#include "srsran/common/rwlock_guard.h" +#include "srsran/srslog/srslog.h" +#include +#include + +namespace srsue { + +/** + * @brief Helper class to manage the mapping between EPS bearer and radio bearer + * + * The class maps EPS bearers that are known to NAS and GW and radio bearer (RB) that + * are only known to RRC. Since the lifetime of a EPS bearer is usually longer + * than the lifetime of a RB, the GW needs to query the Stack to check whether a + * given EPS bearer is active, i.e. a DRB is established, or not. + * + * The class also maps between RATs since each LCID can exist on either EUTRA or NR RATs, or both. + * + * Since the access of this class is happening from two different threads (GW+RRC/Stack) + * it's public interface is protected. + * + */ +class bearer_manager +{ +public: + bearer_manager(); + ~bearer_manager(); + + // RRC interface + /// Registers EPS bearer with PDCP RAT type and LCID + void add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid); + + /// EPS bearer is removed from map when the associated DRB is deleted (e.g. after connection release) + void remove_eps_bearer(uint8_t eps_bearer_id); + + // GW interface + bool has_active_radio_bearer(uint32_t eps_bearer_id); + + // Stack interface to retrieve active RB + struct radio_bearer_t { + srsran::srsran_rat_t rat; + uint32_t lcid; + }; + radio_bearer_t& get_radio_bearer(uint32_t eps_bearer_id); + +private: + pthread_rwlock_t rwlock = {}; /// RW lock to protect access from RRC/GW threads + srslog::basic_logger& logger; + std::map eps_rb_map; + radio_bearer_t invalid_rb = {srsran::srsran_rat_t::nulltype, 0}; +}; + +} // namespace srsue + +#endif // SRSUE_BEARER_MANAGER_H \ No newline at end of file diff --git a/srsue/hdr/stack/rrc/rrc.h b/srsue/hdr/stack/rrc/rrc.h index abe9910c3..0f6a3fef4 100644 --- a/srsue/hdr/stack/rrc/rrc.h +++ b/srsue/hdr/stack/rrc/rrc.h @@ -193,8 +193,6 @@ private: srsran::s_tmsi_t ue_identity; bool ue_identity_configured = false; - bool drb_up = false; - // PHY controller state machine std::unique_ptr phy_ctrl; @@ -382,6 +380,7 @@ private: void release_drb(uint32_t drb_id); uint32_t get_lcid_for_eps_bearer(const uint32_t& eps_bearer_id); uint32_t get_drb_id_for_eps_bearer(const uint32_t& eps_bearer_id); + uint32_t get_eps_bearer_id_for_drb_id(const uint32_t& drb_id); void add_mrb(uint32_t lcid, uint32_t port); // Helpers for setting default values diff --git a/srsue/hdr/stack/rrc/rrc_nr.h b/srsue/hdr/stack/rrc/rrc_nr.h index 5e4f3e6ff..642bdbf4f 100644 --- a/srsue/hdr/stack/rrc/rrc_nr.h +++ b/srsue/hdr/stack/rrc/rrc_nr.h @@ -20,6 +20,7 @@ #include "srsran/common/common_nr.h" #include "srsran/common/stack_procedure.h" #include "srsran/common/task_scheduler.h" +#include "srsran/interfaces/ue_interfaces.h" #include "srsran/interfaces/ue_nr_interfaces.h" #include "srsran/interfaces/ue_rrc_interfaces.h" #include "srsue/hdr/stack/upper/gw.h" @@ -29,7 +30,6 @@ namespace srsue { class usim_interface_rrc_nr; class pdcp_interface_rrc; class rlc_interface_rrc; -class stack_interface_rrc; // Expert arguments to create GW without proper RRC struct core_less_args_t { diff --git a/srsue/hdr/stack/ue_stack_lte.h b/srsue/hdr/stack/ue_stack_lte.h index 493962ce6..2c81c017b 100644 --- a/srsue/hdr/stack/ue_stack_lte.h +++ b/srsue/hdr/stack/ue_stack_lte.h @@ -31,6 +31,7 @@ #include "upper/nas.h" #include "upper/usim.h" +#include "bearer_manager.h" #include "srsran/common/buffer_pool.h" #include "srsran/common/multiqueue.h" #include "srsran/common/string_helpers.h" @@ -159,12 +160,13 @@ public: } // Interface for GW - void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) final; - - bool is_lcid_enabled(uint32_t lcid) final { return pdcp.is_lcid_enabled(lcid); } + void write_sdu(uint32_t eps_bearer_id, srsran::unique_byte_buffer_t sdu) final; + bool has_active_radio_bearer(uint32_t eps_bearer_id) final; // Interface for RRC tti_point get_current_tti() final { return current_tti; } + void add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) final; + void remove_eps_bearer(uint8_t eps_bearer_id) final; srsran::ext_task_sched_handle get_task_sched() { return {&task_sched}; } @@ -228,6 +230,8 @@ private: srsue::nas nas; std::unique_ptr usim; + bearer_manager bearers; // helper to manage mapping between EPS and radio bearers + // Metrics helper uint32_t ul_dropped_sdus = 0; }; diff --git a/srsue/hdr/stack/ue_stack_nr.h b/srsue/hdr/stack/ue_stack_nr.h index 661cfc373..dbb4cf0cb 100644 --- a/srsue/hdr/stack/ue_stack_nr.h +++ b/srsue/hdr/stack/ue_stack_nr.h @@ -102,11 +102,13 @@ public: } // Interface for GW - void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) final; - bool is_lcid_enabled(uint32_t lcid) final { return pdcp->is_lcid_enabled(lcid); } + void write_sdu(uint32_t eps_bearer_id, srsran::unique_byte_buffer_t sdu) final; + bool has_active_radio_bearer(uint32_t eps_bearer_id) final { return true; /* TODO: add EPS to LCID mapping */ } // Interface for RRC srsran::tti_point get_current_tti() { return srsran::tti_point{0}; }; + void add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) final{}; + void remove_eps_bearer(uint8_t eps_bearer_id) final{}; private: void run_thread() final; diff --git a/srsue/hdr/stack/upper/gw.h b/srsue/hdr/stack/upper/gw.h index 3011e84c4..f4bf13ab2 100644 --- a/srsue/hdr/stack/upper/gw.h +++ b/srsue/hdr/stack/upper/gw.h @@ -21,6 +21,7 @@ #include "srsran/interfaces/ue_gw_interfaces.h" #include "srsran/srslog/srslog.h" #include "tft_packet_filter.h" +#include #include #include @@ -53,19 +54,17 @@ public: // NAS interface int setup_if_addr(uint32_t eps_bearer_id, - uint32_t lcid, uint8_t pdn_type, uint32_t ip_addr, uint8_t* ipv6_if_addr, char* err_str); + int deactivate_eps_bearer(const uint32_t eps_bearer_id); int apply_traffic_flow_template(const uint8_t& eps_bearer_id, - const uint8_t& lcid, const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft); void set_test_loop_mode(const test_loop_mode_state_t mode, const uint32_t ip_pdu_delay_ms); // RRC interface void add_mch_port(uint32_t lcid, uint32_t port); - int update_lcid(uint32_t eps_bearer_id, uint32_t new_lcid); bool is_running(); private: @@ -75,18 +74,18 @@ private: gw_args_t args = {}; - bool running = false; + std::atomic running = {false}; bool run_enable = false; int32_t netns_fd = 0; int32_t tun_fd = 0; struct ifreq ifr = {}; int32_t sock = 0; bool if_up = false; - uint32_t default_lcid = 0; - srslog::basic_logger& logger; + static const int NOT_ASSIGNED = -1; + int32_t default_eps_bearer_id = NOT_ASSIGNED; - std::map eps_lcid; // Mapping between eps bearer ID and LCID + srslog::basic_logger& logger; uint32_t current_ip_addr = 0; uint8_t current_if_id[8]; diff --git a/srsue/hdr/stack/upper/nas.h b/srsue/hdr/stack/upper/nas.h index e2d33fe33..eaac627e6 100644 --- a/srsue/hdr/stack/upper/nas.h +++ b/srsue/hdr/stack/upper/nas.h @@ -231,6 +231,9 @@ private: void airplane_mode_sim_switch_off(); void airplane_mode_sim_switch_on(); + // Misc helpers + void clear_eps_bearer(); + // FSM Helpers void enter_state(emm_state_t state_); void enter_emm_null(); diff --git a/srsue/hdr/stack/upper/tft_packet_filter.h b/srsue/hdr/stack/upper/tft_packet_filter.h index b7c806096..1f03f5434 100644 --- a/srsue/hdr/stack/upper/tft_packet_filter.h +++ b/srsue/hdr/stack/upper/tft_packet_filter.h @@ -59,14 +59,12 @@ class tft_packet_filter_t { public: tft_packet_filter_t(uint8_t eps_bearer_id_, - uint8_t lcid_, const LIBLTE_MME_PACKET_FILTER_STRUCT& tft_, srslog::basic_logger& logger); bool match(const srsran::unique_byte_buffer_t& pdu); bool filter_contains(uint16_t filtertype); uint8_t eps_bearer_id{}; - uint8_t lcid = {}; uint8_t id = {}; uint8_t eval_precedence = {}; uint32_t active_filters = {}; @@ -108,15 +106,12 @@ public: explicit tft_pdu_matcher(srslog::basic_logger& logger) : logger(logger) {} ~tft_pdu_matcher(){}; - void set_default_lcid(const uint8_t lcid); - uint8_t check_tft_filter_match(const srsran::unique_byte_buffer_t& pdu); + int check_tft_filter_match(const srsran::unique_byte_buffer_t& pdu, uint8_t& eps_bearer_id); int apply_traffic_flow_template(const uint8_t& erab_id, - const uint8_t& lcid, const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft); private: srslog::basic_logger& logger; - uint8_t default_lcid = 0; std::mutex tft_mutex; typedef std::map tft_filter_map_t; tft_filter_map_t tft_filter_map; diff --git a/srsue/src/stack/CMakeLists.txt b/srsue/src/stack/CMakeLists.txt index c2834833e..1d2e9e1aa 100644 --- a/srsue/src/stack/CMakeLists.txt +++ b/srsue/src/stack/CMakeLists.txt @@ -11,7 +11,7 @@ add_subdirectory(mac) add_subdirectory(rrc) add_subdirectory(upper) -set(SOURCES ue_stack_lte.cc) +set(SOURCES ue_stack_lte.cc bearer_manager.cc) add_library(srsue_stack STATIC ${SOURCES}) add_subdirectory(mac_nr) diff --git a/srsue/src/stack/bearer_manager.cc b/srsue/src/stack/bearer_manager.cc new file mode 100644 index 000000000..9b2d4c87e --- /dev/null +++ b/srsue/src/stack/bearer_manager.cc @@ -0,0 +1,69 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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 "srsue/hdr/stack/bearer_manager.h" + +namespace srsue { + +bearer_manager::bearer_manager() : logger(srslog::fetch_basic_logger("STCK", false)) +{ + pthread_rwlock_init(&rwlock, nullptr); +} + +bearer_manager::~bearer_manager() +{ + pthread_rwlock_destroy(&rwlock); +} + +void bearer_manager::add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) +{ + srsran::rwlock_write_guard rw_lock(rwlock); + auto it = eps_rb_map.find(eps_bearer_id); + if (it != eps_rb_map.end()) { + logger.error("EPS bearer ID %d already registered", eps_bearer_id); + return; + } + eps_rb_map.emplace(eps_bearer_id, radio_bearer_t{rat, lcid}); + logger.info("Registered EPS bearer ID %d for lcid=%d over %s-PDCP", eps_bearer_id, lcid, to_string(rat).c_str()); +} + +/// EPS bearer is removed from map when the associated DRB is deleted (e.g. after connection release) +void bearer_manager::remove_eps_bearer(uint8_t eps_bearer_id) +{ + srsran::rwlock_write_guard rw_lock(rwlock); + auto it = eps_rb_map.find(eps_bearer_id); + if (it == eps_rb_map.end()) { + logger.error("Can't remove EPS bearer ID %d", eps_bearer_id); + return; + } + eps_rb_map.erase(it); + logger.info("Removed mapping for EPS bearer ID %d", eps_bearer_id); +} + +// GW interface +bool bearer_manager::has_active_radio_bearer(uint32_t eps_bearer_id) +{ + srsran::rwlock_read_guard rw_lock(rwlock); + return eps_rb_map.find(eps_bearer_id) != eps_rb_map.end(); +} + +// Stack interface +bearer_manager::radio_bearer_t& bearer_manager::get_radio_bearer(uint32_t eps_bearer_id) +{ + srsran::rwlock_read_guard rw_lock(rwlock); + if (eps_rb_map.find(eps_bearer_id) != eps_rb_map.end()) { + return eps_rb_map.at(eps_bearer_id); + } + return invalid_rb; +} + +} // namespace srsue \ No newline at end of file diff --git a/srsue/src/stack/rrc/rrc.cc b/srsue/src/stack/rrc/rrc.cc index d738ef8f1..b97956247 100644 --- a/srsue/src/stack/rrc/rrc.cc +++ b/srsue/src/stack/rrc/rrc.cc @@ -53,7 +53,6 @@ rrc::rrc(stack_interface_rrc* stack_, srsran::task_sched_handle task_sched_) : task_sched(task_sched_), state(RRC_STATE_IDLE), last_state(RRC_STATE_CONNECTED), - drb_up(false), logger(srslog::fetch_basic_logger("RRC")), measurements(new rrc_meas()), cell_searcher(this), @@ -191,11 +190,6 @@ bool rrc::is_connected() return (RRC_STATE_CONNECTED == state); } -bool rrc::have_drb() -{ - return drb_up; -} - /* * * RRC State Machine @@ -1113,7 +1107,6 @@ void rrc::leave_connected() srsran::console("RRC IDLE\n"); logger.info("Leaving RRC_CONNECTED state"); state = RRC_STATE_IDLE; - drb_up = false; security_is_activated = false; // 1> reset MAC; @@ -2669,19 +2662,24 @@ void rrc::add_drb(const drb_to_add_mod_s& drb_cnfg) } mac->setup_lcid(lcid, log_chan_group, priority, prioritized_bit_rate, bucket_size_duration); + uint8_t eps_bearer_id = 5; // default? + if (drb_cnfg.eps_bearer_id_present) { + eps_bearer_id = drb_cnfg.eps_bearer_id; + } + + // register EPS bearer over LTE PDCP + stack->add_eps_bearer(eps_bearer_id, srsran::srsran_rat_t::lte, lcid); + drbs[drb_cnfg.drb_id] = drb_cnfg; - drb_up = true; logger.info("Added DRB Id %d (LCID=%d)", drb_cnfg.drb_id, lcid); - // Update LCID if gw is running - if (gw->is_running()) { - gw->update_lcid(drb_cnfg.eps_bearer_id, lcid); - } } void rrc::release_drb(uint32_t drb_id) { if (drbs.find(drb_id) != drbs.end()) { logger.info("Releasing DRB Id %d", drb_id); + // remove EPS bearer associated with this DRB from Stack (GW will trigger service request if needed) + stack->remove_eps_bearer(get_eps_bearer_id_for_drb_id(drb_id)); drbs.erase(drb_id); } else { logger.error("Couldn't release DRB Id %d. Doesn't exist.", drb_id); @@ -2704,6 +2702,17 @@ uint32_t rrc::get_lcid_for_eps_bearer(const uint32_t& eps_bearer_id) return lcid; } +uint32_t rrc::get_eps_bearer_id_for_drb_id(const uint32_t& drb_id) +{ + // check if this bearer id exists and return it's LCID + for (auto& drb : drbs) { + if (drb.first == drb_id) { + return drb.second.eps_bearer_id; + } + } + return 0; +} + uint32_t rrc::get_drb_id_for_eps_bearer(const uint32_t& eps_bearer_id) { // check if this bearer id exists and return it's LCID diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index 18ee3375a..079a97e39 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -1362,7 +1362,10 @@ bool rrc_nr::apply_drb_add_mod(const drb_to_add_mod_s& drb_cfg) srsran::pdcp_config_t pdcp_cfg = make_drb_pdcp_config_t(drb_cfg.drb_id, true, drb_cfg.pdcp_cfg); pdcp->add_bearer(lcid, pdcp_cfg); - gw->update_lcid(eps_bearer_id, lcid); + + // register EPS bearer over NR PDCP + stack->add_eps_bearer(eps_bearer_id, srsran::srsran_rat_t::nr, lcid); + return true; } diff --git a/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc b/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc index a05d2813a..185386a01 100644 --- a/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc +++ b/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc @@ -66,7 +66,7 @@ class dummy_pdcp : public pdcp_interface_rrc void reestablish(uint32_t lcid){}; void reset(){}; void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu, int sn = -1){}; - void add_bearer(uint32_t lcid, srsran::pdcp_config_t cnfg){}; + int add_bearer(uint32_t lcid, srsran::pdcp_config_t cnfg) { return SRSRAN_SUCCESS; }; void del_bearer(uint32_t lcid){}; void change_lcid(uint32_t old_lcid, uint32_t new_lcid){}; void config_security(uint32_t lcid, const srsran::as_security_config_t& sec_cfg){}; @@ -81,7 +81,6 @@ class dummy_pdcp : public pdcp_interface_rrc class dummy_gw : public gw_interface_rrc { void add_mch_port(uint32_t lcid, uint32_t port){}; - int update_lcid(uint32_t eps_bearer_id, uint32_t new_lcid) { return SRSRAN_SUCCESS; }; bool is_running() { return true; }; }; @@ -102,6 +101,8 @@ class dummy_sim : public usim_interface_rrc_nr class dummy_stack : public stack_interface_rrc { srsran::tti_point get_current_tti() { return srsran::tti_point(); }; + void add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid){}; + void remove_eps_bearer(uint8_t eps_bearer_id){}; }; int rrc_nr_cap_request_test() diff --git a/srsue/src/stack/ue_stack_lte.cc b/srsue/src/stack/ue_stack_lte.cc index 0898c0c85..40f0eb0a9 100644 --- a/srsue/src/stack/ue_stack_lte.cc +++ b/srsue/src/stack/ue_stack_lte.cc @@ -214,10 +214,11 @@ int ue_stack_lte::init(const stack_args_t& args_) nas.init(usim.get(), &rrc, gw, args.nas); mac_nr_args_t mac_nr_args = {}; - mac_nr.init(mac_nr_args, phy_nr, &rlc, &rrc_nr); + mac_nr.init(mac_nr_args, phy_nr, &rlc_nr, &rrc_nr); rlc_nr.init(&pdcp_nr, &rrc_nr, task_sched.get_timer_handler(), 0 /* RB_ID_SRB0 */); pdcp_nr.init(&rlc_nr, &rrc_nr, gw); - rrc_nr.init(phy_nr, &mac_nr, &rlc, &pdcp, gw, &rrc, usim.get(), task_sched.get_timer_handler(), nullptr, args.rrc_nr); + rrc_nr.init( + phy_nr, &mac_nr, &rlc_nr, &pdcp_nr, gw, &rrc, usim.get(), task_sched.get_timer_handler(), this, args.rrc_nr); rrc.init(phy, &mac, &rlc, &pdcp, &nas, usim.get(), gw, &rrc_nr, args.rrc); running = true; @@ -338,26 +339,58 @@ void ue_stack_lte::run_thread() * Stack Interfaces **********************************************************************************************************************/ +/******************** + * RRC Interface + *******************/ + +void ue_stack_lte::add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) +{ + bearers.add_eps_bearer(eps_bearer_id, rat, lcid); +} + +void ue_stack_lte::remove_eps_bearer(uint8_t eps_bearer_id) +{ + bearers.remove_eps_bearer(eps_bearer_id); +} + /******************** * GW Interface *******************/ /** - * Push GW SDU to stack - * @param lcid + * GW calls write_sdu() to push SDU for EPS bearer to stack. + * If the EPS bearer ID is valid it will deliver the PDU to the + * registered PDCP entity. + * + * @param eps_bearer_id * @param sdu - * @param blocking */ -void ue_stack_lte::write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) +void ue_stack_lte::write_sdu(uint32_t eps_bearer_id, srsran::unique_byte_buffer_t sdu) { - auto task = [this, lcid](srsran::unique_byte_buffer_t& sdu) { pdcp.write_sdu(lcid, std::move(sdu)); }; - bool ret = gw_queue_id.try_push(std::bind(task, std::move(sdu))).has_value(); + auto bearer = bearers.get_radio_bearer(eps_bearer_id); + auto task = [this, eps_bearer_id, bearer](srsran::unique_byte_buffer_t& sdu) { + // route SDU to PDCP entity + if (bearer.rat == srsran_rat_t::lte) { + pdcp.write_sdu(bearer.lcid, std::move(sdu)); + } else if (bearer.rat == srsran_rat_t::nr) { + pdcp_nr.write_sdu(bearer.lcid, std::move(sdu)); + } else { + stack_logger.warning("Can't deliver SDU for EPS bearer %d. Dropping it.", eps_bearer_id); + } + }; + + bool ret = gw_queue_id.try_push(std::bind(task, std::move(sdu))).has_value(); if (not ret) { - pdcp_logger.info("GW SDU with lcid=%d was discarded.", lcid); + pdcp_logger.info("GW SDU with lcid=%d was discarded.", bearer.lcid); ul_dropped_sdus++; } } +bool ue_stack_lte::has_active_radio_bearer(uint32_t eps_bearer_id) +{ + return bearers.has_active_radio_bearer(eps_bearer_id); +} + /** * Check whether nas is attached * @return bool wether NAS is in EMM_REGISTERED diff --git a/srsue/src/stack/ue_stack_nr.cc b/srsue/src/stack/ue_stack_nr.cc index 33ed31c5f..bd52f665b 100644 --- a/srsue/src/stack/ue_stack_nr.cc +++ b/srsue/src/stack/ue_stack_nr.cc @@ -111,7 +111,7 @@ bool ue_stack_nr::switch_on() { // statically setup TUN (will be done through RRC later) char* err_str = nullptr; - if (gw->setup_if_addr(5, 4, LIBLTE_MME_PDN_TYPE_IPV4, htonl(inet_addr("192.168.1.3")), nullptr, err_str)) { + if (gw->setup_if_addr(5, LIBLTE_MME_PDN_TYPE_IPV4, htonl(inet_addr("192.168.1.3")), nullptr, err_str)) { printf("Error configuring TUN interface\n"); } return true; diff --git a/srsue/src/stack/upper/gw.cc b/srsue/src/stack/upper/gw.cc index cac140b87..e92433dbe 100644 --- a/srsue/src/stack/upper/gw.cc +++ b/srsue/src/stack/upper/gw.cc @@ -166,7 +166,6 @@ void gw::write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) NAS interface *******************************************************************************/ int gw::setup_if_addr(uint32_t eps_bearer_id, - uint32_t lcid, uint8_t pdn_type, uint32_t ip_addr, uint8_t* ipv6_if_addr, @@ -186,46 +185,34 @@ int gw::setup_if_addr(uint32_t eps_bearer_id, } } - eps_lcid[eps_bearer_id] = lcid; - default_lcid = lcid; - tft_matcher.set_default_lcid(lcid); + default_eps_bearer_id = static_cast(eps_bearer_id); // Setup a thread to receive packets from the TUN device start(GW_THREAD_PRIO); return SRSRAN_SUCCESS; } - -bool gw::is_running() +int gw::deactivate_eps_bearer(const uint32_t eps_bearer_id) { - return running; + // only deactivation of default bearer + if (eps_bearer_id == static_cast(default_eps_bearer_id)) { + logger.debug("Deactivating EPS bearer %d", eps_bearer_id); + default_eps_bearer_id = NOT_ASSIGNED; + return SRSRAN_SUCCESS; + } + logger.error("Couldn't deactivate EPS bearer %d", eps_bearer_id); + return SRSRAN_ERROR; } -int gw::update_lcid(uint32_t eps_bearer_id, uint32_t new_lcid) +bool gw::is_running() { - auto it = eps_lcid.find(eps_bearer_id); - if (it != eps_lcid.end()) { - uint32_t old_lcid = eps_lcid[eps_bearer_id]; - logger.debug("Found EPS bearer %d. Update old lcid %d to new lcid %d", eps_bearer_id, old_lcid, new_lcid); - eps_lcid[eps_bearer_id] = new_lcid; - if (old_lcid == default_lcid) { - logger.debug("Defaulting new lcid %d", new_lcid); - default_lcid = new_lcid; - tft_matcher.set_default_lcid(new_lcid); - } - // TODO: update need filters if not the default lcid - } else { - logger.error("Did not found EPS bearer %d for updating LCID.", eps_bearer_id); - return SRSRAN_ERROR; - } - return SRSRAN_SUCCESS; + return running; } int gw::apply_traffic_flow_template(const uint8_t& erab_id, - const uint8_t& lcid, const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft) { - return tft_matcher.apply_traffic_flow_template(erab_id, lcid, tft); + return tft_matcher.apply_traffic_flow_template(erab_id, tft); } void gw::set_test_loop_mode(const test_loop_mode_state_t mode, const uint32_t ip_pdu_delay_ms) @@ -299,8 +286,8 @@ void gw::run_thread() if (pkt_len == pdu->N_bytes) { logger.info(pdu->msg, pdu->N_bytes, "TX PDU"); - // Make sure UE is attached - while (run_enable && !stack->is_registered() && register_wait < REGISTER_WAIT_TOUT) { + // Make sure UE is attached and has default EPS bearer activated + while (run_enable && default_eps_bearer_id == NOT_ASSIGNED && register_wait < REGISTER_WAIT_TOUT) { if (!register_wait) { logger.info("UE is not attached, waiting for NAS attach (%d/%d)", register_wait, REGISTER_WAIT_TOUT); } @@ -310,12 +297,18 @@ void gw::run_thread() register_wait = 0; // If we are still not attached by this stage, drop packet - if (run_enable && !stack->is_registered()) { + if (run_enable && default_eps_bearer_id == NOT_ASSIGNED) { continue; } + // Beyond this point we should have a activated default EPS bearer + srsran_assert(default_eps_bearer_id != NOT_ASSIGNED, "Default EPS bearer not activated"); + + uint8_t eps_bearer_id = default_eps_bearer_id; + tft_matcher.check_tft_filter_match(pdu, eps_bearer_id); + // Wait for service request if necessary - while (run_enable && !stack->is_lcid_enabled(default_lcid) && service_wait < SERVICE_WAIT_TOUT) { + while (run_enable && !stack->has_active_radio_bearer(eps_bearer_id) && service_wait < SERVICE_WAIT_TOUT) { if (!service_wait) { logger.info( "UE does not have service, waiting for NAS service request (%d/%d)", service_wait, SERVICE_WAIT_TOUT); @@ -331,21 +324,18 @@ void gw::run_thread() break; } - uint8_t lcid = tft_matcher.check_tft_filter_match(pdu); // Send PDU directly to PDCP - if (stack->is_lcid_enabled(lcid)) { - pdu->set_timestamp(); - ul_tput_bytes += pdu->N_bytes; - stack->write_sdu(lcid, std::move(pdu)); - do { - pdu = srsran::make_byte_buffer(); - if (!pdu) { - logger.error("Fatal Error: Couldn't allocate PDU in run_thread()."); - usleep(100000); - } - } while (!pdu); - idx = 0; - } + pdu->set_timestamp(); + ul_tput_bytes += pdu->N_bytes; + stack->write_sdu(eps_bearer_id, std::move(pdu)); + do { + pdu = srsran::make_byte_buffer(); + if (!pdu) { + logger.error("Fatal Error: Couldn't allocate PDU in run_thread()."); + usleep(100000); + } + } while (!pdu); + idx = 0; } else { idx += N_bytes; logger.debug("Entire packet not read from socket. Total Length %d, N_Bytes %d.", ip_pkt->tot_len, pdu->N_bytes); diff --git a/srsue/src/stack/upper/nas.cc b/srsue/src/stack/upper/nas.cc index 3633e70e6..adcbea366 100644 --- a/srsue/src/stack/upper/nas.cc +++ b/srsue/src/stack/upper/nas.cc @@ -161,32 +161,38 @@ void nas::run_tti() } } -/******************************************************************************* - * FSM Helperse - ******************************************************************************/ -void nas::enter_emm_null() +// Helper method to inform GW about remove default EPS bearer +void nas::clear_eps_bearer() { // Deactivate EPS bearer according to Sec. 5.5.2.2.2 logger.debug("Clearing EPS bearer context"); + for (const auto& bearer : eps_bearer) { + if (bearer.second.type == DEFAULT_EPS_BEARER) { + gw->deactivate_eps_bearer(bearer.second.eps_bearer_id); + } + } eps_bearer.clear(); +} + +/******************************************************************************* + * FSM Helpers + ******************************************************************************/ +void nas::enter_emm_null() +{ + clear_eps_bearer(); state.set_null(); } void nas::enter_emm_deregistered_initiated() { - // Deactivate EPS bearer according to Sec. 5.5.2.2.2 - logger.debug("Clearing EPS bearer context"); - eps_bearer.clear(); + clear_eps_bearer(); state.set_deregistered_initiated(); } void nas::enter_emm_deregistered(emm_state_t::deregistered_substate_t substate) { // TODO Start cell selection. - - // Deactivate EPS bearer according to Sec. 5.5.2.2.2 - logger.debug("Clearing EPS bearer context"); - eps_bearer.clear(); + clear_eps_bearer(); state.set_deregistered(substate); } @@ -1010,6 +1016,14 @@ void nas::parse_attach_accept(uint32_t lcid, unique_byte_buffer_t pdu) liblte_mme_unpack_activate_default_eps_bearer_context_request_msg(&attach_accept.esm_msg, &act_def_eps_bearer_context_req); + // make sure we don't already have a default EPS bearer activated + for (const auto& bearer : eps_bearer) { + if (bearer.second.type == DEFAULT_EPS_BEARER) { + logger.error("Only one default EPS bearer supported."); + return; + } + } + if ((cfg.apn_protocol == "ipv4" && LIBLTE_MME_PDN_TYPE_IPV6 == act_def_eps_bearer_context_req.pdn_addr.pdn_type) || (cfg.apn_protocol == "ipv6" && LIBLTE_MME_PDN_TYPE_IPV4 == act_def_eps_bearer_context_req.pdn_addr.pdn_type)) { logger.error("Failed to attach -- Mismatch between PDN protocol and PDN type in attach accept."); @@ -1045,7 +1059,6 @@ void nas::parse_attach_accept(uint32_t lcid, unique_byte_buffer_t pdu) // Setup GW char* err_str = nullptr; if (gw->setup_if_addr(act_def_eps_bearer_context_req.eps_bearer_id, - rrc->get_lcid_for_eps_bearer(act_def_eps_bearer_context_req.eps_bearer_id), LIBLTE_MME_PDN_TYPE_IPV4, ip_addr, nullptr, @@ -1078,7 +1091,6 @@ void nas::parse_attach_accept(uint32_t lcid, unique_byte_buffer_t pdu) // Setup GW char* err_str = nullptr; if (gw->setup_if_addr(act_def_eps_bearer_context_req.eps_bearer_id, - rrc->get_lcid_for_eps_bearer(act_def_eps_bearer_context_req.eps_bearer_id), LIBLTE_MME_PDN_TYPE_IPV6, 0, ipv6_if_id, @@ -1129,7 +1141,6 @@ void nas::parse_attach_accept(uint32_t lcid, unique_byte_buffer_t pdu) char* err_str = nullptr; if (gw->setup_if_addr(act_def_eps_bearer_context_req.eps_bearer_id, - rrc->get_lcid_for_eps_bearer(act_def_eps_bearer_context_req.eps_bearer_id), LIBLTE_MME_PDN_TYPE_IPV4V6, ip_addr, ipv6_if_id, @@ -1564,7 +1575,7 @@ void nas::parse_activate_dedicated_eps_bearer_context_request(uint32_t lcid, uni } // apply packet filters to GW - gw->apply_traffic_flow_template(request.eps_bearer_id, rrc->get_lcid_for_eps_bearer(request.eps_bearer_id), tft); + gw->apply_traffic_flow_template(request.eps_bearer_id, tft); send_activate_dedicated_eps_bearer_context_accept(request.proc_transaction_id, request.eps_bearer_id); } @@ -1593,6 +1604,9 @@ void nas::parse_deactivate_eps_bearer_context_request(unique_byte_buffer_t pdu) eps_bearer_map_t::iterator it = eps_bearer.find(request.eps_bearer_id); eps_bearer.erase(it); + // inform GW about removed EPS bearer + gw->deactivate_eps_bearer(request.eps_bearer_id); + logger.info("Removed EPS bearer context (eps_bearer_id=%d)", request.eps_bearer_id); send_deactivate_eps_bearer_context_accept(request.proc_transaction_id, request.eps_bearer_id); @@ -1951,7 +1965,7 @@ void nas::send_detach_request(bool switch_off) } if (switch_off) { - enter_emm_deregistered_initiated(); + enter_emm_deregistered(emm_state_t::deregistered_substate_t::null); } else { // we are expecting a response from the core state.set_deregistered_initiated(); diff --git a/srsue/src/stack/upper/test/gw_test.cc b/srsue/src/stack/upper/test/gw_test.cc index 3fa169784..9aa26226a 100644 --- a/srsue/src/stack/upper/test/gw_test.cc +++ b/srsue/src/stack/upper/test/gw_test.cc @@ -23,10 +23,10 @@ public: bool is_registered() { return true; } bool start_service_request() { return true; }; void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) { return; } - bool is_lcid_enabled(uint32_t lcid) { return true; } + bool has_active_radio_bearer(uint32_t eps_bearer_id) { return true; } }; -int gw_change_lcid_test() +int gw_test() { srsue::gw_args_t gw_args; gw_args.tun_dev_name = "tun1"; @@ -43,8 +43,7 @@ int gw_change_lcid_test() char* err_str = nullptr; int rtn = 0; - rtn = gw.setup_if_addr( - eps_bearer_id, old_lcid, LIBLTE_MME_PDN_TYPE_IPV4, htonl(inet_addr("192.168.56.32")), nullptr, err_str); + rtn = gw.setup_if_addr(eps_bearer_id, LIBLTE_MME_PDN_TYPE_IPV4, htonl(inet_addr("192.168.56.32")), nullptr, err_str); if (rtn != SRSRAN_SUCCESS) { srslog::fetch_basic_logger("TEST", false) @@ -53,8 +52,8 @@ int gw_change_lcid_test() return SRSRAN_SUCCESS; } - TESTASSERT(gw.update_lcid(eps_bearer_id, new_lcid) == SRSRAN_SUCCESS); - TESTASSERT(gw.update_lcid(non_existing_eps_bearer_id, new_lcid) == SRSRAN_ERROR); + TESTASSERT(gw.deactivate_eps_bearer(eps_bearer_id) == SRSRAN_SUCCESS); + TESTASSERT(gw.deactivate_eps_bearer(non_existing_eps_bearer_id) == SRSRAN_ERROR); gw.stop(); return SRSRAN_SUCCESS; } @@ -63,7 +62,7 @@ int main(int argc, char** argv) { srslog::init(); - TESTASSERT(gw_change_lcid_test() == SRSRAN_SUCCESS); + TESTASSERT(gw_test() == SRSRAN_SUCCESS); return SRSRAN_SUCCESS; } diff --git a/srsue/src/stack/upper/test/nas_test.cc b/srsue/src/stack/upper/test/nas_test.cc index 0769167af..11f52a7a6 100644 --- a/srsue/src/stack/upper/test/nas_test.cc +++ b/srsue/src/stack/upper/test/nas_test.cc @@ -63,18 +63,19 @@ using namespace srsran; namespace srsran { // fake classes -class pdcp_dummy : public rrc_interface_pdcp, public pdcp_interface_gw +class pdcp_dummy : public rrc_interface_pdcp, public pdcp_interface_stack { public: - void write_pdu(uint32_t lcid, unique_byte_buffer_t pdu) {} - void write_pdu_bcch_bch(unique_byte_buffer_t pdu) {} - void write_pdu_bcch_dlsch(unique_byte_buffer_t pdu) {} - void write_pdu_pcch(unique_byte_buffer_t pdu) {} - void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t sdu) {} - const char* get_rb_name(uint32_t lcid) { return "lcid"; } - void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) {} - bool is_lcid_enabled(uint32_t lcid) { return false; } - void notify_pdcp_integrity_error(uint32_t lcid) {} + void write_pdu(uint32_t lcid, unique_byte_buffer_t pdu) override {} + void write_pdu_bcch_bch(unique_byte_buffer_t pdu) override {} + void write_pdu_bcch_dlsch(unique_byte_buffer_t pdu) override {} + void write_pdu_pcch(unique_byte_buffer_t pdu) override {} + void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t sdu) override {} + const char* get_rb_name(uint32_t lcid) override { return "lcid"; } + void write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, int sn = -1) override {} + bool is_eps_bearer_id_enabled(uint32_t eps_bearer_id) { return false; } + void notify_pdcp_integrity_error(uint32_t lcid) override {} + bool is_lcid_enabled(uint32_t lcid) override { return false; } }; class rrc_dummy : public rrc_interface_nas @@ -131,7 +132,7 @@ private: class test_stack_dummy : public srsue::stack_test_dummy, public stack_interface_gw, public thread { public: - test_stack_dummy(pdcp_interface_gw* pdcp_) : pdcp(pdcp_), thread("DUMMY STACK") {} + test_stack_dummy(pdcp_interface_stack* pdcp_) : pdcp(pdcp_), thread("DUMMY STACK") {} void init(srsue::nas* nas_) { nas = nas_; @@ -139,7 +140,7 @@ public: } bool switch_on() { return true; } void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) { pdcp->write_sdu(lcid, std::move(sdu)); } - bool is_lcid_enabled(uint32_t lcid) { return pdcp->is_lcid_enabled(lcid); } + bool has_active_radio_bearer(uint32_t eps_bearer_id) { return true; } bool is_registered() { return true; } @@ -162,7 +163,7 @@ public: running = false; wait_thread_finish(); } - pdcp_interface_gw* pdcp = nullptr; + pdcp_interface_stack* pdcp = nullptr; srsue::nas* nas = nullptr; std::atomic running = {false}; }; @@ -170,7 +171,6 @@ public: class gw_dummy : public gw_interface_nas, public gw_interface_pdcp { int setup_if_addr(uint32_t eps_bearer_id, - uint32_t lcid, uint8_t pdn_type, uint32_t ip_addr, uint8_t* ipv6_if_id, @@ -178,8 +178,8 @@ class gw_dummy : public gw_interface_nas, public gw_interface_pdcp { return SRSRAN_SUCCESS; } + int deactivate_eps_bearer(const uint32_t eps_bearer_id) { return SRSRAN_SUCCESS; } int apply_traffic_flow_template(const uint8_t& eps_bearer_id, - const uint8_t& lcid, const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft) { return SRSRAN_SUCCESS; diff --git a/srsue/src/stack/upper/test/tft_test.cc b/srsue/src/stack/upper/test/tft_test.cc index 9b1ae415a..1b8fd8f5d 100644 --- a/srsue/src/stack/upper/test/tft_test.cc +++ b/srsue/src/stack/upper/test/tft_test.cc @@ -99,7 +99,6 @@ uint8_t ipv6_unmatched_packet_lport[] = { 0x80, 0x61, 0x00, 0x01, 0x00, 0x00, 0x0c, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; #define EPS_BEARER_ID 6 -#define LCID 1 int tft_filter_test_ipv6_combined() { @@ -150,7 +149,7 @@ int tft_filter_test_ipv6_combined() packet_filter.filter_size = sizeof(ipv6_filter); memcpy(packet_filter.filter, ipv6_filter, sizeof(ipv6_filter)); - srsue::tft_packet_filter_t filter(EPS_BEARER_ID, LCID, packet_filter, logger); + srsue::tft_packet_filter_t filter(EPS_BEARER_ID, packet_filter, logger); // Check filter TESTASSERT(filter.match(ip_msg1)); @@ -199,7 +198,7 @@ int tft_filter_test_single_local_port() packet_filter.filter_size = 3; memcpy(packet_filter.filter, filter_message, 3); - srsue::tft_packet_filter_t filter(EPS_BEARER_ID, LCID, packet_filter, logger); + srsue::tft_packet_filter_t filter(EPS_BEARER_ID, packet_filter, logger); // Check filter TESTASSERT(filter.match(ip_msg1)); @@ -245,7 +244,7 @@ int tft_filter_test_single_remote_port() packet_filter.filter_size = 3; memcpy(packet_filter.filter, filter_message, 3); - srsue::tft_packet_filter_t filter(EPS_BEARER_ID, LCID, packet_filter, logger); + srsue::tft_packet_filter_t filter(EPS_BEARER_ID, packet_filter, logger); // Check filter TESTASSERT(filter.match(ip_msg1)); @@ -294,7 +293,7 @@ int tft_filter_test_ipv4_local_addr() packet_filter.filter_size = filter_size; memcpy(packet_filter.filter, filter_message, filter_size); - srsue::tft_packet_filter_t filter(EPS_BEARER_ID, LCID, packet_filter, logger); + srsue::tft_packet_filter_t filter(EPS_BEARER_ID, packet_filter, logger); // Check filter TESTASSERT(filter.match(ip_msg1)); @@ -342,7 +341,7 @@ int tft_filter_test_ipv4_remote_addr() packet_filter.filter_size = filter_size; memcpy(packet_filter.filter, filter_message, filter_size); - srsue::tft_packet_filter_t filter(EPS_BEARER_ID, LCID, packet_filter, logger); + srsue::tft_packet_filter_t filter(EPS_BEARER_ID, packet_filter, logger); // Check filter TESTASSERT(filter.match(ip_msg1)); @@ -391,7 +390,7 @@ int tft_filter_test_ipv4_tos() packet_filter.filter_size = filter_size; memcpy(packet_filter.filter, filter_message, filter_size); - srsue::tft_packet_filter_t filter(EPS_BEARER_ID, LCID, packet_filter, logger); + srsue::tft_packet_filter_t filter(EPS_BEARER_ID, packet_filter, logger); // Check filter TESTASSERT(filter.match(ip_msg1)); diff --git a/srsue/src/stack/upper/tft_packet_filter.cc b/srsue/src/stack/upper/tft_packet_filter.cc index a0de74636..b31f6bf8d 100644 --- a/srsue/src/stack/upper/tft_packet_filter.cc +++ b/srsue/src/stack/upper/tft_packet_filter.cc @@ -24,11 +24,9 @@ extern "C" { namespace srsue { tft_packet_filter_t::tft_packet_filter_t(uint8_t eps_bearer_id_, - uint8_t lcid_, const LIBLTE_MME_PACKET_FILTER_STRUCT& tft, srslog::basic_logger& logger) : eps_bearer_id(eps_bearer_id_), - lcid(lcid_), id(tft.id), eval_precedence(tft.eval_precedence), active_filters(0), @@ -380,23 +378,28 @@ bool tft_packet_filter_t::match_port(const srsran::unique_byte_buffer_t& pdu) return true; } -uint8_t tft_pdu_matcher::check_tft_filter_match(const srsran::unique_byte_buffer_t& pdu) +/** + * Checks whether the provided PDU matches any configured TFT. + * If it finds a match, it updates the eps_bearer_id parameter. + * @param pdu Reference to the PDU to check. + * @param eps_bearer_id Reference to variable to store EPS bearer ID. + * @return SRSRAN_SUCCESS if a reference could be found, SRSRAN_ERROR otherwise. + */ +int tft_pdu_matcher::check_tft_filter_match(const srsran::unique_byte_buffer_t& pdu, uint8_t& eps_bearer_id) { std::lock_guard lock(tft_mutex); - uint8_t lcid = default_lcid; for (std::pair& filter_pair : tft_filter_map) { bool match = filter_pair.second.match(pdu); if (match) { - lcid = filter_pair.second.lcid; - logger.debug("Found filter match -- EPS bearer Id %d, LCID %d", filter_pair.second.eps_bearer_id, lcid); - break; + eps_bearer_id = filter_pair.second.eps_bearer_id; + logger.debug("Found filter match -- EPS bearer Id %d", filter_pair.second.eps_bearer_id); + return SRSRAN_SUCCESS; } } - return lcid; + return SRSRAN_ERROR; } int tft_pdu_matcher::apply_traffic_flow_template(const uint8_t& erab_id, - const uint8_t& lcid, const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft) { std::lock_guard lock(tft_mutex); @@ -404,7 +407,7 @@ int tft_pdu_matcher::apply_traffic_flow_template(const uint8_t& case LIBLTE_MME_TFT_OPERATION_CODE_CREATE_NEW_TFT: for (int i = 0; i < tft->packet_filter_list_size; i++) { logger.info("New packet filter for TFT"); - tft_packet_filter_t filter(erab_id, lcid, tft->packet_filter_list[i], logger); + tft_packet_filter_t filter(erab_id, tft->packet_filter_list[i], logger); auto it = tft_filter_map.insert(std::make_pair(filter.eval_precedence, filter)); if (it.second == false) { logger.error("Error inserting TFT Packet Filter"); @@ -419,9 +422,4 @@ int tft_pdu_matcher::apply_traffic_flow_template(const uint8_t& return SRSRAN_SUCCESS; } -void tft_pdu_matcher::set_default_lcid(const uint8_t lcid) -{ - default_lcid = lcid; -} - } // namespace srsue diff --git a/srsue/src/test/ttcn3/hdr/ttcn3_ue.h b/srsue/src/test/ttcn3/hdr/ttcn3_ue.h index f72f04652..1af0418fe 100644 --- a/srsue/src/test/ttcn3/hdr/ttcn3_ue.h +++ b/srsue/src/test/ttcn3/hdr/ttcn3_ue.h @@ -53,16 +53,15 @@ public: void write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu); void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t pdu); int setup_if_addr(uint32_t eps_bearer_id, - uint32_t lcid, uint8_t pdn_type, uint32_t ip_addr, uint8_t* ipv6_if_id, char* err_str); - int update_lcid(uint32_t eps_bearer_id, uint32_t new_lcid); bool is_running(); + int deactivate_eps_bearer(const uint32_t eps_bearer_id); + int apply_traffic_flow_template(const uint8_t& eps_bearer_id, - const uint8_t& lcid, const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft); void set_test_loop_mode(const test_loop_mode_state_t mode, const uint32_t ip_pdu_delay_ms_ = 0); @@ -71,7 +70,7 @@ public: void send_queued_data(); - void loop_back_pdu_with_tft(uint32_t input_lcid, srsran::unique_byte_buffer_t pdu); + void loop_back_pdu_with_tft(srsran::unique_byte_buffer_t pdu); private: std::unique_ptr phy; @@ -82,9 +81,11 @@ private: test_loop_mode_state_t test_loop_mode = TEST_LOOP_INACTIVE; srsran::timer_handler::unique_timer pdu_delay_timer; - std::map > pdu_queue; // A PDU queue for each DRB + block_queue pdu_queue; // PDU for UL data tft_pdu_matcher tft_matcher; + int default_eps_bearer_id = -1; + all_args_t args = {}; }; diff --git a/srsue/src/test/ttcn3/src/ttcn3_dut.cc b/srsue/src/test/ttcn3/src/ttcn3_dut.cc index 29006774f..a39f8d64c 100644 --- a/srsue/src/test/ttcn3/src/ttcn3_dut.cc +++ b/srsue/src/test/ttcn3/src/ttcn3_dut.cc @@ -72,6 +72,8 @@ all_args_t parse_args(ttcn3_dut_args_t* args, int argc, char* argv[]) all_args_t all_args = {}; + all_args.stack.pkt_trace.enable = "mac,nas"; + all_args.stack.pkt_trace.mac_pcap.enable = args->mac_pcap.enable; all_args.stack.pkt_trace.mac_pcap.filename = args->mac_pcap.filename; @@ -83,6 +85,8 @@ all_args_t parse_args(ttcn3_dut_args_t* args, int argc, char* argv[]) all_args.log.all_hex_limit = args->log_hex_level; all_args.phy.log.phy_level = args->log_level; + + all_args.stack.log.stack_level = args->log_level; all_args.stack.log.mac_level = args->log_level; all_args.stack.log.rlc_level = args->log_level; all_args.stack.log.pdcp_level = args->log_level; @@ -91,6 +95,7 @@ all_args_t parse_args(ttcn3_dut_args_t* args, int argc, char* argv[]) all_args.stack.log.gw_level = args->log_level; all_args.stack.log.usim_level = args->log_level; all_args.phy.log.phy_hex_limit = args->log_hex_level; + all_args.stack.log.stack_hex_limit = args->log_hex_level; all_args.stack.log.mac_hex_limit = args->log_hex_level; all_args.stack.log.rlc_hex_limit = args->log_hex_level; all_args.stack.log.pdcp_hex_limit = args->log_hex_level; diff --git a/srsue/src/test/ttcn3/src/ttcn3_ue.cc b/srsue/src/test/ttcn3/src/ttcn3_ue.cc index f6ebabd9b..6435a6cc8 100644 --- a/srsue/src/test/ttcn3/src/ttcn3_ue.cc +++ b/srsue/src/test/ttcn3/src/ttcn3_ue.cc @@ -153,6 +153,7 @@ void ttcn3_ue::add_mch_port(uint32_t lcid, uint32_t port) {} void ttcn3_ue::write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu) { logger.debug(pdu->msg, pdu->N_bytes, "Rx PDU (%d B) on lcid=%d", pdu->N_bytes, lcid); + switch (test_loop_mode) { case TEST_LOOP_INACTIVE: logger.warning("Test loop inactive. Dropping PDU."); @@ -163,13 +164,13 @@ void ttcn3_ue::write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu) case TEST_LOOP_MODE_B_ACTIVE: // Section 5.4.4 in TS 36.509 if (pdu_delay_timer.is_running()) { - pdu_queue[lcid].push(std::move(pdu)); + pdu_queue.push(std::move(pdu)); } else { if (pdu_delay_timer.is_set()) { - pdu_queue[lcid].push(std::move(pdu)); + pdu_queue.push(std::move(pdu)); pdu_delay_timer.run(); // timer is already set } else { - loop_back_pdu_with_tft(lcid, std::move(pdu)); + loop_back_pdu_with_tft(std::move(pdu)); } } break; @@ -180,12 +181,12 @@ void ttcn3_ue::write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu) } void ttcn3_ue::write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) {} int ttcn3_ue::setup_if_addr(uint32_t eps_bearer_id, - uint32_t lcid, uint8_t pdn_type, uint32_t ip_addr, uint8_t* ipv6_if_id, char* err_str) { + default_eps_bearer_id = static_cast(eps_bearer_id); return 0; } @@ -194,16 +195,16 @@ bool ttcn3_ue::is_running() return true; } -int ttcn3_ue::update_lcid(uint32_t eps_bearer_id, uint32_t new_lcid) +int ttcn3_ue::deactivate_eps_bearer(const uint32_t eps_bearer_id) { + default_eps_bearer_id = -1; return SRSRAN_SUCCESS; } int ttcn3_ue::apply_traffic_flow_template(const uint8_t& eps_bearer_id, - const uint8_t& lcid, const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft) { - return tft_matcher.apply_traffic_flow_template(eps_bearer_id, lcid, tft); + return tft_matcher.apply_traffic_flow_template(eps_bearer_id, tft); } void ttcn3_ue::set_test_loop_mode(const test_loop_mode_state_t mode, const uint32_t ip_pdu_delay_ms_) @@ -249,18 +250,27 @@ void ttcn3_ue::send_queued_data() return; } - for (auto& bearer_pdu_queue : pdu_queue) { - logger.info("Delivering %zd buffered PDUs for LCID=%d", bearer_pdu_queue.second.size(), bearer_pdu_queue.first); - while (not bearer_pdu_queue.second.empty()) { - srsran::unique_byte_buffer_t pdu; - bearer_pdu_queue.second.try_pop(&pdu); - loop_back_pdu_with_tft(bearer_pdu_queue.first, std::move(pdu)); - } + logger.info("Delivering %zd buffered UL PDUs", pdu_queue.size()); + while (not pdu_queue.empty()) { + srsran::unique_byte_buffer_t pdu; + pdu_queue.try_pop(&pdu); + loop_back_pdu_with_tft(std::move(pdu)); } } -void ttcn3_ue::loop_back_pdu_with_tft(uint32_t input_lcid, srsran::unique_byte_buffer_t pdu) +void ttcn3_ue::loop_back_pdu_with_tft(srsran::unique_byte_buffer_t pdu) { - logger.info(pdu->msg, pdu->N_bytes, "Rx PDU (%d B) on lcid=%d, looping back", pdu->N_bytes, input_lcid); - stack->write_sdu(input_lcid, std::move(pdu)); + if (default_eps_bearer_id == -1) { + logger.error("No default EPS bearer activated. Dropping PDU."); + } + + uint8_t target_eps_bearer_id = default_eps_bearer_id; + if (tft_matcher.check_tft_filter_match(pdu, target_eps_bearer_id) == SRSRAN_SUCCESS) { + logger.debug("Updated EPS bearer"); + } + + logger.info( + pdu->msg, pdu->N_bytes, "Rx PDU (%d B) looping back on eps_bearer_id=%d", pdu->N_bytes, target_eps_bearer_id); + + stack->write_sdu(target_eps_bearer_id, std::move(pdu)); } From 60f8a8db1cf7951e68621015538888a1e32dcd7b Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 17 May 2021 16:55:16 +0200 Subject: [PATCH 09/43] nas,tft: add support for TFT modification --- srsue/src/stack/upper/nas.cc | 16 +++++++++++++-- srsue/src/stack/upper/tft_packet_filter.cc | 24 ++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/srsue/src/stack/upper/nas.cc b/srsue/src/stack/upper/nas.cc index adcbea366..7f7b16234 100644 --- a/srsue/src/stack/upper/nas.cc +++ b/srsue/src/stack/upper/nas.cc @@ -1625,13 +1625,25 @@ void nas::parse_modify_eps_bearer_context_request(srsran::unique_byte_buffer_t p ctxt.rx_count++; // check if bearer exists - if (eps_bearer.find(request.eps_bearer_id) == eps_bearer.end()) { + const auto it = eps_bearer.find(request.eps_bearer_id); + if (it == eps_bearer.end()) { logger.error("EPS bearer doesn't exist (eps_bearer_id=%d)", request.eps_bearer_id); // fixme: send proper response return; } - // fixme: carry out modification + LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft = &request.tft; + logger.info("Traffic Flow Template: TFT OP code 0x%x, Filter list size %d, Parameter list size %d", + tft->tft_op_code, + tft->packet_filter_list_size, + tft->parameter_list_size); + + // modify/apply packet filters to GW + if (gw->apply_traffic_flow_template(request.eps_bearer_id, tft) != SRSRAN_SUCCESS) { + logger.error("Couldn't modify TFT"); + return; + } + logger.info("Modified EPS bearer context (eps_bearer_id=%d)", request.eps_bearer_id); send_modify_eps_bearer_context_accept(request.proc_transaction_id, request.eps_bearer_id); diff --git a/srsue/src/stack/upper/tft_packet_filter.cc b/srsue/src/stack/upper/tft_packet_filter.cc index b31f6bf8d..eca72c8d3 100644 --- a/srsue/src/stack/upper/tft_packet_filter.cc +++ b/srsue/src/stack/upper/tft_packet_filter.cc @@ -415,6 +415,30 @@ int tft_pdu_matcher::apply_traffic_flow_template(const uint8_t& } } break; + case LIBLTE_MME_TFT_OPERATION_CODE_REPLACE_PACKET_FILTERS_IN_EXISTING_TFT: + for (int i = 0; i < tft->packet_filter_list_size; i++) { + // erase old filter if it exists + auto old_filter = std::find_if( + tft_filter_map.begin(), tft_filter_map.end(), [&](const std::pair& filter) { + return filter.second.id == tft->packet_filter_list[i].id; + }); + if (old_filter == tft_filter_map.end()) { + logger.error("Error couldn't find TFT with id %d", tft->packet_filter_list[i].id); + return SRSRAN_ERROR_CANT_START; + } + + // release old filter + tft_filter_map.erase(old_filter); + + // Add new filter + tft_packet_filter_t new_filter(erab_id, tft->packet_filter_list[i], logger); + auto it = tft_filter_map.insert(std::make_pair(new_filter.eval_precedence, new_filter)); + if (it.second == false) { + logger.error("Error inserting TFT Packet Filter"); + return SRSRAN_ERROR_CANT_START; + } + } + break; default: logger.error("Unhandled TFT OP code"); return SRSRAN_ERROR_CANT_START; From eef9eb80c40163392522b633da28614e145a4dab Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 17 May 2021 17:39:29 +0200 Subject: [PATCH 10/43] ttcn3_ue: fix removal of dedicated EPS bearer --- srsue/src/test/ttcn3/src/ttcn3_ue.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/srsue/src/test/ttcn3/src/ttcn3_ue.cc b/srsue/src/test/ttcn3/src/ttcn3_ue.cc index 6435a6cc8..41325e6e9 100644 --- a/srsue/src/test/ttcn3/src/ttcn3_ue.cc +++ b/srsue/src/test/ttcn3/src/ttcn3_ue.cc @@ -197,7 +197,9 @@ bool ttcn3_ue::is_running() int ttcn3_ue::deactivate_eps_bearer(const uint32_t eps_bearer_id) { - default_eps_bearer_id = -1; + if (default_eps_bearer_id == static_cast(eps_bearer_id)) { + default_eps_bearer_id = -1; + } return SRSRAN_SUCCESS; } From 5313fb99d6c065841b7464cb103146c55ec41145 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 22 Jun 2021 15:41:32 +0200 Subject: [PATCH 11/43] tft: add helper to delete all TFTs for EPS bearer when a EPS bearer is removed, all associated TFTs need to be removed as well. --- srsue/hdr/stack/upper/tft_packet_filter.h | 5 +++- srsue/src/stack/upper/tft_packet_filter.cc | 33 +++++++++++++++++++--- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/srsue/hdr/stack/upper/tft_packet_filter.h b/srsue/hdr/stack/upper/tft_packet_filter.h index 1f03f5434..04eb46584 100644 --- a/srsue/hdr/stack/upper/tft_packet_filter.h +++ b/srsue/hdr/stack/upper/tft_packet_filter.h @@ -64,7 +64,7 @@ public: bool match(const srsran::unique_byte_buffer_t& pdu); bool filter_contains(uint16_t filtertype); - uint8_t eps_bearer_id{}; + uint8_t eps_bearer_id = {}; uint8_t id = {}; uint8_t eval_precedence = {}; uint32_t active_filters = {}; @@ -106,9 +106,12 @@ public: explicit tft_pdu_matcher(srslog::basic_logger& logger) : logger(logger) {} ~tft_pdu_matcher(){}; + void reset(); + int check_tft_filter_match(const srsran::unique_byte_buffer_t& pdu, uint8_t& eps_bearer_id); int apply_traffic_flow_template(const uint8_t& erab_id, const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft); + void delete_tft_for_eps_bearer(const uint8_t eps_bearer_id); private: srslog::basic_logger& logger; diff --git a/srsue/src/stack/upper/tft_packet_filter.cc b/srsue/src/stack/upper/tft_packet_filter.cc index eca72c8d3..d6fc6fd42 100644 --- a/srsue/src/stack/upper/tft_packet_filter.cc +++ b/srsue/src/stack/upper/tft_packet_filter.cc @@ -378,6 +378,11 @@ bool tft_packet_filter_t::match_port(const srsran::unique_byte_buffer_t& pdu) return true; } +void tft_pdu_matcher::reset() +{ + tft_filter_map.clear(); +} + /** * Checks whether the provided PDU matches any configured TFT. * If it finds a match, it updates the eps_bearer_id parameter. @@ -399,15 +404,35 @@ int tft_pdu_matcher::check_tft_filter_match(const srsran::unique_byte_buffer_t& return SRSRAN_ERROR; } -int tft_pdu_matcher::apply_traffic_flow_template(const uint8_t& erab_id, +/** + * @brief Deletes all registered TFT for a given EPS bearer ID + * + * @param eps_bearer_id The EPS bearer ID + */ +void tft_pdu_matcher::delete_tft_for_eps_bearer(const uint8_t eps_bearer_id) +{ + std::lock_guard lock(tft_mutex); + auto old_filter = std::find_if( + tft_filter_map.begin(), tft_filter_map.end(), [&](const std::pair& filter) { + return filter.second.eps_bearer_id == eps_bearer_id; + }); + if (old_filter != tft_filter_map.end()) { + logger.debug("Deleting TFT for EPS bearer %d", eps_bearer_id); + tft_filter_map.erase(old_filter); + } +} + +int tft_pdu_matcher::apply_traffic_flow_template(const uint8_t& eps_bearer_id, const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft) { std::lock_guard lock(tft_mutex); switch (tft->tft_op_code) { case LIBLTE_MME_TFT_OPERATION_CODE_CREATE_NEW_TFT: for (int i = 0; i < tft->packet_filter_list_size; i++) { - logger.info("New packet filter for TFT"); - tft_packet_filter_t filter(erab_id, tft->packet_filter_list[i], logger); + logger.info("New TFT for eps_bearer_id=%d, eval_precedence=%d", + eps_bearer_id, + tft->packet_filter_list[i].eval_precedence); + tft_packet_filter_t filter(eps_bearer_id, tft->packet_filter_list[i], logger); auto it = tft_filter_map.insert(std::make_pair(filter.eval_precedence, filter)); if (it.second == false) { logger.error("Error inserting TFT Packet Filter"); @@ -431,7 +456,7 @@ int tft_pdu_matcher::apply_traffic_flow_template(const uint8_t& tft_filter_map.erase(old_filter); // Add new filter - tft_packet_filter_t new_filter(erab_id, tft->packet_filter_list[i], logger); + tft_packet_filter_t new_filter(eps_bearer_id, tft->packet_filter_list[i], logger); auto it = tft_filter_map.insert(std::make_pair(new_filter.eval_precedence, new_filter)); if (it.second == false) { logger.error("Error inserting TFT Packet Filter"); From ab0fba5449e905f2a9b6bddeadc3821917d5d1d7 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 22 Jun 2021 15:42:29 +0200 Subject: [PATCH 12/43] gw: try to remove TFTs for all non-default EPS bearer GW needs to reset its default EPS bearer when it is removed and also try to remove all TFTs for a non-default bearere when it is removed. --- srsue/src/stack/upper/gw.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/srsue/src/stack/upper/gw.cc b/srsue/src/stack/upper/gw.cc index e92433dbe..90afe24ad 100644 --- a/srsue/src/stack/upper/gw.cc +++ b/srsue/src/stack/upper/gw.cc @@ -189,6 +189,7 @@ int gw::setup_if_addr(uint32_t eps_bearer_id, // Setup a thread to receive packets from the TUN device start(GW_THREAD_PRIO); + return SRSRAN_SUCCESS; } @@ -199,9 +200,11 @@ int gw::deactivate_eps_bearer(const uint32_t eps_bearer_id) logger.debug("Deactivating EPS bearer %d", eps_bearer_id); default_eps_bearer_id = NOT_ASSIGNED; return SRSRAN_SUCCESS; + } else { + // delete TFT template (if any) for this bearer + tft_matcher.delete_tft_for_eps_bearer(eps_bearer_id); + return SRSRAN_SUCCESS; } - logger.error("Couldn't deactivate EPS bearer %d", eps_bearer_id); - return SRSRAN_ERROR; } bool gw::is_running() From 7a85191323ce0e54166072850426a2b8254e5f9f Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 22 Jun 2021 15:43:36 +0200 Subject: [PATCH 13/43] nas: call GW for all removed EPS bearers this makes sure that GW can also remove all associated TFTs --- srsue/src/stack/upper/nas.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/srsue/src/stack/upper/nas.cc b/srsue/src/stack/upper/nas.cc index 7f7b16234..7606e1343 100644 --- a/srsue/src/stack/upper/nas.cc +++ b/srsue/src/stack/upper/nas.cc @@ -167,9 +167,7 @@ void nas::clear_eps_bearer() // Deactivate EPS bearer according to Sec. 5.5.2.2.2 logger.debug("Clearing EPS bearer context"); for (const auto& bearer : eps_bearer) { - if (bearer.second.type == DEFAULT_EPS_BEARER) { - gw->deactivate_eps_bearer(bearer.second.eps_bearer_id); - } + gw->deactivate_eps_bearer(bearer.second.eps_bearer_id); } eps_bearer.clear(); } From e248e086ed24be64c99b3107f6ef8df07a6eea35 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 22 Jun 2021 15:44:07 +0200 Subject: [PATCH 14/43] ttcn3_dut: reset TFT matcher object when DUT is switched off --- srsue/src/test/ttcn3/src/ttcn3_ue.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/srsue/src/test/ttcn3/src/ttcn3_ue.cc b/srsue/src/test/ttcn3/src/ttcn3_ue.cc index 41325e6e9..568f9d98d 100644 --- a/srsue/src/test/ttcn3/src/ttcn3_ue.cc +++ b/srsue/src/test/ttcn3/src/ttcn3_ue.cc @@ -108,6 +108,7 @@ bool ttcn3_ue::switch_on() bool ttcn3_ue::switch_off() { + tft_matcher.reset(); // empty all TFTs return stack->switch_off(); } From 4fa27f3841fd12b60135d4a3a4cc544bf4292759 Mon Sep 17 00:00:00 2001 From: Francisco Date: Mon, 21 Jun 2021 17:34:34 +0100 Subject: [PATCH 15/43] sched,nr: implementation of main classes for NR scheduler, and basic test for concurrency --- srsenb/hdr/stack/mac/nr/sched_nr.h | 65 ++++++++ srsenb/hdr/stack/mac/nr/sched_nr_common.h | 25 +++ srsenb/hdr/stack/mac/nr/sched_nr_harq.h | 61 ++++++++ srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 58 +++++++ srsenb/hdr/stack/mac/nr/sched_nr_ue.h | 101 ++++++++++++ srsenb/hdr/stack/mac/nr/sched_nr_worker.h | 79 ++++++++++ srsenb/src/stack/mac/CMakeLists.txt | 3 +- srsenb/src/stack/mac/nr/CMakeLists.txt | 11 ++ srsenb/src/stack/mac/{ => nr}/mac_nr.cc | 0 srsenb/src/stack/mac/nr/sched_nr.cc | 154 +++++++++++++++++++ srsenb/src/stack/mac/nr/sched_nr_ue.cc | 80 ++++++++++ srsenb/src/stack/mac/nr/sched_nr_worker.cc | 139 +++++++++++++++++ srsenb/test/mac/CMakeLists.txt | 2 + srsenb/test/mac/nr/CMakeLists.txt | 15 ++ srsenb/test/mac/nr/sched_nr_test.cc | 120 +++++++++++++++ 15 files changed, 911 insertions(+), 2 deletions(-) create mode 100644 srsenb/hdr/stack/mac/nr/sched_nr.h create mode 100644 srsenb/hdr/stack/mac/nr/sched_nr_common.h create mode 100644 srsenb/hdr/stack/mac/nr/sched_nr_harq.h create mode 100644 srsenb/hdr/stack/mac/nr/sched_nr_interface.h create mode 100644 srsenb/hdr/stack/mac/nr/sched_nr_ue.h create mode 100644 srsenb/hdr/stack/mac/nr/sched_nr_worker.h create mode 100644 srsenb/src/stack/mac/nr/CMakeLists.txt rename srsenb/src/stack/mac/{ => nr}/mac_nr.cc (100%) create mode 100644 srsenb/src/stack/mac/nr/sched_nr.cc create mode 100644 srsenb/src/stack/mac/nr/sched_nr_ue.cc create mode 100644 srsenb/src/stack/mac/nr/sched_nr_worker.cc create mode 100644 srsenb/test/mac/nr/CMakeLists.txt create mode 100644 srsenb/test/mac/nr/sched_nr_test.cc diff --git a/srsenb/hdr/stack/mac/nr/sched_nr.h b/srsenb/hdr/stack/mac/nr/sched_nr.h new file mode 100644 index 000000000..c34e0605f --- /dev/null +++ b/srsenb/hdr/stack/mac/nr/sched_nr.h @@ -0,0 +1,65 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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. + * + */ + +#ifndef SRSRAN_SCHED_NR_H +#define SRSRAN_SCHED_NR_H + +#include "sched_nr_common.h" +#include "sched_nr_interface.h" +#include "sched_nr_ue.h" +#include "sched_nr_worker.h" +#include "srsran/adt/pool/cached_alloc.h" +#include "srsran/common/tti_point.h" +#include +extern "C" { +#include "srsran/config.h" +} + +namespace srsenb { + +class ue_event_manager; + +class sched_nr final : public sched_nr_interface +{ +public: + sched_nr(const sched_nr_cfg& cfg); + ~sched_nr() override; + void ue_cfg(uint16_t rnti, const sched_nr_ue_cfg& cfg) override; + + void new_tti(tti_point tti_rx) override; + int generate_sched_result(tti_point tti_rx, uint32_t cc, sched_nr_res_t& result); + + void dl_ack_info(tti_point tti_rx, uint16_t rnti, uint32_t cc, uint32_t tb_idx, bool ack) override; + void ul_sr_info(tti_point tti_rx, uint16_t rnti) override; + +private: + void ue_cfg_impl(uint16_t rnti, const sched_nr_ue_cfg& cfg); + void run_tti(tti_point tti_rx, uint32_t cc); + + sched_nr_cfg cfg; + + using sched_worker_manager = sched_nr_impl::sched_worker_manager; + sched_worker_manager sched_workers; + + std::array, SCHED_NR_MAX_CARRIERS> sched_results; + + using ue_map_t = sched_nr_impl::ue_map_t; + std::mutex ue_db_mutex; + ue_map_t ue_db; + + // management of PHY UE feedback + std::unique_ptr pending_events; +}; + +} // namespace srsenb + +#endif // SRSRAN_SCHED_NR_H diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_common.h b/srsenb/hdr/stack/mac/nr/sched_nr_common.h new file mode 100644 index 000000000..f120fa802 --- /dev/null +++ b/srsenb/hdr/stack/mac/nr/sched_nr_common.h @@ -0,0 +1,25 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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. + * + */ + +#ifndef SRSRAN_SCHED_NR_COMMON_H +#define SRSRAN_SCHED_NR_COMMON_H + +#include "srsran/adt/circular_map.h" + +namespace srsenb { + +const static size_t SCHED_NR_MAX_USERS = 4; +const static size_t SCHED_NR_NOF_SUBFRAMES = 10; + +} // namespace srsenb + +#endif // SRSRAN_SCHED_NR_COMMON_H diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h new file mode 100644 index 000000000..6b6fe2ed2 --- /dev/null +++ b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h @@ -0,0 +1,61 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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. + * + */ + +#ifndef SRSRAN_SCHED_NR_HARQ_H +#define SRSRAN_SCHED_NR_HARQ_H + +#include "srsran/common/tti_point.h" +#include + +namespace srsenb { +namespace sched_nr_impl { + +template +class harq +{ +public: + harq() = default; + + bool empty() const + { + return std::all_of(tb.begin(), tb.end(), [](const tb_t t) { return not t.active; }); + } + bool empty(uint32_t tb_idx) const { return tb[tb_idx].active; } + +private: + struct tb_t { + bool active = false; + bool ack_state = false; + bool ndi = false; + uint32_t n_rtx = 0; + uint32_t mcs = 0; + }; + + uint32_t id; + tti_point tti_tx; + std::array tb; +}; + +class harq_entity +{ +public: + void dl_ack_info(tti_point tti_rx, uint32_t tb_idx, bool ack) {} + +private: + std::array, 16> dl_harqs; + std::array, 16> ul_harqs; +}; + +} // namespace sched_nr_impl +} // namespace srsenb + +#endif // SRSRAN_SCHED_NR_HARQ_H diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h new file mode 100644 index 000000000..fb1fe93fc --- /dev/null +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -0,0 +1,58 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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. + * + */ + +#ifndef SRSRAN_SCHED_NR_INTERFACE_H +#define SRSRAN_SCHED_NR_INTERFACE_H + +#include "srsran/adt/bounded_vector.h" +#include "srsran/common/tti_point.h" + +namespace srsenb { + +const static size_t SCHED_NR_MAX_CARRIERS = 4; +const static uint16_t SCHED_NR_INVALID_RNTI = 0; + +struct sched_nr_cell_cfg {}; + +struct sched_nr_cfg { + uint32_t nof_concurrent_subframes = 1; + + srsran::bounded_vector cells; +}; + +struct sched_nr_ue_cc_cfg { + bool active = false; +}; + +struct sched_nr_ue_cfg { + srsran::bounded_vector carriers; +}; + +struct sched_nr_res_t { + struct dl_result {}; + struct ul_result {}; +}; + +class sched_nr_interface +{ +public: + virtual ~sched_nr_interface() = default; + virtual void ue_cfg(uint16_t rnti, const sched_nr_ue_cfg& ue_cfg) = 0; + virtual void new_tti(tti_point tti_rx) = 0; + + virtual void dl_ack_info(tti_point tti_rx, uint16_t rnti, uint32_t cc, uint32_t tb_idx, bool ack) = 0; + virtual void ul_sr_info(tti_point, uint16_t rnti) = 0; +}; + +} // namespace srsenb + +#endif // SRSRAN_SCHED_NR_INTERFACE_H diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h new file mode 100644 index 000000000..5eccca607 --- /dev/null +++ b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h @@ -0,0 +1,101 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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. + * + */ + +#ifndef SRSRAN_SCHED_NR_UE_H +#define SRSRAN_SCHED_NR_UE_H + +#include "sched_nr_common.h" +#include "sched_nr_harq.h" +#include "sched_nr_interface.h" +#include "srsran/adt/move_callback.h" +#include "srsran/adt/pool/cached_alloc.h" + +namespace srsenb { + +namespace sched_nr_impl { + +class ue_carrier; + +class bwp_ue +{ +public: + bwp_ue() = default; + explicit bwp_ue(ue_carrier& carrier_, tti_point tti_rx_); + ~bwp_ue(); + bwp_ue(bwp_ue&& other) noexcept : carrier(other.carrier) { other.carrier = nullptr; } + bwp_ue& operator=(bwp_ue&& other) noexcept + { + carrier = other.carrier; + other.carrier = nullptr; + return *this; + } + bool empty() const { return carrier == nullptr; } + + tti_point tti_rx; + uint32_t cc = SCHED_NR_MAX_CARRIERS; + + const sched_nr_ue_cfg* cfg = nullptr; + bool pending_sr; + +private: + ue_carrier* carrier = nullptr; +}; + +class ue_carrier +{ +public: + ue_carrier(uint16_t rnti, uint32_t cc, const sched_nr_ue_cfg& cfg); + bwp_ue try_reserve(tti_point tti_rx); + void push_feedback(srsran::move_callback callback); + + const uint16_t rnti; + const uint32_t cc; + + harq_entity harq_ent; + +private: + friend class bwp_ue; + void release() { busy = false; } + + const sched_nr_ue_cfg* cfg; + + srsran::deque > pending_feedback; + bool busy{false}; +}; + +class ue +{ +public: + ue(uint16_t rnti, const sched_nr_ue_cfg& cfg); + + bwp_ue try_reserve(tti_point tti_rx, uint32_t cc); + + void set_cfg(const sched_nr_ue_cfg& cfg); + + void ul_sr_info(tti_point tti_rx) { pending_sr = true; } + + std::array, SCHED_NR_MAX_CARRIERS> carriers; + +private: + bool pending_sr = false; + + int current_idx = 0; + std::array ue_cfgs; +}; + +using ue_map_t = srsran::static_circular_map, SCHED_NR_MAX_USERS>; + +} // namespace sched_nr_impl + +} // namespace srsenb + +#endif // SRSRAN_SCHED_NR_UE_H diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h new file mode 100644 index 000000000..67a31878f --- /dev/null +++ b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h @@ -0,0 +1,79 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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. + * + */ + +#ifndef SRSRAN_SCHED_NR_WORKER_H +#define SRSRAN_SCHED_NR_WORKER_H + +#include "sched_nr_common.h" +#include "sched_nr_ue.h" +#include "srsran/adt/circular_array.h" +#include "srsran/adt/optional.h" +#include "srsran/adt/pool/cached_alloc.h" +#include "srsran/adt/span.h" +#include +#include +#include + +namespace srsenb { +namespace sched_nr_impl { + +class bwp_worker +{ +public: + explicit bwp_worker(uint32_t cc_, ue_map_t& ue_db_) : cc(cc_), ue_db(ue_db_) {} + + void start(tti_point tti_rx_); + void run(); + void end_tti(); + bool running() const { return tti_rx.is_valid(); } + +private: + ue_map_t& ue_db; + + tti_point tti_rx; + uint32_t cc; + + srsran::circular_array bwp_ues; +}; + +class sched_worker_manager +{ +public: + explicit sched_worker_manager(ue_map_t& ue_db_, const sched_nr_cfg& cfg_); + sched_worker_manager(const sched_worker_manager&) = delete; + sched_worker_manager(sched_worker_manager&&) = delete; + ~sched_worker_manager(); + + void reserve_workers(tti_point tti_rx, srsran::span sf_result_); + void start_tti(tti_point tti_rx); + bool run_tti(tti_point tti_rx, uint32_t cc); + void end_tti(tti_point tti_rx); + +private: + const sched_nr_cfg& cfg; + + struct sf_worker_ctxt { + sem_t sf_sem; + tti_point tti_rx; + srsran::span sf_result; + int worker_count = 0; + std::vector workers; + }; + std::vector > sf_ctxts; + + sf_worker_ctxt& get_sf(tti_point tti_rx); +}; + +} // namespace sched_nr_impl +} // namespace srsenb + +#endif // SRSRAN_SCHED_NR_WORKER_H diff --git a/srsenb/src/stack/mac/CMakeLists.txt b/srsenb/src/stack/mac/CMakeLists.txt index 7fe25ee6b..0ee0ac9bf 100644 --- a/srsenb/src/stack/mac/CMakeLists.txt +++ b/srsenb/src/stack/mac/CMakeLists.txt @@ -14,5 +14,4 @@ set(SOURCES mac.cc ue.cc sched.cc sched_carrier.cc sched_grid.cc sched_ue_ctrl/s sched_helpers.cc) add_library(srsenb_mac STATIC ${SOURCES} $) -set(SOURCES mac_nr.cc) -add_library(srsgnb_mac STATIC ${SOURCES}) +add_subdirectory(nr) \ No newline at end of file diff --git a/srsenb/src/stack/mac/nr/CMakeLists.txt b/srsenb/src/stack/mac/nr/CMakeLists.txt new file mode 100644 index 000000000..ee33f96bc --- /dev/null +++ b/srsenb/src/stack/mac/nr/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright 2013-2021 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(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc) + +add_library(srsgnb_mac STATIC ${SOURCES}) diff --git a/srsenb/src/stack/mac/mac_nr.cc b/srsenb/src/stack/mac/nr/mac_nr.cc similarity index 100% rename from srsenb/src/stack/mac/mac_nr.cc rename to srsenb/src/stack/mac/nr/mac_nr.cc diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsenb/src/stack/mac/nr/sched_nr.cc new file mode 100644 index 000000000..83423f734 --- /dev/null +++ b/srsenb/src/stack/mac/nr/sched_nr.cc @@ -0,0 +1,154 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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 "srsenb/hdr/stack/mac/nr/sched_nr.h" +#include "srsran/common/thread_pool.h" + +namespace srsenb { + +using sched_nr_impl::bwp_worker; +using sched_nr_impl::sched_worker_manager; +using sched_nr_impl::ue; +using sched_nr_impl::ue_carrier; +using sched_nr_impl::ue_map_t; + +class ue_event_manager +{ + using callback_t = srsran::move_callback; + using callback_list = srsran::deque; + +public: + explicit ue_event_manager(ue_map_t& ue_db_) : ue_db(ue_db_) {} + + void push_event(srsran::move_callback event) + { + std::lock_guard lock(common_mutex); + common_events.push_back(std::move(event)); + } + void push_cc_feedback(uint16_t rnti, uint32_t cc, srsran::move_callback event) + { + std::lock_guard lock(common_mutex); + feedback_list.emplace_back(); + feedback_list.back().rnti = rnti; + feedback_list.back().cc = cc; + feedback_list.back().callback = std::move(event); + } + void new_tti() + { + { + std::lock_guard lock(common_mutex); + common_events.swap(common_events_tmp); // reuse memory + feedback_list.swap(feedback_list_tmp); + } + while (not common_events_tmp.empty()) { + common_events_tmp.front()(); + common_events_tmp.pop_front(); + } + while (not feedback_list_tmp.empty()) { + auto& e = feedback_list_tmp.front(); + if (ue_db.contains(e.rnti) and ue_db[e.rnti]->carriers[e.cc] != nullptr) { + ue_db[e.rnti]->carriers[e.cc]->push_feedback(std::move(e.callback)); + } + } + } + +private: + ue_map_t& ue_db; + + std::mutex common_mutex; + callback_list common_events; + struct ue_feedback { + uint16_t rnti = SCHED_NR_INVALID_RNTI; + uint32_t cc = SCHED_NR_MAX_CARRIERS; + srsran::move_callback callback; + }; + srsran::deque feedback_list; + callback_list common_events_tmp; + srsran::deque feedback_list_tmp; +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +sched_nr::sched_nr(const sched_nr_cfg& cfg_) : + cfg(cfg_), pending_events(new ue_event_manager(ue_db)), sched_workers(ue_db, cfg) +{} + +sched_nr::~sched_nr() {} + +void sched_nr::ue_cfg(uint16_t rnti, const sched_nr_ue_cfg& uecfg) +{ + pending_events->push_event([this, rnti, uecfg]() { ue_cfg_impl(rnti, uecfg); }); +} + +void sched_nr::ue_cfg_impl(uint16_t rnti, const sched_nr_ue_cfg& uecfg) +{ + if (not ue_db.contains(rnti)) { + ue_db.insert(rnti, std::unique_ptr(new ue{rnti, uecfg})); + } else { + ue_db[rnti]->set_cfg(uecfg); + } +} + +void sched_nr::new_tti(tti_point tti_rx) +{ + // Lock subframe workers to provided tti_rx + sched_workers.reserve_workers(tti_rx, sched_results[tti_rx.sf_idx()]); + + { + // synchronize {tti,cc} state. e.g. reserve UE resources for {tti,cc} decision, process feedback + std::lock_guard lock(ue_db_mutex); + // Process pending events + pending_events->new_tti(); + + sched_workers.start_tti(tti_rx); + } +} + +int sched_nr::generate_sched_result(tti_point tti_rx, uint32_t cc, sched_nr_res_t& result) +{ + // Generate {tti,cc} scheduling decision + run_tti(tti_rx, cc); + + // copy scheduling decision result + result = sched_results[tti_rx.sf_idx()][cc]; + + return SRSRAN_SUCCESS; +} + +void sched_nr::run_tti(tti_point tti_rx, uint32_t cc) +{ + // unlocked, parallel region + bool all_workers_finished = sched_workers.run_tti(tti_rx, cc); + + if (all_workers_finished) { + // once all workers of the same subframe finished, synchronize sched outcome with ue_db + std::lock_guard lock(ue_db_mutex); + sched_workers.end_tti(tti_rx); + } +} + +void sched_nr::dl_ack_info(tti_point tti_rx, uint16_t rnti, uint32_t cc, uint32_t tb_idx, bool ack) +{ + pending_events->push_cc_feedback( + rnti, cc, [tti_rx, tb_idx, ack](ue_carrier& ue_cc) { ue_cc.harq_ent.dl_ack_info(tti_rx, tb_idx, ack); }); +} + +void sched_nr::ul_sr_info(tti_point tti_rx, uint16_t rnti) +{ + pending_events->push_event([this, rnti, tti_rx]() { + if (ue_db.contains(rnti)) { + ue_db[rnti]->ul_sr_info(tti_rx); + } + }); +} + +} // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue.cc b/srsenb/src/stack/mac/nr/sched_nr_ue.cc new file mode 100644 index 000000000..c772978e6 --- /dev/null +++ b/srsenb/src/stack/mac/nr/sched_nr_ue.cc @@ -0,0 +1,80 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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 "srsenb/hdr/stack/mac/nr/sched_nr_ue.h" + +namespace srsenb { +namespace sched_nr_impl { + +bwp_ue::bwp_ue(ue_carrier& carrier_, tti_point tti_rx_) : carrier(&carrier_), tti_rx(tti_rx_), cc(carrier_.cc) {} + +bwp_ue::~bwp_ue() +{ + if (carrier != nullptr) { + carrier->release(); + } +} + +ue_carrier::ue_carrier(uint16_t rnti_, uint32_t cc_, const sched_nr_ue_cfg& cfg_) : rnti(rnti_), cc(cc_), cfg(&cfg_) {} + +void ue_carrier::push_feedback(srsran::move_callback callback) +{ + pending_feedback.push_back(std::move(callback)); +} + +bwp_ue ue_carrier::try_reserve(tti_point tti_rx) +{ + if (busy) { + return bwp_ue(); + } + // successfully acquired + busy = true; + while (not pending_feedback.empty()) { + pending_feedback.front()(*this); + pending_feedback.pop_front(); + } + return bwp_ue(*this, tti_rx); +} + +ue::ue(uint16_t rnti, const sched_nr_ue_cfg& cfg) +{ + for (uint32_t cc = 0; cc < cfg.carriers.size(); ++cc) { + if (cfg.carriers[cc].active) { + carriers[cc].reset(new ue_carrier(rnti, cc, cfg)); + } + } +} + +void ue::set_cfg(const sched_nr_ue_cfg& cfg) +{ + current_idx = (current_idx + 1) % ue_cfgs.size(); + ue_cfgs[current_idx] = cfg; +} + +bwp_ue ue::try_reserve(tti_point tti_rx, uint32_t cc) +{ + if (carriers[cc] == nullptr) { + return bwp_ue(); + } + bwp_ue sfu = carriers[cc]->try_reserve(tti_rx); + if (sfu.empty()) { + return bwp_ue(); + } + // set UE-common parameters + sfu.pending_sr = pending_sr; + sfu.cfg = &ue_cfgs[current_idx]; + + return sfu; +} + +} // namespace sched_nr_impl +} // namespace srsenb diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc new file mode 100644 index 000000000..1f673a086 --- /dev/null +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -0,0 +1,139 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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 "srsenb/hdr/stack/mac/nr/sched_nr_worker.h" + +namespace srsenb { +namespace sched_nr_impl { + +/// Called at the beginning of TTI in a locked context, to reserve available UE resources +void bwp_worker::start(tti_point tti_rx_) +{ + srsran_assert(not running(), "scheduler worker::start() called for active worker"); + // Try reserve UE cells for this worker + for (auto& ue_pair : ue_db) { + uint16_t rnti = ue_pair.first; + ue& u = *ue_pair.second; + + bwp_ue sfu0 = u.try_reserve(tti_rx, cc); + if (sfu0.empty()) { + // Failed to synchronize because UE is being used by another worker + continue; + } + // Synchronization of UE for this {tti, cc} was successful + bwp_ues[rnti] = std::move(sfu0); + } + + tti_rx = tti_rx_; +} + +void bwp_worker::run() +{ + srsran_assert(running(), "scheduler worker::run() called for non-active worker"); +} + +void bwp_worker::end_tti() +{ + srsran_assert(running(), "scheduler worker::end() called for non-active worker"); + + // releases UE resources + for (bwp_ue& u : bwp_ues) { + if (not u.empty()) { + u = {}; + } + } + + tti_rx = {}; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, const sched_nr_cfg& cfg_) : cfg(cfg_) +{ + // Note: For now, we only allow parallelism at the sector level + sf_ctxts.resize(cfg.nof_concurrent_subframes); + for (size_t i = 0; i < cfg.nof_concurrent_subframes; ++i) { + sf_ctxts[i].reset(new sf_worker_ctxt()); + sem_init(&sf_ctxts[i]->sf_sem, 0, 1); + sf_ctxts[i]->workers.reserve(cfg.cells.size()); + for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { + sf_ctxts[i]->workers.emplace_back(cc, ue_db_); + } + } +} + +sched_worker_manager::~sched_worker_manager() +{ + for (uint32_t sf = 0; sf < sf_ctxts.size(); ++sf) { + sem_destroy(&sf_ctxts[sf]->sf_sem); + } +} + +sched_worker_manager::sf_worker_ctxt& sched_worker_manager::get_sf(tti_point tti_rx) +{ + return *sf_ctxts[tti_rx.to_uint() % sf_ctxts.size()]; +} + +void sched_worker_manager::reserve_workers(tti_point tti_rx_, srsran::span sf_result_) +{ + // lock if slot worker is already being used + auto& sf_worker_ctxt = get_sf(tti_rx_); + sem_wait(&sf_worker_ctxt.sf_sem); + + sf_worker_ctxt.sf_result = sf_result_; + sf_worker_ctxt.tti_rx = tti_rx_; + sf_worker_ctxt.worker_count = sf_worker_ctxt.workers.size(); +} + +void sched_worker_manager::start_tti(tti_point tti_rx_) +{ + auto& sf_worker_ctxt = get_sf(tti_rx_); + srsran_assert(sf_worker_ctxt.tti_rx == tti_rx_, "invalid run_tti(tti, cc) arguments"); + + for (uint32_t cc = 0; cc < sf_worker_ctxt.workers.size(); ++cc) { + sf_worker_ctxt.workers[cc].start(sf_worker_ctxt.tti_rx); + } +} + +bool sched_worker_manager::run_tti(tti_point tti_rx_, uint32_t cc) +{ + auto& sf_worker_ctxt = get_sf(tti_rx_); + srsran_assert(sf_worker_ctxt.tti_rx == tti_rx_, "invalid run_tti(tti, cc) arguments"); + if (not sf_worker_ctxt.workers[cc].running()) { + // run for this tti and cc was already called + return false; + } + + // Get {tti, cc} scheduling decision + sf_worker_ctxt.workers[cc].run(); + + // decrement the number of active workers + --sf_worker_ctxt.worker_count; + srsran_assert(sf_worker_ctxt.worker_count >= 0, "invalid number of calls to run_tti(tti, cc)"); + return sf_worker_ctxt.worker_count == 0; +} + +void sched_worker_manager::end_tti(tti_point tti_rx_) +{ + auto& sf_worker_ctxt = get_sf(tti_rx_); + srsran_assert(sf_worker_ctxt.tti_rx == tti_rx_, "invalid run_tti(tti, cc) arguments"); + srsran_assert(sf_worker_ctxt.worker_count == 0, "invalid number of calls to run_tti(tti, cc)"); + + // All the workers of the same TTI have finished. Synchronize scheduling decisions with UEs state + for (auto& worker : sf_worker_ctxt.workers) { + worker.end_tti(); + } + sem_post(&sf_worker_ctxt.sf_sem); +} + +} // namespace sched_nr_impl +} // namespace srsenb \ No newline at end of file diff --git a/srsenb/test/mac/CMakeLists.txt b/srsenb/test/mac/CMakeLists.txt index 117372fe6..2d3806231 100644 --- a/srsenb/test/mac/CMakeLists.txt +++ b/srsenb/test/mac/CMakeLists.txt @@ -74,3 +74,5 @@ add_test(sched_cqi_test sched_cqi_test) add_executable(sched_phy_resource_test sched_phy_resource_test.cc) target_link_libraries(sched_phy_resource_test srsran_common srsenb_mac srsran_mac sched_test_common) add_test(sched_phy_resource_test sched_phy_resource_test) + +add_subdirectory(nr) \ No newline at end of file diff --git a/srsenb/test/mac/nr/CMakeLists.txt b/srsenb/test/mac/nr/CMakeLists.txt new file mode 100644 index 000000000..d9e97fe56 --- /dev/null +++ b/srsenb/test/mac/nr/CMakeLists.txt @@ -0,0 +1,15 @@ +# +# Copyright 2013-2021 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_executable(sched_nr_test sched_nr_test.cc) +target_link_libraries(sched_nr_test + srsgnb_mac + srsran_common + ${CMAKE_THREAD_LIBS_INIT} + ${Boost_LIBRARIES}) +add_test(sched_nr_test sched_nr_test) diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc new file mode 100644 index 000000000..338e514b6 --- /dev/null +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -0,0 +1,120 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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 "srsenb/hdr/stack/mac/nr/sched_nr.h" +#include "srsran/common/test_common.h" +#include "srsran/common/thread_pool.h" + +namespace srsenb { + +void sched_nr_cfg_serialized_test() +{ + sched_nr_cfg cfg; + cfg.cells.resize(1); + + sched_nr sched(cfg); + + sched_nr_ue_cfg uecfg; + uecfg.carriers.resize(1); + uecfg.carriers[0].active = true; + sched.ue_cfg(0x46, uecfg); + + for (uint32_t nof_ttis = 0; nof_ttis < 1000; ++nof_ttis) { + tti_point tti(nof_ttis % 10240); + sched.new_tti(tti); + for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { + sched_nr_res_t res; + TESTASSERT(sched.generate_sched_result(tti, cc, res) == SRSRAN_SUCCESS); + } + } +} + +void sched_nr_cfg_parallel_cc_test() +{ + std::atomic tasks{0}; + + sched_nr_cfg cfg; + cfg.cells.resize(4); + + sched_nr sched(cfg); + + sched_nr_ue_cfg uecfg; + uecfg.carriers.resize(cfg.cells.size()); + for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { + uecfg.carriers[cc].active = true; + } + sched.ue_cfg(0x46, uecfg); + + for (uint32_t nof_ttis = 0; nof_ttis < 1000; ++nof_ttis) { + tti_point tti(nof_ttis % 10240); + sched.new_tti(tti); + ++tasks; + srsran::get_background_workers().push_task([&cfg, &sched, tti, &tasks]() { + for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { + sched_nr_res_t res; + TESTASSERT(sched.generate_sched_result(tti, cc, res) == SRSRAN_SUCCESS); + } + --tasks; + }); + } + + while (tasks > 0) { + usleep(100); + } +} + +void sched_nr_cfg_parallel_sf_test() +{ + uint32_t nof_sectors = 2; + std::atomic tasks{0}; + + sched_nr_cfg cfg; + cfg.nof_concurrent_subframes = 2; + cfg.cells.resize(nof_sectors); + + sched_nr sched(cfg); + + sched_nr_ue_cfg uecfg; + uecfg.carriers.resize(cfg.cells.size()); + for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { + uecfg.carriers[cc].active = true; + } + sched.ue_cfg(0x46, uecfg); + + for (uint32_t nof_ttis = 0; nof_ttis < 1000; ++nof_ttis) { + tti_point tti(nof_ttis % 10240); + sched.new_tti(tti); + ++tasks; + srsran::get_background_workers().push_task([&cfg, &sched, tti, &tasks]() { + for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { + sched_nr_res_t res; + TESTASSERT(sched.generate_sched_result(tti, cc, res) == SRSRAN_SUCCESS); + } + --tasks; + }); + } + + while (tasks > 0) { + usleep(100); + } +} + +} // namespace srsenb + +int main() +{ + srsran::get_background_workers().set_nof_workers(4); + + srsenb::sched_nr_cfg_serialized_test(); + srsenb::sched_nr_cfg_parallel_cc_test(); + srsenb::sched_nr_cfg_parallel_sf_test(); +} \ No newline at end of file From 407da794e1c58d139cfa69daf6bfcc091a71e353 Mon Sep 17 00:00:00 2001 From: Francisco Date: Tue, 22 Jun 2021 13:00:48 +0100 Subject: [PATCH 16/43] sched,nr: implementation of slot grid class --- srsenb/hdr/stack/mac/nr/sched_nr.h | 4 +- srsenb/hdr/stack/mac/nr/sched_nr_common.h | 11 ++- srsenb/hdr/stack/mac/nr/sched_nr_harq.h | 70 ++++++++++++--- srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 32 +++++-- srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h | 49 +++++++++++ srsenb/hdr/stack/mac/nr/sched_nr_ue.h | 51 ++++++----- srsenb/hdr/stack/mac/nr/sched_nr_worker.h | 36 ++++---- srsenb/src/stack/mac/nr/CMakeLists.txt | 2 +- srsenb/src/stack/mac/nr/sched_nr.cc | 23 ++--- srsenb/src/stack/mac/nr/sched_nr_harq.cc | 46 ++++++++++ srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 80 +++++++++++++++++ srsenb/src/stack/mac/nr/sched_nr_ue.cc | 79 +++++++++++++---- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 93 ++++++++++++++------ srsenb/test/mac/nr/sched_nr_test.cc | 2 +- 14 files changed, 462 insertions(+), 116 deletions(-) create mode 100644 srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h create mode 100644 srsenb/src/stack/mac/nr/sched_nr_harq.cc create mode 100644 srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc diff --git a/srsenb/hdr/stack/mac/nr/sched_nr.h b/srsenb/hdr/stack/mac/nr/sched_nr.h index c34e0605f..b1cf3502e 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr.h @@ -38,7 +38,7 @@ public: void new_tti(tti_point tti_rx) override; int generate_sched_result(tti_point tti_rx, uint32_t cc, sched_nr_res_t& result); - void dl_ack_info(tti_point tti_rx, uint16_t rnti, uint32_t cc, uint32_t tb_idx, bool ack) override; + void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) override; void ul_sr_info(tti_point tti_rx, uint16_t rnti) override; private: @@ -50,7 +50,7 @@ private: using sched_worker_manager = sched_nr_impl::sched_worker_manager; sched_worker_manager sched_workers; - std::array, SCHED_NR_MAX_CARRIERS> sched_results; + std::array, SCHED_NR_NOF_SUBFRAMES> sched_results; using ue_map_t = sched_nr_impl::ue_map_t; std::mutex ue_db_mutex; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_common.h b/srsenb/hdr/stack/mac/nr/sched_nr_common.h index f120fa802..996003cc2 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_common.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_common.h @@ -13,12 +13,21 @@ #ifndef SRSRAN_SCHED_NR_COMMON_H #define SRSRAN_SCHED_NR_COMMON_H -#include "srsran/adt/circular_map.h" +#include "sched_nr_interface.h" +#include "srsran/adt/bounded_bitset.h" namespace srsenb { const static size_t SCHED_NR_MAX_USERS = 4; const static size_t SCHED_NR_NOF_SUBFRAMES = 10; +const static size_t SCHED_NR_MAX_NOF_RBGS = 25; +const static size_t SCHED_NR_NOF_HARQS = 16; + +namespace sched_nr_impl { + +using rbgmask_t = srsran::bounded_bitset; + +} // namespace sched_nr_impl } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h index 6b6fe2ed2..e090e109a 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h @@ -13,24 +13,29 @@ #ifndef SRSRAN_SCHED_NR_HARQ_H #define SRSRAN_SCHED_NR_HARQ_H +#include "sched_nr_common.h" #include "srsran/common/tti_point.h" #include namespace srsenb { namespace sched_nr_impl { -template -class harq +class harq_proc { public: - harq() = default; + explicit harq_proc(uint32_t id_, uint32_t max_nof_tb_ = 1) : pid(id_), max_nof_tb(max_nof_tb_) {} - bool empty() const - { - return std::all_of(tb.begin(), tb.end(), [](const tb_t t) { return not t.active; }); - } + bool empty() const { return not tb[0].active and not tb[1].active; } bool empty(uint32_t tb_idx) const { return tb[tb_idx].active; } + void ack_info(uint32_t tb_idx, bool ack) { tb[tb_idx].ack_state = ack; } + + bool has_pending_retx(tti_point tti_rx) const { return not empty() and tti_tx + ack_delay <= tti_rx; } + + bool new_tx(tti_point tti_tx, const rbgmask_t& rbgmask, uint32_t mcs, uint32_t ack_delay); + + const uint32_t pid; + private: struct tb_t { bool active = false; @@ -40,19 +45,58 @@ private: uint32_t mcs = 0; }; - uint32_t id; - tti_point tti_tx; - std::array tb; + const uint32_t max_nof_tb; + + tti_point tti_tx; + uint32_t ack_delay = 0; + rbgmask_t rbgmask; + std::array tb; }; class harq_entity { public: - void dl_ack_info(tti_point tti_rx, uint32_t tb_idx, bool ack) {} + harq_entity(); + void new_tti(tti_point tti_rx_); + + void dl_ack_info(uint32_t pid, uint32_t tb_idx, bool ack) { dl_harqs[pid].ack_info(tb_idx, ack); } + + harq_proc& get_dl_harq(uint32_t pid) { return dl_harqs[pid]; } + + harq_proc* find_pending_dl_retx() + { + return find_dl([this](const harq_proc& h) { return h.has_pending_retx(tti_rx); }); + } + harq_proc* find_pending_ul_retx() + { + return find_ul([this](const harq_proc& h) { return h.has_pending_retx(tti_rx); }); + } + harq_proc* find_empty_dl_harq() + { + return find_dl([](const harq_proc& h) { return h.empty(); }); + } + harq_proc* find_empty_ul_harq() + { + return find_ul([](const harq_proc& h) { return h.empty(); }); + } private: - std::array, 16> dl_harqs; - std::array, 16> ul_harqs; + template + harq_proc* find_dl(Predicate p) + { + auto it = std::find_if(dl_harqs.begin(), dl_harqs.end(), p); + return (it == dl_harqs.end()) ? nullptr : &(*it); + } + template + harq_proc* find_ul(Predicate p) + { + auto it = std::find_if(ul_harqs.begin(), ul_harqs.end(), p); + return (it == ul_harqs.end()) ? nullptr : &(*it); + } + + tti_point tti_rx; + std::vector dl_harqs; + std::vector ul_harqs; }; } // namespace sched_nr_impl diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index fb1fe93fc..e38d4e8ad 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -18,10 +18,16 @@ namespace srsenb { -const static size_t SCHED_NR_MAX_CARRIERS = 4; -const static uint16_t SCHED_NR_INVALID_RNTI = 0; +const static size_t SCHED_NR_MAX_CARRIERS = 4; +const static uint16_t SCHED_NR_INVALID_RNTI = 0; +const static size_t SCHED_NR_MAX_PDSCH_DATA = 16; +const static size_t SCHED_NR_MAX_PUSCH_DATA = 16; +const static size_t SCHED_NR_MAX_TB = 2; -struct sched_nr_cell_cfg {}; +struct sched_nr_cell_cfg { + uint32_t nof_prb; + uint32_t nof_rbg; +}; struct sched_nr_cfg { uint32_t nof_concurrent_subframes = 1; @@ -37,9 +43,21 @@ struct sched_nr_ue_cfg { srsran::bounded_vector carriers; }; +struct sched_nr_data_t { + srsran::bounded_vector tbs; +}; + +struct sched_nr_dl_res_t { + srsran::bounded_vector data; +}; + +struct sched_nr_ul_res_t { + srsran::bounded_vector pusch; +}; + struct sched_nr_res_t { - struct dl_result {}; - struct ul_result {}; + sched_nr_dl_res_t dl_res; + sched_nr_ul_res_t ul_res; }; class sched_nr_interface @@ -49,8 +67,8 @@ public: virtual void ue_cfg(uint16_t rnti, const sched_nr_ue_cfg& ue_cfg) = 0; virtual void new_tti(tti_point tti_rx) = 0; - virtual void dl_ack_info(tti_point tti_rx, uint16_t rnti, uint32_t cc, uint32_t tb_idx, bool ack) = 0; - virtual void ul_sr_info(tti_point, uint16_t rnti) = 0; + virtual void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) = 0; + virtual void ul_sr_info(tti_point, uint16_t rnti) = 0; }; } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h new file mode 100644 index 000000000..38ae6a366 --- /dev/null +++ b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h @@ -0,0 +1,49 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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. + * + */ + +#ifndef SRSRAN_SCHED_NR_RB_GRID_H +#define SRSRAN_SCHED_NR_RB_GRID_H + +#include "sched_nr_interface.h" +#include "sched_nr_ue.h" + +namespace srsenb { +namespace sched_nr_impl { + +class slot_grid +{ +public: + explicit slot_grid(uint32_t cc, const sched_nr_cfg& cfg_); + void new_tti(tti_point tti_rx_, sched_nr_res_t& sched_res_); + bool alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask); + bool alloc_pusch(slot_ue& ue, const rbgmask_t& dl_mask); + + void generate_dcis(); + + tti_point tti_tx_dl() const { return tti_rx + TX_ENB_DELAY; } + tti_point tti_tx_ul() const { return tti_tx_dl() + K2; } + +private: + static const size_t K0 = 0, K1 = 4, K2 = 4; + const uint32_t cc; + const sched_nr_cfg& cfg; + + tti_point tti_rx; + rbgmask_t pdsch_mask; + rbgmask_t pusch_mask; + sched_nr_res_t* sched_res = nullptr; +}; + +} // namespace sched_nr_impl +} // namespace srsenb + +#endif // SRSRAN_SCHED_NR_RB_GRID_H diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h index 5eccca607..16688f11c 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h @@ -16,6 +16,7 @@ #include "sched_nr_common.h" #include "sched_nr_harq.h" #include "sched_nr_interface.h" +#include "srsran/adt/circular_map.h" #include "srsran/adt/move_callback.h" #include "srsran/adt/pool/cached_alloc.h" @@ -25,51 +26,61 @@ namespace sched_nr_impl { class ue_carrier; -class bwp_ue +class slot_ue { public: - bwp_ue() = default; - explicit bwp_ue(ue_carrier& carrier_, tti_point tti_rx_); - ~bwp_ue(); - bwp_ue(bwp_ue&& other) noexcept : carrier(other.carrier) { other.carrier = nullptr; } - bwp_ue& operator=(bwp_ue&& other) noexcept - { - carrier = other.carrier; - other.carrier = nullptr; - return *this; - } - bool empty() const { return carrier == nullptr; } + slot_ue() = default; + explicit slot_ue(bool& busy_signal, tti_point tti_rx_, uint32_t cc); + ~slot_ue(); + slot_ue(slot_ue&&) noexcept = default; + slot_ue& operator=(slot_ue&&) noexcept = default; + bool empty() const { return busy_signal == nullptr; } + void release(); tti_point tti_rx; uint32_t cc = SCHED_NR_MAX_CARRIERS; + // UE parameters common to all sectors const sched_nr_ue_cfg* cfg = nullptr; bool pending_sr; + // UE parameters that are sector specific + uint32_t dl_cqi; + uint32_t ul_cqi; + harq_proc* h_dl = nullptr; + harq_proc* h_ul = nullptr; + private: - ue_carrier* carrier = nullptr; + struct noop { + void operator()(bool* ptr) {} + }; + std::unique_ptr busy_signal; }; class ue_carrier { public: ue_carrier(uint16_t rnti, uint32_t cc, const sched_nr_ue_cfg& cfg); - bwp_ue try_reserve(tti_point tti_rx); - void push_feedback(srsran::move_callback callback); + slot_ue try_reserve(tti_point tti_rx, const sched_nr_ue_cfg& cfg); + void push_feedback(srsran::move_callback callback); + void set_cfg(const sched_nr_ue_cfg& uecfg); const uint16_t rnti; const uint32_t cc; + // Channel state + uint32_t dl_cqi = 1; + uint32_t ul_cqi = 0; + harq_entity harq_ent; private: - friend class bwp_ue; - void release() { busy = false; } + const sched_nr_ue_cfg* cfg = nullptr; - const sched_nr_ue_cfg* cfg; + bool busy{false}; + tti_point last_tti_rx; srsran::deque > pending_feedback; - bool busy{false}; }; class ue @@ -77,7 +88,7 @@ class ue public: ue(uint16_t rnti, const sched_nr_ue_cfg& cfg); - bwp_ue try_reserve(tti_point tti_rx, uint32_t cc); + slot_ue try_reserve(tti_point tti_rx, uint32_t cc); void set_cfg(const sched_nr_ue_cfg& cfg); diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h index 67a31878f..af1c79734 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h @@ -14,6 +14,7 @@ #define SRSRAN_SCHED_NR_WORKER_H #include "sched_nr_common.h" +#include "sched_nr_rb_grid.h" #include "sched_nr_ue.h" #include "srsran/adt/circular_array.h" #include "srsran/adt/optional.h" @@ -26,23 +27,27 @@ namespace srsenb { namespace sched_nr_impl { -class bwp_worker +class carrier_slot_worker { public: - explicit bwp_worker(uint32_t cc_, ue_map_t& ue_db_) : cc(cc_), ue_db(ue_db_) {} + explicit carrier_slot_worker(uint32_t cc_, const sched_nr_cfg& cfg_) : cc(cc_), cfg(cfg_), res_grid(cc, cfg) {} - void start(tti_point tti_rx_); + void start(tti_point tti_rx_, sched_nr_res_t& bwp_result, ue_map_t& ue_db_); void run(); void end_tti(); bool running() const { return tti_rx.is_valid(); } private: - ue_map_t& ue_db; + void alloc_dl_ues(); + void alloc_ul_ues(); + + const uint32_t cc; + const sched_nr_cfg& cfg; tti_point tti_rx; - uint32_t cc; + slot_grid res_grid; - srsran::circular_array bwp_ues; + srsran::static_circular_map slot_ues; }; class sched_worker_manager @@ -55,22 +60,23 @@ public: void reserve_workers(tti_point tti_rx, srsran::span sf_result_); void start_tti(tti_point tti_rx); - bool run_tti(tti_point tti_rx, uint32_t cc); + bool run_tti(tti_point tti_rx, uint32_t cc, sched_nr_res_t& result); void end_tti(tti_point tti_rx); private: const sched_nr_cfg& cfg; + ue_map_t& ue_db; - struct sf_worker_ctxt { - sem_t sf_sem; - tti_point tti_rx; - srsran::span sf_result; - int worker_count = 0; - std::vector workers; + struct slot_worker_ctxt { + sem_t sf_sem; + tti_point tti_rx; + srsran::span sf_result; + int worker_count = 0; + std::vector workers; }; - std::vector > sf_ctxts; + std::vector > slot_ctxts; - sf_worker_ctxt& get_sf(tti_point tti_rx); + slot_worker_ctxt& get_sf(tti_point tti_rx); }; } // namespace sched_nr_impl diff --git a/srsenb/src/stack/mac/nr/CMakeLists.txt b/srsenb/src/stack/mac/nr/CMakeLists.txt index ee33f96bc..480fb0d24 100644 --- a/srsenb/src/stack/mac/nr/CMakeLists.txt +++ b/srsenb/src/stack/mac/nr/CMakeLists.txt @@ -6,6 +6,6 @@ # the distribution. # -set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc) +set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc sched_nr_rb_grid.cc sched_nr_harq.cc) add_library(srsgnb_mac STATIC ${SOURCES}) diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsenb/src/stack/mac/nr/sched_nr.cc index 83423f734..8d0797318 100644 --- a/srsenb/src/stack/mac/nr/sched_nr.cc +++ b/srsenb/src/stack/mac/nr/sched_nr.cc @@ -15,7 +15,6 @@ namespace srsenb { -using sched_nr_impl::bwp_worker; using sched_nr_impl::sched_worker_manager; using sched_nr_impl::ue; using sched_nr_impl::ue_carrier; @@ -100,7 +99,7 @@ void sched_nr::ue_cfg_impl(uint16_t rnti, const sched_nr_ue_cfg& uecfg) void sched_nr::new_tti(tti_point tti_rx) { - // Lock subframe workers to provided tti_rx + // Lock slot workers for provided tti_rx sched_workers.reserve_workers(tti_rx, sched_results[tti_rx.sf_idx()]); { @@ -113,33 +112,25 @@ void sched_nr::new_tti(tti_point tti_rx) } } +/// Generate {tti,cc} scheduling decision int sched_nr::generate_sched_result(tti_point tti_rx, uint32_t cc, sched_nr_res_t& result) -{ - // Generate {tti,cc} scheduling decision - run_tti(tti_rx, cc); - - // copy scheduling decision result - result = sched_results[tti_rx.sf_idx()][cc]; - - return SRSRAN_SUCCESS; -} - -void sched_nr::run_tti(tti_point tti_rx, uint32_t cc) { // unlocked, parallel region - bool all_workers_finished = sched_workers.run_tti(tti_rx, cc); + bool all_workers_finished = sched_workers.run_tti(tti_rx, cc, result); if (all_workers_finished) { // once all workers of the same subframe finished, synchronize sched outcome with ue_db std::lock_guard lock(ue_db_mutex); sched_workers.end_tti(tti_rx); } + + return SRSRAN_SUCCESS; } -void sched_nr::dl_ack_info(tti_point tti_rx, uint16_t rnti, uint32_t cc, uint32_t tb_idx, bool ack) +void sched_nr::dl_ack_info(uint16_t rnti, uint32_t pid, uint32_t cc, uint32_t tb_idx, bool ack) { pending_events->push_cc_feedback( - rnti, cc, [tti_rx, tb_idx, ack](ue_carrier& ue_cc) { ue_cc.harq_ent.dl_ack_info(tti_rx, tb_idx, ack); }); + rnti, cc, [pid, tb_idx, ack](ue_carrier& ue_cc) { ue_cc.harq_ent.dl_ack_info(pid, tb_idx, ack); }); } void sched_nr::ul_sr_info(tti_point tti_rx, uint16_t rnti) diff --git a/srsenb/src/stack/mac/nr/sched_nr_harq.cc b/srsenb/src/stack/mac/nr/sched_nr_harq.cc new file mode 100644 index 000000000..9c9c0c627 --- /dev/null +++ b/srsenb/src/stack/mac/nr/sched_nr_harq.cc @@ -0,0 +1,46 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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 "srsenb/hdr/stack/mac/nr/sched_nr_harq.h" + +namespace srsenb { +namespace sched_nr_impl { + +bool harq_proc::new_tx(tti_point tti_tx_, const rbgmask_t& rbgmask_, uint32_t mcs, uint32_t ack_delay_) +{ + if (not empty()) { + return false; + } + tti_tx = tti_tx_; + ack_delay = ack_delay_; + rbgmask = rbgmask_; + tb[0].mcs = mcs; + return true; +} + +harq_entity::harq_entity() +{ + dl_harqs.reserve(SCHED_NR_NOF_HARQS); + ul_harqs.reserve(SCHED_NR_NOF_HARQS); + for (uint32_t pid = 0; pid < SCHED_NR_NOF_HARQS; ++pid) { + dl_harqs.emplace_back(pid); + ul_harqs.emplace_back(pid); + } +} + +void harq_entity::new_tti(tti_point tti_rx_) +{ + tti_rx = tti_rx_; +} + +} // namespace sched_nr_impl +} // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc new file mode 100644 index 000000000..c27ff43a7 --- /dev/null +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -0,0 +1,80 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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 "srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h" + +namespace srsenb { +namespace sched_nr_impl { + +slot_grid::slot_grid(uint32_t cc_, const sched_nr_cfg& cfg_) : cc(cc_), cfg(cfg_) {} + +void slot_grid::new_tti(tti_point tti_rx_, sched_nr_res_t& sched_res_) +{ + tti_rx = tti_rx_; + sched_res = &sched_res_; + + pdsch_mask.reset(); + pusch_mask.reset(); + *sched_res = {}; +} + +bool slot_grid::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) +{ + const uint32_t tbs = 100, mcs = 20; + if (ue.h_dl == nullptr) { + return false; + } + if ((pdsch_mask & dl_mask).any()) { + return false; + } + if (sched_res->dl_res.data.full()) { + return false; + } + if (not ue.h_dl->new_tx(tti_tx_dl(), dl_mask, mcs, K1)) { + return false; + } + + pdsch_mask |= dl_mask; + sched_res->dl_res.data.emplace_back(); + sched_nr_data_t& data = sched_res->dl_res.data.back(); + data.tbs.resize(1); + data.tbs[0] = tbs; + + return true; +} + +bool slot_grid::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) +{ + const uint32_t tbs = 100, mcs = 20; + if ((pusch_mask & ul_mask).any()) { + return false; + } + if (sched_res->ul_res.pusch.full()) { + return false; + } + if (not ue.h_ul->new_tx(tti_tx_ul(), ul_mask, mcs, 0)) { + return false; + } + + pusch_mask |= ul_mask; + sched_res->ul_res.pusch.emplace_back(); + sched_nr_data_t& data = sched_res->ul_res.pusch.back(); + data.tbs.resize(1); + data.tbs[0] = tbs; + + return true; +} + +void slot_grid::generate_dcis() {} + +} // namespace sched_nr_impl +} // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue.cc b/srsenb/src/stack/mac/nr/sched_nr_ue.cc index c772978e6..9d3d0dbef 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_ue.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_ue.cc @@ -15,36 +15,86 @@ namespace srsenb { namespace sched_nr_impl { -bwp_ue::bwp_ue(ue_carrier& carrier_, tti_point tti_rx_) : carrier(&carrier_), tti_rx(tti_rx_), cc(carrier_.cc) {} +slot_ue::slot_ue(bool& busy_signal_, tti_point tti_rx_, uint32_t cc_) : + busy_signal(&busy_signal_), tti_rx(tti_rx_), cc(cc_) +{} -bwp_ue::~bwp_ue() +slot_ue::~slot_ue() { - if (carrier != nullptr) { - carrier->release(); + release(); +} + +void slot_ue::release() +{ + if (busy_signal != nullptr) { + *busy_signal = false; } } -ue_carrier::ue_carrier(uint16_t rnti_, uint32_t cc_, const sched_nr_ue_cfg& cfg_) : rnti(rnti_), cc(cc_), cfg(&cfg_) {} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +ue_carrier::ue_carrier(uint16_t rnti_, uint32_t cc_, const sched_nr_ue_cfg& uecfg_) : rnti(rnti_), cc(cc_), cfg(&uecfg_) +{} + +void ue_carrier::set_cfg(const sched_nr_ue_cfg& uecfg) +{ + cfg = &uecfg; +} void ue_carrier::push_feedback(srsran::move_callback callback) { pending_feedback.push_back(std::move(callback)); } -bwp_ue ue_carrier::try_reserve(tti_point tti_rx) +slot_ue ue_carrier::try_reserve(tti_point tti_rx, const sched_nr_ue_cfg& uecfg_) { - if (busy) { - return bwp_ue(); + slot_ue sfu = (busy) ? slot_ue() : slot_ue(busy, tti_rx, cc); + if (sfu.empty()) { + return sfu; } - // successfully acquired + // successfully acquired. Process any CC-specific pending feedback busy = true; + if (cfg != &uecfg_) { + set_cfg(uecfg_); + } while (not pending_feedback.empty()) { pending_feedback.front()(*this); pending_feedback.pop_front(); } - return bwp_ue(*this, tti_rx); + if (not last_tti_rx.is_valid()) { + last_tti_rx = tti_rx; + harq_ent.new_tti(tti_rx); + } else { + while (last_tti_rx++ < tti_rx) { + harq_ent.new_tti(tti_rx); + } + } + + // set UE parameters common to all carriers + sfu.cfg = &uecfg_; + + // copy cc-specific parameters and find available HARQs + sfu.dl_cqi = dl_cqi; + sfu.ul_cqi = ul_cqi; + sfu.h_dl = harq_ent.find_pending_dl_retx(); + if (sfu.h_dl == nullptr) { + sfu.h_dl = harq_ent.find_empty_dl_harq(); + } + sfu.h_ul = harq_ent.find_pending_ul_retx(); + if (sfu.h_ul == nullptr) { + sfu.h_ul = harq_ent.find_empty_ul_harq(); + } + + if (sfu.h_dl == nullptr and sfu.h_ul == nullptr) { + // there needs to be at least one available HARQ for newtx/retx + sfu.release(); + return sfu; + } + return sfu; } +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ue::ue(uint16_t rnti, const sched_nr_ue_cfg& cfg) { for (uint32_t cc = 0; cc < cfg.carriers.size(); ++cc) { @@ -60,18 +110,17 @@ void ue::set_cfg(const sched_nr_ue_cfg& cfg) ue_cfgs[current_idx] = cfg; } -bwp_ue ue::try_reserve(tti_point tti_rx, uint32_t cc) +slot_ue ue::try_reserve(tti_point tti_rx, uint32_t cc) { if (carriers[cc] == nullptr) { - return bwp_ue(); + return slot_ue(); } - bwp_ue sfu = carriers[cc]->try_reserve(tti_rx); + slot_ue sfu = carriers[cc]->try_reserve(tti_rx, ue_cfgs[current_idx]); if (sfu.empty()) { - return bwp_ue(); + return slot_ue(); } // set UE-common parameters sfu.pending_sr = pending_sr; - sfu.cfg = &ue_cfgs[current_idx]; return sfu; } diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index 1f673a086..be64998ac 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -16,7 +16,7 @@ namespace srsenb { namespace sched_nr_impl { /// Called at the beginning of TTI in a locked context, to reserve available UE resources -void bwp_worker::start(tti_point tti_rx_) +void carrier_slot_worker::start(tti_point tti_rx_, sched_nr_res_t& bwp_result_, ue_map_t& ue_db) { srsran_assert(not running(), "scheduler worker::start() called for active worker"); // Try reserve UE cells for this worker @@ -24,63 +24,101 @@ void bwp_worker::start(tti_point tti_rx_) uint16_t rnti = ue_pair.first; ue& u = *ue_pair.second; - bwp_ue sfu0 = u.try_reserve(tti_rx, cc); - if (sfu0.empty()) { + slot_ues.insert(rnti, u.try_reserve(tti_rx, cc)); + if (slot_ues[rnti].empty()) { // Failed to synchronize because UE is being used by another worker + slot_ues.erase(rnti); continue; } - // Synchronization of UE for this {tti, cc} was successful - bwp_ues[rnti] = std::move(sfu0); + // UE acquired successfully for scheduling in this {tti, cc} } + res_grid.new_tti(tti_rx_, bwp_result_); tti_rx = tti_rx_; } -void bwp_worker::run() +void carrier_slot_worker::run() { srsran_assert(running(), "scheduler worker::run() called for non-active worker"); + + // Prioritize PDCCH scheduling for DL and UL data in a RoundRobin fashion + if ((tti_rx.to_uint() & 0x1u) == 0) { + alloc_dl_ues(); + alloc_ul_ues(); + } else { + alloc_ul_ues(); + alloc_dl_ues(); + } + + // Select the winner PDCCH allocation combination, store all the scheduling results + res_grid.generate_dcis(); } -void bwp_worker::end_tti() +void carrier_slot_worker::end_tti() { srsran_assert(running(), "scheduler worker::end() called for non-active worker"); // releases UE resources - for (bwp_ue& u : bwp_ues) { - if (not u.empty()) { - u = {}; - } - } + slot_ues.clear(); tti_rx = {}; } +void carrier_slot_worker::alloc_dl_ues() +{ + if (slot_ues.empty()) { + return; + } + slot_ue& ue = slot_ues.begin()->second; + if (ue.h_dl == nullptr) { + return; + } + + rbgmask_t dlmask(cfg.cells[cc].nof_rbg); + dlmask.fill(0, dlmask.size(), true); + res_grid.alloc_pdsch(ue, dlmask); +} +void carrier_slot_worker::alloc_ul_ues() +{ + if (slot_ues.empty()) { + return; + } + slot_ue& ue = slot_ues.begin()->second; + if (ue.h_ul == nullptr) { + return; + } + + rbgmask_t ulmask(cfg.cells[cc].nof_rbg); + ulmask.fill(0, ulmask.size(), true); + res_grid.alloc_pusch(ue, ulmask); +} + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, const sched_nr_cfg& cfg_) : cfg(cfg_) +sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, const sched_nr_cfg& cfg_) : cfg(cfg_), ue_db(ue_db_) { // Note: For now, we only allow parallelism at the sector level - sf_ctxts.resize(cfg.nof_concurrent_subframes); + slot_ctxts.resize(cfg.nof_concurrent_subframes); for (size_t i = 0; i < cfg.nof_concurrent_subframes; ++i) { - sf_ctxts[i].reset(new sf_worker_ctxt()); - sem_init(&sf_ctxts[i]->sf_sem, 0, 1); - sf_ctxts[i]->workers.reserve(cfg.cells.size()); + slot_ctxts[i].reset(new slot_worker_ctxt()); + sem_init(&slot_ctxts[i]->sf_sem, 0, 1); + slot_ctxts[i]->workers.reserve(cfg.cells.size()); for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { - sf_ctxts[i]->workers.emplace_back(cc, ue_db_); + slot_ctxts[i]->workers.emplace_back(cc, cfg); } } } sched_worker_manager::~sched_worker_manager() { - for (uint32_t sf = 0; sf < sf_ctxts.size(); ++sf) { - sem_destroy(&sf_ctxts[sf]->sf_sem); + for (uint32_t sf = 0; sf < slot_ctxts.size(); ++sf) { + sem_destroy(&slot_ctxts[sf]->sf_sem); } } -sched_worker_manager::sf_worker_ctxt& sched_worker_manager::get_sf(tti_point tti_rx) +sched_worker_manager::slot_worker_ctxt& sched_worker_manager::get_sf(tti_point tti_rx) { - return *sf_ctxts[tti_rx.to_uint() % sf_ctxts.size()]; + return *slot_ctxts[tti_rx.to_uint() % slot_ctxts.size()]; } void sched_worker_manager::reserve_workers(tti_point tti_rx_, srsran::span sf_result_) @@ -91,7 +129,7 @@ void sched_worker_manager::reserve_workers(tti_point tti_rx_, srsran::span(sf_worker_ctxt.workers.size()); } void sched_worker_manager::start_tti(tti_point tti_rx_) @@ -100,11 +138,11 @@ void sched_worker_manager::start_tti(tti_point tti_rx_) srsran_assert(sf_worker_ctxt.tti_rx == tti_rx_, "invalid run_tti(tti, cc) arguments"); for (uint32_t cc = 0; cc < sf_worker_ctxt.workers.size(); ++cc) { - sf_worker_ctxt.workers[cc].start(sf_worker_ctxt.tti_rx); + sf_worker_ctxt.workers[cc].start(sf_worker_ctxt.tti_rx, sf_worker_ctxt.sf_result[cc], ue_db); } } -bool sched_worker_manager::run_tti(tti_point tti_rx_, uint32_t cc) +bool sched_worker_manager::run_tti(tti_point tti_rx_, uint32_t cc, sched_nr_res_t& result) { auto& sf_worker_ctxt = get_sf(tti_rx_); srsran_assert(sf_worker_ctxt.tti_rx == tti_rx_, "invalid run_tti(tti, cc) arguments"); @@ -116,6 +154,9 @@ bool sched_worker_manager::run_tti(tti_point tti_rx_, uint32_t cc) // Get {tti, cc} scheduling decision sf_worker_ctxt.workers[cc].run(); + // copy sched result + result = sf_worker_ctxt.sf_result[cc]; + // decrement the number of active workers --sf_worker_ctxt.worker_count; srsran_assert(sf_worker_ctxt.worker_count >= 0, "invalid number of calls to run_tti(tti, cc)"); @@ -132,6 +173,8 @@ void sched_worker_manager::end_tti(tti_point tti_rx_) for (auto& worker : sf_worker_ctxt.workers) { worker.end_tti(); } + + sf_worker_ctxt.sf_result = {}; sem_post(&sf_worker_ctxt.sf_sem); } diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index 338e514b6..3a2d3da13 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -112,7 +112,7 @@ void sched_nr_cfg_parallel_sf_test() int main() { - srsran::get_background_workers().set_nof_workers(4); + srsran::get_background_workers().set_nof_workers(8); srsenb::sched_nr_cfg_serialized_test(); srsenb::sched_nr_cfg_parallel_cc_test(); From 35a236b1b9101737d35b20e5157ebe087fae85b4 Mon Sep 17 00:00:00 2001 From: Francisco Date: Tue, 22 Jun 2021 17:38:26 +0100 Subject: [PATCH 17/43] sched,nr: fix sched_nr_test. Resolve data race issues. Created new config structs used across the scheduler. --- srsenb/hdr/stack/mac/nr/sched_nr.h | 13 +- srsenb/hdr/stack/mac/nr/sched_nr_common.h | 17 +++ srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 9 +- srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h | 10 +- srsenb/hdr/stack/mac/nr/sched_nr_worker.h | 21 ++-- srsenb/src/stack/mac/nr/sched_nr.cc | 24 ++-- srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 6 +- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 40 +++--- srsenb/test/mac/nr/sched_nr_test.cc | 121 +++++++++++++------ 9 files changed, 171 insertions(+), 90 deletions(-) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr.h b/srsenb/hdr/stack/mac/nr/sched_nr.h index b1cf3502e..55c4441f6 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr.h @@ -16,7 +16,6 @@ #include "sched_nr_common.h" #include "sched_nr_interface.h" #include "sched_nr_ue.h" -#include "sched_nr_worker.h" #include "srsran/adt/pool/cached_alloc.h" #include "srsran/common/tti_point.h" #include @@ -26,13 +25,18 @@ extern "C" { namespace srsenb { +namespace sched_nr_impl { +class sched_worker_manager; +} + class ue_event_manager; class sched_nr final : public sched_nr_interface { public: - sched_nr(const sched_nr_cfg& cfg); + explicit sched_nr(const sched_nr_cfg& sched_cfg); ~sched_nr() override; + int cell_cfg(const std::vector& cell_list); void ue_cfg(uint16_t rnti, const sched_nr_ue_cfg& cfg) override; void new_tti(tti_point tti_rx) override; @@ -45,10 +49,11 @@ private: void ue_cfg_impl(uint16_t rnti, const sched_nr_ue_cfg& cfg); void run_tti(tti_point tti_rx, uint32_t cc); - sched_nr_cfg cfg; + // args + sched_nr_impl::sched_params cfg; using sched_worker_manager = sched_nr_impl::sched_worker_manager; - sched_worker_manager sched_workers; + std::unique_ptr sched_workers; std::array, SCHED_NR_NOF_SUBFRAMES> sched_results; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_common.h b/srsenb/hdr/stack/mac/nr/sched_nr_common.h index 996003cc2..75d7ad1aa 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_common.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_common.h @@ -25,6 +25,23 @@ const static size_t SCHED_NR_NOF_HARQS = 16; namespace sched_nr_impl { +struct sched_cell_params { + const uint32_t cc; + const sched_nr_cell_cfg cell_cfg; + const sched_nr_cfg& sched_cfg; + + sched_cell_params(uint32_t cc_, const sched_nr_cell_cfg& cell, const sched_nr_cfg& sched_cfg_) : + cc(cc_), cell_cfg(cell), sched_cfg(sched_cfg_) + {} +}; + +struct sched_params { + const sched_nr_cfg sched_cfg; + std::vector cells; + + explicit sched_params(const sched_nr_cfg& sched_cfg_) : sched_cfg(sched_cfg_) {} +}; + using rbgmask_t = srsran::bounded_bitset; } // namespace sched_nr_impl diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index e38d4e8ad..f274daf8f 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -25,14 +25,15 @@ const static size_t SCHED_NR_MAX_PUSCH_DATA = 16; const static size_t SCHED_NR_MAX_TB = 2; struct sched_nr_cell_cfg { - uint32_t nof_prb; - uint32_t nof_rbg; + uint32_t nof_prb = 100; + uint32_t nof_rbg = 25; + uint32_t K0 = 0; + uint32_t K1 = 4; + uint32_t K2 = 4; }; struct sched_nr_cfg { uint32_t nof_concurrent_subframes = 1; - - srsran::bounded_vector cells; }; struct sched_nr_ue_cc_cfg { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h index 38ae6a366..c8962f031 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h @@ -22,7 +22,7 @@ namespace sched_nr_impl { class slot_grid { public: - explicit slot_grid(uint32_t cc, const sched_nr_cfg& cfg_); + explicit slot_grid(const sched_cell_params& cfg_); void new_tti(tti_point tti_rx_, sched_nr_res_t& sched_res_); bool alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask); bool alloc_pusch(slot_ue& ue, const rbgmask_t& dl_mask); @@ -30,13 +30,11 @@ public: void generate_dcis(); tti_point tti_tx_dl() const { return tti_rx + TX_ENB_DELAY; } - tti_point tti_tx_ul() const { return tti_tx_dl() + K2; } + tti_point tti_tx_ul() const { return tti_tx_dl() + cfg.cell_cfg.K2; } -private: - static const size_t K0 = 0, K1 = 4, K2 = 4; - const uint32_t cc; - const sched_nr_cfg& cfg; + const sched_cell_params& cfg; +private: tti_point tti_rx; rbgmask_t pdsch_mask; rbgmask_t pusch_mask; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h index af1c79734..c8cc19165 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h @@ -27,10 +27,10 @@ namespace srsenb { namespace sched_nr_impl { -class carrier_slot_worker +class slot_cc_worker { public: - explicit carrier_slot_worker(uint32_t cc_, const sched_nr_cfg& cfg_) : cc(cc_), cfg(cfg_), res_grid(cc, cfg) {} + explicit slot_cc_worker(const sched_cell_params& cell_params) : cfg(cell_params), res_grid(cfg) {} void start(tti_point tti_rx_, sched_nr_res_t& bwp_result, ue_map_t& ue_db_); void run(); @@ -41,8 +41,7 @@ private: void alloc_dl_ues(); void alloc_ul_ues(); - const uint32_t cc; - const sched_nr_cfg& cfg; + const sched_cell_params& cfg; tti_point tti_rx; slot_grid res_grid; @@ -53,7 +52,7 @@ private: class sched_worker_manager { public: - explicit sched_worker_manager(ue_map_t& ue_db_, const sched_nr_cfg& cfg_); + explicit sched_worker_manager(ue_map_t& ue_db_, const sched_params& cfg_); sched_worker_manager(const sched_worker_manager&) = delete; sched_worker_manager(sched_worker_manager&&) = delete; ~sched_worker_manager(); @@ -64,15 +63,15 @@ public: void end_tti(tti_point tti_rx); private: - const sched_nr_cfg& cfg; + const sched_params& cfg; ue_map_t& ue_db; struct slot_worker_ctxt { - sem_t sf_sem; - tti_point tti_rx; - srsran::span sf_result; - int worker_count = 0; - std::vector workers; + sem_t sf_sem; // lock of all workers of the same slot. unlocked by last slot_cc_worker + tti_point tti_rx; + srsran::span sf_result; + std::atomic worker_count{0}; // variable shared across slot_cc_workers + std::vector workers; }; std::vector > slot_ctxts; diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsenb/src/stack/mac/nr/sched_nr.cc index 8d0797318..66b6f8a54 100644 --- a/srsenb/src/stack/mac/nr/sched_nr.cc +++ b/srsenb/src/stack/mac/nr/sched_nr.cc @@ -11,6 +11,7 @@ */ #include "srsenb/hdr/stack/mac/nr/sched_nr.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_worker.h" #include "srsran/common/thread_pool.h" namespace srsenb { @@ -77,12 +78,21 @@ private: /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -sched_nr::sched_nr(const sched_nr_cfg& cfg_) : - cfg(cfg_), pending_events(new ue_event_manager(ue_db)), sched_workers(ue_db, cfg) -{} +sched_nr::sched_nr(const sched_nr_cfg& sched_cfg) : cfg(sched_cfg), pending_events(new ue_event_manager(ue_db)) {} sched_nr::~sched_nr() {} +int sched_nr::cell_cfg(const std::vector& cell_list) +{ + cfg.cells.reserve(cell_list.size()); + for (uint32_t cc = 0; cc < cell_list.size(); ++cc) { + cfg.cells.emplace_back(cc, cell_list[cc], cfg.sched_cfg); + } + + sched_workers.reset(new sched_nr_impl::sched_worker_manager(ue_db, cfg)); + return SRSRAN_SUCCESS; +} + void sched_nr::ue_cfg(uint16_t rnti, const sched_nr_ue_cfg& uecfg) { pending_events->push_event([this, rnti, uecfg]() { ue_cfg_impl(rnti, uecfg); }); @@ -100,7 +110,7 @@ void sched_nr::ue_cfg_impl(uint16_t rnti, const sched_nr_ue_cfg& uecfg) void sched_nr::new_tti(tti_point tti_rx) { // Lock slot workers for provided tti_rx - sched_workers.reserve_workers(tti_rx, sched_results[tti_rx.sf_idx()]); + sched_workers->reserve_workers(tti_rx, sched_results[tti_rx.sf_idx()]); { // synchronize {tti,cc} state. e.g. reserve UE resources for {tti,cc} decision, process feedback @@ -108,7 +118,7 @@ void sched_nr::new_tti(tti_point tti_rx) // Process pending events pending_events->new_tti(); - sched_workers.start_tti(tti_rx); + sched_workers->start_tti(tti_rx); } } @@ -116,12 +126,12 @@ void sched_nr::new_tti(tti_point tti_rx) int sched_nr::generate_sched_result(tti_point tti_rx, uint32_t cc, sched_nr_res_t& result) { // unlocked, parallel region - bool all_workers_finished = sched_workers.run_tti(tti_rx, cc, result); + bool all_workers_finished = sched_workers->run_tti(tti_rx, cc, result); if (all_workers_finished) { // once all workers of the same subframe finished, synchronize sched outcome with ue_db std::lock_guard lock(ue_db_mutex); - sched_workers.end_tti(tti_rx); + sched_workers->end_tti(tti_rx); } return SRSRAN_SUCCESS; diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc index c27ff43a7..d244d9de8 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -15,7 +15,9 @@ namespace srsenb { namespace sched_nr_impl { -slot_grid::slot_grid(uint32_t cc_, const sched_nr_cfg& cfg_) : cc(cc_), cfg(cfg_) {} +slot_grid::slot_grid(const sched_cell_params& cfg_) : + cfg(cfg_), pdsch_mask(cfg.cell_cfg.nof_rbg), pusch_mask(cfg.cell_cfg.nof_rbg) +{} void slot_grid::new_tti(tti_point tti_rx_, sched_nr_res_t& sched_res_) { @@ -39,7 +41,7 @@ bool slot_grid::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) if (sched_res->dl_res.data.full()) { return false; } - if (not ue.h_dl->new_tx(tti_tx_dl(), dl_mask, mcs, K1)) { + if (not ue.h_dl->new_tx(tti_tx_dl(), dl_mask, mcs, cfg.cell_cfg.K1)) { return false; } diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index be64998ac..ad8089844 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -16,7 +16,7 @@ namespace srsenb { namespace sched_nr_impl { /// Called at the beginning of TTI in a locked context, to reserve available UE resources -void carrier_slot_worker::start(tti_point tti_rx_, sched_nr_res_t& bwp_result_, ue_map_t& ue_db) +void slot_cc_worker::start(tti_point tti_rx_, sched_nr_res_t& bwp_result_, ue_map_t& ue_db) { srsran_assert(not running(), "scheduler worker::start() called for active worker"); // Try reserve UE cells for this worker @@ -24,7 +24,7 @@ void carrier_slot_worker::start(tti_point tti_rx_, sched_nr_res_t& bwp_result_, uint16_t rnti = ue_pair.first; ue& u = *ue_pair.second; - slot_ues.insert(rnti, u.try_reserve(tti_rx, cc)); + slot_ues.insert(rnti, u.try_reserve(tti_rx, cfg.cc)); if (slot_ues[rnti].empty()) { // Failed to synchronize because UE is being used by another worker slot_ues.erase(rnti); @@ -37,7 +37,7 @@ void carrier_slot_worker::start(tti_point tti_rx_, sched_nr_res_t& bwp_result_, tti_rx = tti_rx_; } -void carrier_slot_worker::run() +void slot_cc_worker::run() { srsran_assert(running(), "scheduler worker::run() called for non-active worker"); @@ -54,7 +54,7 @@ void carrier_slot_worker::run() res_grid.generate_dcis(); } -void carrier_slot_worker::end_tti() +void slot_cc_worker::end_tti() { srsran_assert(running(), "scheduler worker::end() called for non-active worker"); @@ -64,7 +64,7 @@ void carrier_slot_worker::end_tti() tti_rx = {}; } -void carrier_slot_worker::alloc_dl_ues() +void slot_cc_worker::alloc_dl_ues() { if (slot_ues.empty()) { return; @@ -74,11 +74,11 @@ void carrier_slot_worker::alloc_dl_ues() return; } - rbgmask_t dlmask(cfg.cells[cc].nof_rbg); + rbgmask_t dlmask(cfg.cell_cfg.nof_rbg); dlmask.fill(0, dlmask.size(), true); res_grid.alloc_pdsch(ue, dlmask); } -void carrier_slot_worker::alloc_ul_ues() +void slot_cc_worker::alloc_ul_ues() { if (slot_ues.empty()) { return; @@ -88,23 +88,23 @@ void carrier_slot_worker::alloc_ul_ues() return; } - rbgmask_t ulmask(cfg.cells[cc].nof_rbg); + rbgmask_t ulmask(cfg.cell_cfg.nof_rbg); ulmask.fill(0, ulmask.size(), true); res_grid.alloc_pusch(ue, ulmask); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, const sched_nr_cfg& cfg_) : cfg(cfg_), ue_db(ue_db_) +sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, const sched_params& cfg_) : cfg(cfg_), ue_db(ue_db_) { // Note: For now, we only allow parallelism at the sector level - slot_ctxts.resize(cfg.nof_concurrent_subframes); - for (size_t i = 0; i < cfg.nof_concurrent_subframes; ++i) { + slot_ctxts.resize(cfg.sched_cfg.nof_concurrent_subframes); + for (size_t i = 0; i < cfg.sched_cfg.nof_concurrent_subframes; ++i) { slot_ctxts[i].reset(new slot_worker_ctxt()); sem_init(&slot_ctxts[i]->sf_sem, 0, 1); slot_ctxts[i]->workers.reserve(cfg.cells.size()); for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { - slot_ctxts[i]->workers.emplace_back(cc, cfg); + slot_ctxts[i]->workers.emplace_back(cfg.cells[cc]); } } } @@ -127,9 +127,9 @@ void sched_worker_manager::reserve_workers(tti_point tti_rx_, srsran::span(sf_worker_ctxt.workers.size()); + sf_worker_ctxt.sf_result = sf_result_; + sf_worker_ctxt.tti_rx = tti_rx_; + sf_worker_ctxt.worker_count.store(static_cast(sf_worker_ctxt.workers.size()), std::memory_order_relaxed); } void sched_worker_manager::start_tti(tti_point tti_rx_) @@ -146,10 +146,6 @@ bool sched_worker_manager::run_tti(tti_point tti_rx_, uint32_t cc, sched_nr_res_ { auto& sf_worker_ctxt = get_sf(tti_rx_); srsran_assert(sf_worker_ctxt.tti_rx == tti_rx_, "invalid run_tti(tti, cc) arguments"); - if (not sf_worker_ctxt.workers[cc].running()) { - // run for this tti and cc was already called - return false; - } // Get {tti, cc} scheduling decision sf_worker_ctxt.workers[cc].run(); @@ -158,9 +154,9 @@ bool sched_worker_manager::run_tti(tti_point tti_rx_, uint32_t cc, sched_nr_res_ result = sf_worker_ctxt.sf_result[cc]; // decrement the number of active workers - --sf_worker_ctxt.worker_count; - srsran_assert(sf_worker_ctxt.worker_count >= 0, "invalid number of calls to run_tti(tti, cc)"); - return sf_worker_ctxt.worker_count == 0; + int rem_workers = sf_worker_ctxt.worker_count.fetch_sub(1, std::memory_order_release) - 1; + srsran_assert(rem_workers >= 0, "invalid number of calls to run_tti(tti, cc)"); + return rem_workers == 0; } void sched_worker_manager::end_tti(tti_point tti_rx_) diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index 3a2d3da13..d60a3b265 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -16,12 +16,50 @@ namespace srsenb { +struct task_job_manager { + std::mutex mutex; + std::condition_variable cond_var; + int tasks = 0; + int pdsch_count = 0; + int max_tasks = std::numeric_limits::max() / 2; + + void start_task() + { + std::unique_lock lock(mutex); + while (tasks >= max_tasks) { + cond_var.wait(lock); + } + tasks++; + } + void finish_task(const sched_nr_res_t& res) + { + std::unique_lock lock(mutex); + TESTASSERT(res.dl_res.data.size() <= 1); + pdsch_count += res.dl_res.data.size(); + if (tasks-- >= max_tasks or tasks == 0) { + cond_var.notify_one(); + } + } + void wait_task_finish() + { + std::unique_lock lock(mutex); + while (tasks > 0) { + cond_var.wait(lock); + } + } +}; + void sched_nr_cfg_serialized_test() { - sched_nr_cfg cfg; - cfg.cells.resize(1); + uint32_t max_nof_ttis = 1000; + task_job_manager tasks; + + sched_nr_cfg cfg; + std::vector cells_cfg; + cells_cfg.resize(1); sched_nr sched(cfg); + sched.cell_cfg(cells_cfg); sched_nr_ue_cfg uecfg; uecfg.carriers.resize(1); @@ -31,90 +69,105 @@ void sched_nr_cfg_serialized_test() for (uint32_t nof_ttis = 0; nof_ttis < 1000; ++nof_ttis) { tti_point tti(nof_ttis % 10240); sched.new_tti(tti); - for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { + for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { + tasks.start_task(); sched_nr_res_t res; TESTASSERT(sched.generate_sched_result(tti, cc, res) == SRSRAN_SUCCESS); + tasks.finish_task(res); } } + + printf("TESTER: %f PDSCH/slot were allocated\n", tasks.pdsch_count / (double)max_nof_ttis); } void sched_nr_cfg_parallel_cc_test() { - std::atomic tasks{0}; + uint32_t max_nof_ttis = 1000; + task_job_manager tasks; - sched_nr_cfg cfg; - cfg.cells.resize(4); + sched_nr_cfg cfg; + std::vector cells_cfg; + cells_cfg.resize(4); sched_nr sched(cfg); + sched.cell_cfg(cells_cfg); sched_nr_ue_cfg uecfg; - uecfg.carriers.resize(cfg.cells.size()); - for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { + uecfg.carriers.resize(cells_cfg.size()); + for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { uecfg.carriers[cc].active = true; } sched.ue_cfg(0x46, uecfg); - for (uint32_t nof_ttis = 0; nof_ttis < 1000; ++nof_ttis) { + for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { tti_point tti(nof_ttis % 10240); sched.new_tti(tti); - ++tasks; - srsran::get_background_workers().push_task([&cfg, &sched, tti, &tasks]() { - for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { + for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { + tasks.start_task(); + srsran::get_background_workers().push_task([cc, &sched, tti, &tasks]() { sched_nr_res_t res; TESTASSERT(sched.generate_sched_result(tti, cc, res) == SRSRAN_SUCCESS); - } - --tasks; - }); + tasks.finish_task(res); + }); + } } - while (tasks > 0) { - usleep(100); - } + tasks.wait_task_finish(); + + printf("TESTER: %f PDSCH/slot were allocated\n", tasks.pdsch_count / (double)max_nof_ttis); } void sched_nr_cfg_parallel_sf_test() { - uint32_t nof_sectors = 2; - std::atomic tasks{0}; + uint32_t max_nof_ttis = 1000; + uint32_t nof_sectors = 2; + task_job_manager tasks; sched_nr_cfg cfg; cfg.nof_concurrent_subframes = 2; - cfg.cells.resize(nof_sectors); + std::vector cells_cfg; + cells_cfg.resize(nof_sectors); sched_nr sched(cfg); + sched.cell_cfg(cells_cfg); sched_nr_ue_cfg uecfg; - uecfg.carriers.resize(cfg.cells.size()); - for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { + uecfg.carriers.resize(cells_cfg.size()); + for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { uecfg.carriers[cc].active = true; } sched.ue_cfg(0x46, uecfg); - for (uint32_t nof_ttis = 0; nof_ttis < 1000; ++nof_ttis) { + for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { tti_point tti(nof_ttis % 10240); sched.new_tti(tti); - ++tasks; - srsran::get_background_workers().push_task([&cfg, &sched, tti, &tasks]() { - for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { + tasks.start_task(); + for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { + srsran::get_background_workers().push_task([cc, &sched, tti, &tasks]() { sched_nr_res_t res; TESTASSERT(sched.generate_sched_result(tti, cc, res) == SRSRAN_SUCCESS); - } - --tasks; - }); + tasks.finish_task(res); + }); + } } - while (tasks > 0) { - usleep(100); - } + tasks.wait_task_finish(); + + printf("TESTER: %f PDSCH/slot were allocated\n", tasks.pdsch_count / (double)max_nof_ttis); } } // namespace srsenb int main() { + auto& mac_logger = srslog::fetch_basic_logger("MAC"); + mac_logger.set_level(srslog::basic_levels::debug); + auto& pool_logger = srslog::fetch_basic_logger("POOL"); + pool_logger.set_level(srslog::basic_levels::debug); + srsran::get_background_workers().set_nof_workers(8); srsenb::sched_nr_cfg_serialized_test(); srsenb::sched_nr_cfg_parallel_cc_test(); - srsenb::sched_nr_cfg_parallel_sf_test(); + // srsenb::sched_nr_cfg_parallel_sf_test(); } \ No newline at end of file From d950433cbd613f17e892308b4cba2038a41e1c90 Mon Sep 17 00:00:00 2001 From: Francisco Date: Tue, 22 Jun 2021 18:33:30 +0100 Subject: [PATCH 18/43] sched,nr: fix time-domain parallelization sched nr test. creation of util class to handle acquisition of boolean resources --- srsenb/hdr/stack/mac/nr/sched_nr_common.h | 40 ++++++++++++++++++++++ srsenb/hdr/stack/mac/nr/sched_nr_ue.h | 13 +++---- srsenb/src/stack/mac/nr/sched_nr_ue.cc | 11 +++--- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 9 +++-- srsenb/test/mac/nr/sched_nr_test.cc | 15 ++++---- 5 files changed, 65 insertions(+), 23 deletions(-) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_common.h b/srsenb/hdr/stack/mac/nr/sched_nr_common.h index 75d7ad1aa..701fb1d31 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_common.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_common.h @@ -44,6 +44,46 @@ struct sched_params { using rbgmask_t = srsran::bounded_bitset; +struct resource_guard { +public: + resource_guard() = default; + resource_guard(const resource_guard& other) = delete; + resource_guard(resource_guard&& other) = delete; + resource_guard& operator=(const resource_guard& other) = delete; + resource_guard& operator=(resource_guard&& other) = delete; + bool busy() const { return flag; } + + struct token { + token() = default; + token(resource_guard& parent) : flag(parent.busy() ? nullptr : &parent.flag) + { + if (flag != nullptr) { + *flag = true; + } + } + token(token&&) noexcept = default; + token& operator=(token&&) noexcept = default; + void release() { flag.reset(); } + bool owns_token() const { return flag != nullptr; } + bool empty() const { return flag == nullptr; } + + private: + struct release_deleter { + void operator()(bool* ptr) + { + if (ptr != nullptr) { + srsran_assert(*ptr == true, "resource token: detected inconsistency token state"); + *ptr = false; + } + } + }; + std::unique_ptr flag; + }; + +private: + bool flag = false; +}; + } // namespace sched_nr_impl } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h index 16688f11c..327d89d3e 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h @@ -30,11 +30,11 @@ class slot_ue { public: slot_ue() = default; - explicit slot_ue(bool& busy_signal, tti_point tti_rx_, uint32_t cc); + explicit slot_ue(resource_guard::token ue_token, tti_point tti_rx_, uint32_t cc); ~slot_ue(); slot_ue(slot_ue&&) noexcept = default; slot_ue& operator=(slot_ue&&) noexcept = default; - bool empty() const { return busy_signal == nullptr; } + bool empty() const { return ue_token.empty(); } void release(); tti_point tti_rx; @@ -51,10 +51,7 @@ public: harq_proc* h_ul = nullptr; private: - struct noop { - void operator()(bool* ptr) {} - }; - std::unique_ptr busy_signal; + resource_guard::token ue_token; }; class ue_carrier @@ -77,8 +74,8 @@ public: private: const sched_nr_ue_cfg* cfg = nullptr; - bool busy{false}; - tti_point last_tti_rx; + resource_guard busy; + tti_point last_tti_rx; srsran::deque > pending_feedback; }; diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue.cc b/srsenb/src/stack/mac/nr/sched_nr_ue.cc index 9d3d0dbef..5e8d3b570 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_ue.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_ue.cc @@ -15,8 +15,8 @@ namespace srsenb { namespace sched_nr_impl { -slot_ue::slot_ue(bool& busy_signal_, tti_point tti_rx_, uint32_t cc_) : - busy_signal(&busy_signal_), tti_rx(tti_rx_), cc(cc_) +slot_ue::slot_ue(resource_guard::token ue_token_, tti_point tti_rx_, uint32_t cc_) : + ue_token(std::move(ue_token_)), tti_rx(tti_rx_), cc(cc_) {} slot_ue::~slot_ue() @@ -26,9 +26,7 @@ slot_ue::~slot_ue() void slot_ue::release() { - if (busy_signal != nullptr) { - *busy_signal = false; - } + ue_token.release(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -48,12 +46,11 @@ void ue_carrier::push_feedback(srsran::move_callback callback slot_ue ue_carrier::try_reserve(tti_point tti_rx, const sched_nr_ue_cfg& uecfg_) { - slot_ue sfu = (busy) ? slot_ue() : slot_ue(busy, tti_rx, cc); + slot_ue sfu(busy, tti_rx, cc); if (sfu.empty()) { return sfu; } // successfully acquired. Process any CC-specific pending feedback - busy = true; if (cfg != &uecfg_) { set_cfg(uecfg_); } diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index ad8089844..50ed4d71f 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -111,8 +111,13 @@ sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, const sched_params& sched_worker_manager::~sched_worker_manager() { - for (uint32_t sf = 0; sf < slot_ctxts.size(); ++sf) { - sem_destroy(&slot_ctxts[sf]->sf_sem); + // acquire all slot worker contexts + for (auto& slot_ctxt : slot_ctxts) { + sem_wait(&slot_ctxt->sf_sem); + } + // destroy all slot worker contexts + for (auto& slot_ctxt : slot_ctxts) { + sem_destroy(&slot_ctxt->sf_sem); } } diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index d60a3b265..75c2d7522 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -20,6 +20,7 @@ struct task_job_manager { std::mutex mutex; std::condition_variable cond_var; int tasks = 0; + int res_count = 0; int pdsch_count = 0; int max_tasks = std::numeric_limits::max() / 2; @@ -35,6 +36,7 @@ struct task_job_manager { { std::unique_lock lock(mutex); TESTASSERT(res.dl_res.data.size() <= 1); + res_count++; pdsch_count += res.dl_res.data.size(); if (tasks-- >= max_tasks or tasks == 0) { cond_var.notify_one(); @@ -47,6 +49,7 @@ struct task_job_manager { cond_var.wait(lock); } } + void print_results() const { printf("TESTER: %f PDSCH/{slot,cc} were allocated\n", pdsch_count / (double)res_count); } }; void sched_nr_cfg_serialized_test() @@ -66,7 +69,7 @@ void sched_nr_cfg_serialized_test() uecfg.carriers[0].active = true; sched.ue_cfg(0x46, uecfg); - for (uint32_t nof_ttis = 0; nof_ttis < 1000; ++nof_ttis) { + for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { tti_point tti(nof_ttis % 10240); sched.new_tti(tti); for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { @@ -77,7 +80,7 @@ void sched_nr_cfg_serialized_test() } } - printf("TESTER: %f PDSCH/slot were allocated\n", tasks.pdsch_count / (double)max_nof_ttis); + tasks.print_results(); } void sched_nr_cfg_parallel_cc_test() @@ -114,7 +117,7 @@ void sched_nr_cfg_parallel_cc_test() tasks.wait_task_finish(); - printf("TESTER: %f PDSCH/slot were allocated\n", tasks.pdsch_count / (double)max_nof_ttis); + tasks.print_results(); } void sched_nr_cfg_parallel_sf_test() @@ -141,8 +144,8 @@ void sched_nr_cfg_parallel_sf_test() for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { tti_point tti(nof_ttis % 10240); sched.new_tti(tti); - tasks.start_task(); for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { + tasks.start_task(); srsran::get_background_workers().push_task([cc, &sched, tti, &tasks]() { sched_nr_res_t res; TESTASSERT(sched.generate_sched_result(tti, cc, res) == SRSRAN_SUCCESS); @@ -153,7 +156,7 @@ void sched_nr_cfg_parallel_sf_test() tasks.wait_task_finish(); - printf("TESTER: %f PDSCH/slot were allocated\n", tasks.pdsch_count / (double)max_nof_ttis); + tasks.print_results(); } } // namespace srsenb @@ -169,5 +172,5 @@ int main() srsenb::sched_nr_cfg_serialized_test(); srsenb::sched_nr_cfg_parallel_cc_test(); - // srsenb::sched_nr_cfg_parallel_sf_test(); + srsenb::sched_nr_cfg_parallel_sf_test(); } \ No newline at end of file From f1b3cfc76457d00b7f64dfb7423c96244592fbbb Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 23 Jun 2021 13:11:42 +0100 Subject: [PATCH 19/43] sched,nr: implementation of sched NR harq retxs. Refactor of rb grid classes. --- srsenb/hdr/stack/mac/nr/sched_nr.h | 15 +-- srsenb/hdr/stack/mac/nr/sched_nr_common.h | 19 ++-- srsenb/hdr/stack/mac/nr/sched_nr_harq.h | 27 +++-- srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 114 ++++++++++++------- srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h | 78 +++++++++++-- srsenb/hdr/stack/mac/nr/sched_nr_ue.h | 41 ++++--- srsenb/hdr/stack/mac/nr/sched_nr_worker.h | 27 +++-- srsenb/src/stack/mac/nr/sched_nr.cc | 16 +-- srsenb/src/stack/mac/nr/sched_nr_harq.cc | 81 +++++++++++-- srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 100 ++++++++++------ srsenb/src/stack/mac/nr/sched_nr_ue.cc | 38 +++---- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 30 +++-- srsenb/test/mac/nr/sched_nr_test.cc | 41 ++++--- 13 files changed, 410 insertions(+), 217 deletions(-) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr.h b/srsenb/hdr/stack/mac/nr/sched_nr.h index 55c4441f6..11e1ba082 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr.h @@ -34,20 +34,19 @@ class ue_event_manager; class sched_nr final : public sched_nr_interface { public: - explicit sched_nr(const sched_nr_cfg& sched_cfg); + explicit sched_nr(const sched_cfg_t& sched_cfg); ~sched_nr() override; - int cell_cfg(const std::vector& cell_list); - void ue_cfg(uint16_t rnti, const sched_nr_ue_cfg& cfg) override; + int cell_cfg(const std::vector& cell_list); + void ue_cfg(uint16_t rnti, const ue_cfg_t& cfg) override; - void new_tti(tti_point tti_rx) override; - int generate_sched_result(tti_point tti_rx, uint32_t cc, sched_nr_res_t& result); + void slot_indication(tti_point tti_rx) override; + int generate_sched_result(tti_point tti_rx, uint32_t cc, tti_request_t& tti_req); void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) override; void ul_sr_info(tti_point tti_rx, uint16_t rnti) override; private: - void ue_cfg_impl(uint16_t rnti, const sched_nr_ue_cfg& cfg); - void run_tti(tti_point tti_rx, uint32_t cc); + void ue_cfg_impl(uint16_t rnti, const ue_cfg_t& cfg); // args sched_nr_impl::sched_params cfg; @@ -55,8 +54,6 @@ private: using sched_worker_manager = sched_nr_impl::sched_worker_manager; std::unique_ptr sched_workers; - std::array, SCHED_NR_NOF_SUBFRAMES> sched_results; - using ue_map_t = sched_nr_impl::ue_map_t; std::mutex ue_db_mutex; ue_map_t ue_db; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_common.h b/srsenb/hdr/stack/mac/nr/sched_nr_common.h index 701fb1d31..583e47dd3 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_common.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_common.h @@ -20,29 +20,32 @@ namespace srsenb { const static size_t SCHED_NR_MAX_USERS = 4; const static size_t SCHED_NR_NOF_SUBFRAMES = 10; -const static size_t SCHED_NR_MAX_NOF_RBGS = 25; const static size_t SCHED_NR_NOF_HARQS = 16; namespace sched_nr_impl { +using sched_cfg_t = sched_nr_interface::sched_cfg_t; +using cell_cfg_t = sched_nr_interface::cell_cfg_t; + struct sched_cell_params { - const uint32_t cc; - const sched_nr_cell_cfg cell_cfg; - const sched_nr_cfg& sched_cfg; + const uint32_t cc; + const cell_cfg_t cell_cfg; + const sched_cfg_t& sched_cfg; - sched_cell_params(uint32_t cc_, const sched_nr_cell_cfg& cell, const sched_nr_cfg& sched_cfg_) : + sched_cell_params(uint32_t cc_, const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_) : cc(cc_), cell_cfg(cell), sched_cfg(sched_cfg_) {} }; struct sched_params { - const sched_nr_cfg sched_cfg; + const sched_cfg_t sched_cfg; std::vector cells; - explicit sched_params(const sched_nr_cfg& sched_cfg_) : sched_cfg(sched_cfg_) {} + explicit sched_params(const sched_cfg_t& sched_cfg_) : sched_cfg(sched_cfg_) {} }; -using rbgmask_t = srsran::bounded_bitset; +using pdcchmask_t = srsran::bounded_bitset; +using rbgmask_t = srsran::bounded_bitset; struct resource_guard { public: diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h index e090e109a..17bdd0adb 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h @@ -25,14 +25,23 @@ class harq_proc public: explicit harq_proc(uint32_t id_, uint32_t max_nof_tb_ = 1) : pid(id_), max_nof_tb(max_nof_tb_) {} - bool empty() const { return not tb[0].active and not tb[1].active; } + bool empty() const + { + return std::none_of(tb.begin(), tb.end(), [](const tb_t& t) { return t.active; }); + } bool empty(uint32_t tb_idx) const { return tb[tb_idx].active; } + bool has_pending_retx(tti_point tti_rx) const { return not empty() and not tb[0].ack_state and tti_ack <= tti_rx; } + uint32_t nof_retx() const { return tb[0].n_rtx; } + uint32_t max_nof_retx() const { return max_retx; } + uint32_t tbs() const { return tb[0].tbs; } - void ack_info(uint32_t tb_idx, bool ack) { tb[tb_idx].ack_state = ack; } + bool ack_info(uint32_t tb_idx, bool ack); - bool has_pending_retx(tti_point tti_rx) const { return not empty() and tti_tx + ack_delay <= tti_rx; } - - bool new_tx(tti_point tti_tx, const rbgmask_t& rbgmask, uint32_t mcs, uint32_t ack_delay); + void new_tti(tti_point tti_rx); + void reset(); + bool + new_tx(tti_point tti_tx, tti_point tti_ack, const rbgmask_t& rbgmask, uint32_t mcs, uint32_t tbs, uint32_t max_retx); + bool new_retx(tti_point tti_tx, tti_point tti_ack, const rbgmask_t& rbgmask, int* mcs, int* tbs); const uint32_t pid; @@ -43,12 +52,14 @@ private: bool ndi = false; uint32_t n_rtx = 0; uint32_t mcs = 0; + uint32_t tbs = 0; }; const uint32_t max_nof_tb; + uint32_t max_retx = 1; tti_point tti_tx; - uint32_t ack_delay = 0; + tti_point tti_ack; rbgmask_t rbgmask; std::array tb; }; @@ -56,13 +67,11 @@ private: class harq_entity { public: - harq_entity(); + explicit harq_entity(uint32_t nof_harq_procs = 16); void new_tti(tti_point tti_rx_); void dl_ack_info(uint32_t pid, uint32_t tb_idx, bool ack) { dl_harqs[pid].ack_info(tb_idx, ack); } - harq_proc& get_dl_harq(uint32_t pid) { return dl_harqs[pid]; } - harq_proc* find_pending_dl_retx() { return find_dl([this](const harq_proc& h) { return h.has_pending_retx(tti_rx); }); diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index f274daf8f..e56355f97 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -13,60 +13,90 @@ #ifndef SRSRAN_SCHED_NR_INTERFACE_H #define SRSRAN_SCHED_NR_INTERFACE_H +#include "srsran/adt/bounded_bitset.h" #include "srsran/adt/bounded_vector.h" #include "srsran/common/tti_point.h" +#include "srsran/phy/phch/dci_nr.h" namespace srsenb { const static size_t SCHED_NR_MAX_CARRIERS = 4; const static uint16_t SCHED_NR_INVALID_RNTI = 0; const static size_t SCHED_NR_MAX_PDSCH_DATA = 16; -const static size_t SCHED_NR_MAX_PUSCH_DATA = 16; -const static size_t SCHED_NR_MAX_TB = 2; - -struct sched_nr_cell_cfg { - uint32_t nof_prb = 100; - uint32_t nof_rbg = 25; - uint32_t K0 = 0; - uint32_t K1 = 4; - uint32_t K2 = 4; -}; - -struct sched_nr_cfg { - uint32_t nof_concurrent_subframes = 1; -}; - -struct sched_nr_ue_cc_cfg { - bool active = false; -}; - -struct sched_nr_ue_cfg { - srsran::bounded_vector carriers; -}; - -struct sched_nr_data_t { - srsran::bounded_vector tbs; -}; - -struct sched_nr_dl_res_t { - srsran::bounded_vector data; -}; - -struct sched_nr_ul_res_t { - srsran::bounded_vector pusch; -}; - -struct sched_nr_res_t { - sched_nr_dl_res_t dl_res; - sched_nr_ul_res_t ul_res; -}; +const static size_t SCHED_NR_MAX_NOF_RBGS = 25; +const static size_t SCHED_NR_MAX_UL_ALLOCS = 16; +const static size_t SCHED_NR_MAX_TB = 1; class sched_nr_interface { public: - virtual ~sched_nr_interface() = default; - virtual void ue_cfg(uint16_t rnti, const sched_nr_ue_cfg& ue_cfg) = 0; - virtual void new_tti(tti_point tti_rx) = 0; + using pdcch_bitmap = srsran::bounded_bitset; + using rbg_bitmap = srsran::bounded_bitset; + + ///// Configuration ///// + + struct pdsch_td_res_alloc { + uint8_t k0 = 0; // 0..32 + uint8_t k1 = 4; // 0..32 + }; + using pdsch_td_res_alloc_list = srsran::bounded_vector; + struct pusch_td_res_alloc { + uint8_t k2 = 4; // 0..32 + }; + using pusch_td_res_alloc_list = srsran::bounded_vector; + + struct cell_cfg_t { + uint32_t nof_prb = 100; + uint32_t nof_rbg = 25; + }; + + struct sched_cfg_t { + uint32_t nof_concurrent_subframes = 1; + }; + + struct ue_cc_cfg_t { + bool active = false; + pdsch_td_res_alloc_list pdsch_res_list{1}; + pusch_td_res_alloc_list pusch_res_list{1}; + }; + + struct ue_cfg_t { + uint32_t maxharq_tx = 4; + srsran::bounded_vector carriers; + }; + + ///// Sched Result ///// + + struct pdsch_grant { + srsran_dci_dl_nr_t dci; + rbg_bitmap bitmap; + }; + using pdsch_list = srsran::bounded_vector; + + struct dl_tti_request_t { + tti_point pdsch_tti; + pdsch_list pdsch; + }; + + struct pusch_grant { + srsran_dci_ul_nr_t dci; + rbg_bitmap bitmap; + }; + using pusch_list = srsran::bounded_vector; + + struct ul_tti_request_t { + tti_point pusch_tti; + srsran::bounded_vector pusch; + }; + + struct tti_request_t { + dl_tti_request_t dl_res; + ul_tti_request_t ul_res; + }; + + virtual ~sched_nr_interface() = default; + virtual void ue_cfg(uint16_t rnti, const ue_cfg_t& ue_cfg) = 0; + virtual void slot_indication(tti_point tti_rx) = 0; virtual void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) = 0; virtual void ul_sr_info(tti_point, uint16_t rnti) = 0; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h index c8962f031..831923e0a 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h @@ -13,32 +13,86 @@ #ifndef SRSRAN_SCHED_NR_RB_GRID_H #define SRSRAN_SCHED_NR_RB_GRID_H +#include "lib/include/srsran/adt/circular_array.h" #include "sched_nr_interface.h" #include "sched_nr_ue.h" namespace srsenb { namespace sched_nr_impl { -class slot_grid +using pdsch_list = sched_nr_interface::pdsch_list; +using pusch_list = sched_nr_interface::pusch_list; + +struct pdcch_t {}; +struct pdsch_t {}; +struct pusch_t {}; +struct pucch_t {}; + +struct phy_slot_grid { + pdcchmask_t pdcch_tot_mask; + rbgmask_t pdsch_tot_mask; + rbgmask_t ul_tot_mask; + pdsch_list pdsch_grants; + pusch_list pusch_grants; + srsran::bounded_vector pucch_grants; +}; +using phy_cell_rb_grid = srsran::circular_array; + +struct slot_ue_grid { + phy_slot_grid* pdcch_slot; + phy_slot_grid* pdsch_slot; + phy_slot_grid* pusch_slot; + phy_slot_grid* pucch_slot; + pdcch_t* pdcch_alloc = nullptr; + pdsch_t* pdsch_alloc = nullptr; + pusch_t* pusch_alloc = nullptr; + pucch_t* pucch_alloc = nullptr; + + slot_ue_grid(phy_slot_grid& pdcch_sl, phy_slot_grid& pdsch_sl, phy_slot_grid& pusch_sl, phy_slot_grid& pucch_sl) : + pdcch_slot(&pdcch_sl), pdsch_slot(&pdsch_sl), pusch_slot(&pusch_sl), pucch_slot(&pucch_sl) + {} +}; + +class rb_alloc_grid { public: - explicit slot_grid(const sched_cell_params& cfg_); - void new_tti(tti_point tti_rx_, sched_nr_res_t& sched_res_); - bool alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask); - bool alloc_pusch(slot_ue& ue, const rbgmask_t& dl_mask); + slot_ue_grid get_slot_ue_grid(tti_point pdcch_tti, uint8_t K0, uint8_t K1, uint8_t K2) + { + phy_slot_grid& pdcch_slot = phy_grid[pdcch_tti.to_uint()]; + phy_slot_grid& pdsch_slot = phy_grid[(pdcch_tti + K0).to_uint()]; + phy_slot_grid& pucch_slot = phy_grid[(pdcch_tti + K0 + K1).to_uint()]; + phy_slot_grid& pusch_slot = phy_grid[(pdcch_tti + K2).to_uint()]; + return slot_ue_grid{pdcch_slot, pdsch_slot, pusch_slot, pucch_slot}; + } - void generate_dcis(); +private: + phy_cell_rb_grid phy_grid; +}; + +/// Error code of alloc attempt +enum class alloc_result { success, sch_collision, no_grant_space, no_rnti_opportunity }; +inline const char* to_string(alloc_result res) +{ + return ""; +} + +class slot_sched +{ +public: + explicit slot_sched(const sched_cell_params& cfg_, phy_cell_rb_grid& phy_grid_); + void new_tti(tti_point tti_rx_); + alloc_result alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask); + alloc_result alloc_pusch(slot_ue& ue, const rbgmask_t& dl_mask); - tti_point tti_tx_dl() const { return tti_rx + TX_ENB_DELAY; } - tti_point tti_tx_ul() const { return tti_tx_dl() + cfg.cell_cfg.K2; } + void generate_dcis(); const sched_cell_params& cfg; private: - tti_point tti_rx; - rbgmask_t pdsch_mask; - rbgmask_t pusch_mask; - sched_nr_res_t* sched_res = nullptr; + srslog::basic_logger& logger; + phy_cell_rb_grid phy_grid; + + tti_point tti_rx; }; } // namespace sched_nr_impl diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h index 327d89d3e..f15a516d0 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h @@ -24,31 +24,38 @@ namespace srsenb { namespace sched_nr_impl { +using ue_cfg_t = sched_nr_interface::ue_cfg_t; +using ue_cc_cfg_t = sched_nr_interface::ue_cc_cfg_t; + class ue_carrier; class slot_ue { public: slot_ue() = default; - explicit slot_ue(resource_guard::token ue_token, tti_point tti_rx_, uint32_t cc); - ~slot_ue(); + explicit slot_ue(resource_guard::token ue_token, uint16_t rnti_, tti_point tti_rx_, uint32_t cc); slot_ue(slot_ue&&) noexcept = default; slot_ue& operator=(slot_ue&&) noexcept = default; bool empty() const { return ue_token.empty(); } - void release(); + void release() { ue_token.release(); } + uint16_t rnti = SCHED_NR_INVALID_RNTI; tti_point tti_rx; uint32_t cc = SCHED_NR_MAX_CARRIERS; // UE parameters common to all sectors - const sched_nr_ue_cfg* cfg = nullptr; - bool pending_sr; + const ue_cfg_t* cfg = nullptr; + bool pending_sr; // UE parameters that are sector specific - uint32_t dl_cqi; - uint32_t ul_cqi; - harq_proc* h_dl = nullptr; - harq_proc* h_ul = nullptr; + const ue_cc_cfg_t* cc_cfg = nullptr; + tti_point pdsch_tti; + tti_point pusch_tti; + tti_point uci_tti; + uint32_t dl_cqi; + uint32_t ul_cqi; + harq_proc* h_dl = nullptr; + harq_proc* h_ul = nullptr; private: resource_guard::token ue_token; @@ -57,10 +64,10 @@ private: class ue_carrier { public: - ue_carrier(uint16_t rnti, uint32_t cc, const sched_nr_ue_cfg& cfg); - slot_ue try_reserve(tti_point tti_rx, const sched_nr_ue_cfg& cfg); + ue_carrier(uint16_t rnti, uint32_t cc, const ue_cfg_t& cfg); + slot_ue try_reserve(tti_point pdcch_tti, const ue_cfg_t& cfg); void push_feedback(srsran::move_callback callback); - void set_cfg(const sched_nr_ue_cfg& uecfg); + void set_cfg(const ue_cfg_t& uecfg); const uint16_t rnti; const uint32_t cc; @@ -72,7 +79,7 @@ public: harq_entity harq_ent; private: - const sched_nr_ue_cfg* cfg = nullptr; + const ue_cfg_t* cfg = nullptr; resource_guard busy; tti_point last_tti_rx; @@ -83,11 +90,11 @@ private: class ue { public: - ue(uint16_t rnti, const sched_nr_ue_cfg& cfg); + ue(uint16_t rnti, const ue_cfg_t& cfg); slot_ue try_reserve(tti_point tti_rx, uint32_t cc); - void set_cfg(const sched_nr_ue_cfg& cfg); + void set_cfg(const ue_cfg_t& cfg); void ul_sr_info(tti_point tti_rx) { pending_sr = true; } @@ -96,8 +103,8 @@ public: private: bool pending_sr = false; - int current_idx = 0; - std::array ue_cfgs; + int current_idx = 0; + std::array ue_cfgs; }; using ue_map_t = srsran::static_circular_map, SCHED_NR_MAX_USERS>; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h index c8cc19165..30122c5a9 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h @@ -27,12 +27,16 @@ namespace srsenb { namespace sched_nr_impl { +using slot_res_t = sched_nr_interface::tti_request_t; + class slot_cc_worker { public: - explicit slot_cc_worker(const sched_cell_params& cell_params) : cfg(cell_params), res_grid(cfg) {} + explicit slot_cc_worker(const sched_cell_params& cell_params, phy_cell_rb_grid& phy_grid) : + cfg(cell_params), res_grid(cfg, phy_grid) + {} - void start(tti_point tti_rx_, sched_nr_res_t& bwp_result, ue_map_t& ue_db_); + void start(tti_point tti_rx_, ue_map_t& ue_db_); void run(); void end_tti(); bool running() const { return tti_rx.is_valid(); } @@ -43,8 +47,8 @@ private: const sched_cell_params& cfg; - tti_point tti_rx; - slot_grid res_grid; + tti_point tti_rx; + slot_sched res_grid; srsran::static_circular_map slot_ues; }; @@ -57,9 +61,9 @@ public: sched_worker_manager(sched_worker_manager&&) = delete; ~sched_worker_manager(); - void reserve_workers(tti_point tti_rx, srsran::span sf_result_); + void reserve_workers(tti_point tti_rx); void start_tti(tti_point tti_rx); - bool run_tti(tti_point tti_rx, uint32_t cc, sched_nr_res_t& result); + bool run_tti(tti_point tti_rx, uint32_t cc, sched_nr_interface::tti_request_t& req); void end_tti(tti_point tti_rx); private: @@ -67,14 +71,15 @@ private: ue_map_t& ue_db; struct slot_worker_ctxt { - sem_t sf_sem; // lock of all workers of the same slot. unlocked by last slot_cc_worker - tti_point tti_rx; - srsran::span sf_result; - std::atomic worker_count{0}; // variable shared across slot_cc_workers - std::vector workers; + sem_t sf_sem; // lock of all workers of the same slot. unlocked by last slot_cc_worker + tti_point tti_rx; + std::atomic worker_count{0}; // variable shared across slot_cc_workers + std::vector workers; }; std::vector > slot_ctxts; + std::array phy_grid; + slot_worker_ctxt& get_sf(tti_point tti_rx); }; diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsenb/src/stack/mac/nr/sched_nr.cc index 66b6f8a54..d7638de0f 100644 --- a/srsenb/src/stack/mac/nr/sched_nr.cc +++ b/srsenb/src/stack/mac/nr/sched_nr.cc @@ -78,11 +78,11 @@ private: /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -sched_nr::sched_nr(const sched_nr_cfg& sched_cfg) : cfg(sched_cfg), pending_events(new ue_event_manager(ue_db)) {} +sched_nr::sched_nr(const sched_cfg_t& sched_cfg) : cfg(sched_cfg), pending_events(new ue_event_manager(ue_db)) {} sched_nr::~sched_nr() {} -int sched_nr::cell_cfg(const std::vector& cell_list) +int sched_nr::cell_cfg(const std::vector& cell_list) { cfg.cells.reserve(cell_list.size()); for (uint32_t cc = 0; cc < cell_list.size(); ++cc) { @@ -93,12 +93,12 @@ int sched_nr::cell_cfg(const std::vector& cell_list) return SRSRAN_SUCCESS; } -void sched_nr::ue_cfg(uint16_t rnti, const sched_nr_ue_cfg& uecfg) +void sched_nr::ue_cfg(uint16_t rnti, const ue_cfg_t& uecfg) { pending_events->push_event([this, rnti, uecfg]() { ue_cfg_impl(rnti, uecfg); }); } -void sched_nr::ue_cfg_impl(uint16_t rnti, const sched_nr_ue_cfg& uecfg) +void sched_nr::ue_cfg_impl(uint16_t rnti, const ue_cfg_t& uecfg) { if (not ue_db.contains(rnti)) { ue_db.insert(rnti, std::unique_ptr(new ue{rnti, uecfg})); @@ -107,10 +107,10 @@ void sched_nr::ue_cfg_impl(uint16_t rnti, const sched_nr_ue_cfg& uecfg) } } -void sched_nr::new_tti(tti_point tti_rx) +void sched_nr::slot_indication(tti_point tti_rx) { // Lock slot workers for provided tti_rx - sched_workers->reserve_workers(tti_rx, sched_results[tti_rx.sf_idx()]); + sched_workers->reserve_workers(tti_rx); { // synchronize {tti,cc} state. e.g. reserve UE resources for {tti,cc} decision, process feedback @@ -123,10 +123,10 @@ void sched_nr::new_tti(tti_point tti_rx) } /// Generate {tti,cc} scheduling decision -int sched_nr::generate_sched_result(tti_point tti_rx, uint32_t cc, sched_nr_res_t& result) +int sched_nr::generate_sched_result(tti_point tti_rx, uint32_t cc, tti_request_t& req) { // unlocked, parallel region - bool all_workers_finished = sched_workers->run_tti(tti_rx, cc, result); + bool all_workers_finished = sched_workers->run_tti(tti_rx, cc, req); if (all_workers_finished) { // once all workers of the same subframe finished, synchronize sched outcome with ue_db diff --git a/srsenb/src/stack/mac/nr/sched_nr_harq.cc b/srsenb/src/stack/mac/nr/sched_nr_harq.cc index 9c9c0c627..db4cab24a 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_harq.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_harq.cc @@ -15,23 +15,80 @@ namespace srsenb { namespace sched_nr_impl { -bool harq_proc::new_tx(tti_point tti_tx_, const rbgmask_t& rbgmask_, uint32_t mcs, uint32_t ack_delay_) +bool harq_proc::ack_info(uint32_t tb_idx, bool ack) +{ + if (empty(tb_idx)) { + return false; + } + tb[tb_idx].ack_state = ack; + if (ack) { + tb[tb_idx].active = false; + } + return true; +} + +void harq_proc::new_tti(tti_point tti_rx) +{ + if (has_pending_retx(tti_rx) and nof_retx() + 1 >= max_nof_retx()) { + tb[0].active = false; + } +} + +void harq_proc::reset() +{ + tb[0].ack_state = false; + tb[0].active = false; + tb[0].n_rtx = 0; + tb[0].mcs = std::numeric_limits::max(); + tb[0].tbs = std::numeric_limits::max(); +} + +bool harq_proc::new_tx(tti_point tti_tx_, + tti_point tti_ack_, + const rbgmask_t& rbgmask_, + uint32_t mcs, + uint32_t tbs, + uint32_t max_retx_) { if (not empty()) { return false; } - tti_tx = tti_tx_; - ack_delay = ack_delay_; - rbgmask = rbgmask_; - tb[0].mcs = mcs; + reset(); + max_retx = max_retx_; + tti_tx = tti_tx_; + tti_ack = tti_ack_; + rbgmask = rbgmask_; + tb[0].ndi = !tb[0].ndi; + tb[0].mcs = mcs; + tb[0].tbs = tbs; + tb[0].active = true; + return true; +} + +bool harq_proc::new_retx(tti_point tti_tx_, tti_point tti_ack_, const rbgmask_t& rbgmask_, int* mcs, int* tbs) +{ + if (empty() or rbgmask.count() != rbgmask.count()) { + return false; + } + tti_tx = tti_tx_; + tti_ack = tti_ack_; + rbgmask = rbgmask_; + tb[0].ack_state = false; + tb[0].n_rtx++; + if (mcs != nullptr) { + *mcs = tb[0].mcs; + } + if (tbs != nullptr) { + *tbs = tb[0].tbs; + } return true; } -harq_entity::harq_entity() +harq_entity::harq_entity(uint32_t nof_harq_procs) { - dl_harqs.reserve(SCHED_NR_NOF_HARQS); - ul_harqs.reserve(SCHED_NR_NOF_HARQS); - for (uint32_t pid = 0; pid < SCHED_NR_NOF_HARQS; ++pid) { + dl_harqs.reserve(nof_harq_procs); + ul_harqs.reserve(nof_harq_procs); + for (uint32_t pid = 0; pid < nof_harq_procs; ++pid) { dl_harqs.emplace_back(pid); ul_harqs.emplace_back(pid); } @@ -40,6 +97,12 @@ harq_entity::harq_entity() void harq_entity::new_tti(tti_point tti_rx_) { tti_rx = tti_rx_; + for (harq_proc& dl_h : dl_harqs) { + dl_h.new_tti(tti_rx); + } + for (harq_proc& ul_h : ul_harqs) { + ul_h.new_tti(tti_rx); + } } } // namespace sched_nr_impl diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc index d244d9de8..3374b399e 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -15,68 +15,94 @@ namespace srsenb { namespace sched_nr_impl { -slot_grid::slot_grid(const sched_cell_params& cfg_) : - cfg(cfg_), pdsch_mask(cfg.cell_cfg.nof_rbg), pusch_mask(cfg.cell_cfg.nof_rbg) +using pdsch_grant = sched_nr_interface::pdsch_grant; +using pusch_grant = sched_nr_interface::pusch_grant; + +slot_sched::slot_sched(const sched_cell_params& cfg_, phy_cell_rb_grid& phy_grid_) : + logger(srslog::fetch_basic_logger("MAC")), cfg(cfg_), phy_grid(phy_grid_) {} -void slot_grid::new_tti(tti_point tti_rx_, sched_nr_res_t& sched_res_) +void slot_sched::new_tti(tti_point tti_rx_) { - tti_rx = tti_rx_; - sched_res = &sched_res_; - - pdsch_mask.reset(); - pusch_mask.reset(); - *sched_res = {}; + tti_rx = tti_rx_; } -bool slot_grid::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) +alloc_result slot_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) { - const uint32_t tbs = 100, mcs = 20; if (ue.h_dl == nullptr) { - return false; + logger.warning("SCHED: Trying to allocate PDSCH for rnti=0x%x with no available HARQs", ue.rnti); + return alloc_result::no_rnti_opportunity; } - if ((pdsch_mask & dl_mask).any()) { - return false; + pdsch_list& pdsch_grants = phy_grid[ue.pdsch_tti.to_uint()].pdsch_grants; + if (pdsch_grants.full()) { + logger.warning("SCHED: Maximum number of DL allocations reached"); + return alloc_result::no_grant_space; } - if (sched_res->dl_res.data.full()) { - return false; + rbgmask_t& pdsch_mask = phy_grid[ue.pdsch_tti.to_uint()].pdsch_tot_mask; + if ((pdsch_mask & dl_mask).any()) { + return alloc_result::sch_collision; } - if (not ue.h_dl->new_tx(tti_tx_dl(), dl_mask, mcs, cfg.cell_cfg.K1)) { - return false; + + int mcs = -1, tbs = -1; + if (ue.h_dl->empty()) { + mcs = 20; + tbs = 100; + srsran_assert(ue.h_dl->new_tx(ue.pdsch_tti, ue.uci_tti, dl_mask, mcs, tbs, 4), "Failed to allocate DL HARQ"); + } else { + srsran_assert(ue.h_dl->new_retx(ue.pdsch_tti, ue.uci_tti, dl_mask, &mcs, &tbs), "Failed to allocate DL HARQ retx"); } + // Allocation Successful + pdsch_grants.emplace_back(); + pdsch_grant& grant = pdsch_grants.back(); + grant.dci.ctx.rnti = ue.rnti; + grant.dci.pid = ue.h_dl->pid; + grant.bitmap = dl_mask; pdsch_mask |= dl_mask; - sched_res->dl_res.data.emplace_back(); - sched_nr_data_t& data = sched_res->dl_res.data.back(); - data.tbs.resize(1); - data.tbs[0] = tbs; - return true; + return alloc_result::success; } -bool slot_grid::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) +alloc_result slot_sched::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) { - const uint32_t tbs = 100, mcs = 20; - if ((pusch_mask & ul_mask).any()) { - return false; + if (ue.h_ul == nullptr) { + logger.warning("SCHED: Trying to allocate PUSCH for rnti=0x%x with no available HARQs", ue.rnti); + return alloc_result::no_rnti_opportunity; + } + pusch_list& pusch_grants = phy_grid[ue.pusch_tti.to_uint()].pusch_grants; + if (pusch_grants.full()) { + logger.warning("SCHED: Maximum number of UL allocations reached"); + return alloc_result::no_grant_space; } - if (sched_res->ul_res.pusch.full()) { - return false; + rbgmask_t& pusch_mask = phy_grid[ue.pusch_tti.to_uint()].ul_tot_mask; + if ((pusch_mask & ul_mask).any()) { + return alloc_result::sch_collision; } - if (not ue.h_ul->new_tx(tti_tx_ul(), ul_mask, mcs, 0)) { - return false; + + int mcs = -1, tbs = -1; + if (ue.h_ul->empty()) { + mcs = 20; + tbs = 100; + bool ret = ue.h_ul->new_tx(ue.pusch_tti, ue.pusch_tti, ul_mask, mcs, tbs, ue.cfg->maxharq_tx); + srsran_assert(ret, "Failed to allocate UL HARQ"); + } else { + srsran_assert(ue.h_ul->new_retx(ue.pusch_tti, ue.pusch_tti, ul_mask, &mcs, &tbs), + "Failed to allocate UL HARQ retx"); } + // Allocation Successful + pusch_grants.emplace_back(); + pusch_grant& grant = pusch_grants.back(); + grant.dci.ctx.rnti = ue.rnti; + grant.dci.pid = ue.h_dl->pid; + grant.dci.mcs = mcs; + grant.bitmap = ul_mask; pusch_mask |= ul_mask; - sched_res->ul_res.pusch.emplace_back(); - sched_nr_data_t& data = sched_res->ul_res.pusch.back(); - data.tbs.resize(1); - data.tbs[0] = tbs; - return true; + return alloc_result::success; } -void slot_grid::generate_dcis() {} +void slot_sched::generate_dcis() {} } // namespace sched_nr_impl } // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue.cc b/srsenb/src/stack/mac/nr/sched_nr_ue.cc index 5e8d3b570..5b255135d 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_ue.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_ue.cc @@ -15,26 +15,15 @@ namespace srsenb { namespace sched_nr_impl { -slot_ue::slot_ue(resource_guard::token ue_token_, tti_point tti_rx_, uint32_t cc_) : - ue_token(std::move(ue_token_)), tti_rx(tti_rx_), cc(cc_) +slot_ue::slot_ue(resource_guard::token ue_token_, uint16_t rnti_, tti_point tti_rx_, uint32_t cc_) : + ue_token(std::move(ue_token_)), rnti(rnti_), tti_rx(tti_rx_), cc(cc_) {} -slot_ue::~slot_ue() -{ - release(); -} - -void slot_ue::release() -{ - ue_token.release(); -} - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -ue_carrier::ue_carrier(uint16_t rnti_, uint32_t cc_, const sched_nr_ue_cfg& uecfg_) : rnti(rnti_), cc(cc_), cfg(&uecfg_) -{} +ue_carrier::ue_carrier(uint16_t rnti_, uint32_t cc_, const ue_cfg_t& uecfg_) : rnti(rnti_), cc(cc_), cfg(&uecfg_) {} -void ue_carrier::set_cfg(const sched_nr_ue_cfg& uecfg) +void ue_carrier::set_cfg(const ue_cfg_t& uecfg) { cfg = &uecfg; } @@ -44,9 +33,9 @@ void ue_carrier::push_feedback(srsran::move_callback callback pending_feedback.push_back(std::move(callback)); } -slot_ue ue_carrier::try_reserve(tti_point tti_rx, const sched_nr_ue_cfg& uecfg_) +slot_ue ue_carrier::try_reserve(tti_point tti_rx, const ue_cfg_t& uecfg_) { - slot_ue sfu(busy, tti_rx, cc); + slot_ue sfu(busy, rnti, tti_rx, cc); if (sfu.empty()) { return sfu; } @@ -71,9 +60,13 @@ slot_ue ue_carrier::try_reserve(tti_point tti_rx, const sched_nr_ue_cfg& uecfg_) sfu.cfg = &uecfg_; // copy cc-specific parameters and find available HARQs - sfu.dl_cqi = dl_cqi; - sfu.ul_cqi = ul_cqi; - sfu.h_dl = harq_ent.find_pending_dl_retx(); + sfu.cc_cfg = &uecfg_.carriers[cc]; + sfu.pdsch_tti = tti_rx + TX_ENB_DELAY + sfu.cc_cfg->pdsch_res_list[0].k0; + sfu.pusch_tti = tti_rx + TX_ENB_DELAY + sfu.cc_cfg->pusch_res_list[0].k2; + sfu.uci_tti = sfu.pdsch_tti + sfu.cc_cfg->pdsch_res_list[0].k1; + sfu.dl_cqi = dl_cqi; + sfu.ul_cqi = ul_cqi; + sfu.h_dl = harq_ent.find_pending_dl_retx(); if (sfu.h_dl == nullptr) { sfu.h_dl = harq_ent.find_empty_dl_harq(); } @@ -92,8 +85,9 @@ slot_ue ue_carrier::try_reserve(tti_point tti_rx, const sched_nr_ue_cfg& uecfg_) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -ue::ue(uint16_t rnti, const sched_nr_ue_cfg& cfg) +ue::ue(uint16_t rnti, const ue_cfg_t& cfg) { + ue_cfgs[0] = cfg; for (uint32_t cc = 0; cc < cfg.carriers.size(); ++cc) { if (cfg.carriers[cc].active) { carriers[cc].reset(new ue_carrier(rnti, cc, cfg)); @@ -101,7 +95,7 @@ ue::ue(uint16_t rnti, const sched_nr_ue_cfg& cfg) } } -void ue::set_cfg(const sched_nr_ue_cfg& cfg) +void ue::set_cfg(const ue_cfg_t& cfg) { current_idx = (current_idx + 1) % ue_cfgs.size(); ue_cfgs[current_idx] = cfg; diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index 50ed4d71f..24b047ba2 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -16,7 +16,7 @@ namespace srsenb { namespace sched_nr_impl { /// Called at the beginning of TTI in a locked context, to reserve available UE resources -void slot_cc_worker::start(tti_point tti_rx_, sched_nr_res_t& bwp_result_, ue_map_t& ue_db) +void slot_cc_worker::start(tti_point tti_rx_, ue_map_t& ue_db) { srsran_assert(not running(), "scheduler worker::start() called for active worker"); // Try reserve UE cells for this worker @@ -33,7 +33,7 @@ void slot_cc_worker::start(tti_point tti_rx_, sched_nr_res_t& bwp_result_, ue_ma // UE acquired successfully for scheduling in this {tti, cc} } - res_grid.new_tti(tti_rx_, bwp_result_); + res_grid.new_tti(tti_rx_); tti_rx = tti_rx_; } @@ -104,7 +104,7 @@ sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, const sched_params& sem_init(&slot_ctxts[i]->sf_sem, 0, 1); slot_ctxts[i]->workers.reserve(cfg.cells.size()); for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { - slot_ctxts[i]->workers.emplace_back(cfg.cells[cc]); + slot_ctxts[i]->workers.emplace_back(cfg.cells[cc], phy_grid[cc]); } } } @@ -126,14 +126,13 @@ sched_worker_manager::slot_worker_ctxt& sched_worker_manager::get_sf(tti_point t return *slot_ctxts[tti_rx.to_uint() % slot_ctxts.size()]; } -void sched_worker_manager::reserve_workers(tti_point tti_rx_, srsran::span sf_result_) +void sched_worker_manager::reserve_workers(tti_point tti_rx_) { // lock if slot worker is already being used auto& sf_worker_ctxt = get_sf(tti_rx_); sem_wait(&sf_worker_ctxt.sf_sem); - sf_worker_ctxt.sf_result = sf_result_; - sf_worker_ctxt.tti_rx = tti_rx_; + sf_worker_ctxt.tti_rx = tti_rx_; sf_worker_ctxt.worker_count.store(static_cast(sf_worker_ctxt.workers.size()), std::memory_order_relaxed); } @@ -143,11 +142,11 @@ void sched_worker_manager::start_tti(tti_point tti_rx_) srsran_assert(sf_worker_ctxt.tti_rx == tti_rx_, "invalid run_tti(tti, cc) arguments"); for (uint32_t cc = 0; cc < sf_worker_ctxt.workers.size(); ++cc) { - sf_worker_ctxt.workers[cc].start(sf_worker_ctxt.tti_rx, sf_worker_ctxt.sf_result[cc], ue_db); + sf_worker_ctxt.workers[cc].start(sf_worker_ctxt.tti_rx, ue_db); } } -bool sched_worker_manager::run_tti(tti_point tti_rx_, uint32_t cc, sched_nr_res_t& result) +bool sched_worker_manager::run_tti(tti_point tti_rx_, uint32_t cc, slot_res_t& tti_req) { auto& sf_worker_ctxt = get_sf(tti_rx_); srsran_assert(sf_worker_ctxt.tti_rx == tti_rx_, "invalid run_tti(tti, cc) arguments"); @@ -155,12 +154,20 @@ bool sched_worker_manager::run_tti(tti_point tti_rx_, uint32_t cc, sched_nr_res_ // Get {tti, cc} scheduling decision sf_worker_ctxt.workers[cc].run(); - // copy sched result - result = sf_worker_ctxt.sf_result[cc]; + // Copy requested TTI DL and UL sched result + tti_req.dl_res.pdsch_tti = tti_rx_ + TX_ENB_DELAY; + tti_req.dl_res.pdsch = phy_grid[cc][tti_req.dl_res.pdsch_tti.to_uint()].pdsch_grants; + tti_req.ul_res.pusch_tti = tti_rx_ + TX_ENB_DELAY; + tti_req.ul_res.pusch = phy_grid[cc][tti_req.ul_res.pusch_tti.to_uint()].pusch_grants; // decrement the number of active workers int rem_workers = sf_worker_ctxt.worker_count.fetch_sub(1, std::memory_order_release) - 1; srsran_assert(rem_workers >= 0, "invalid number of calls to run_tti(tti, cc)"); + + if (rem_workers == 0) { + // Clear one slot of PHY grid, so it can be reused in the next TTIs + phy_grid[cc][sf_worker_ctxt.tti_rx.to_uint()] = {}; + } return rem_workers == 0; } @@ -171,11 +178,10 @@ void sched_worker_manager::end_tti(tti_point tti_rx_) srsran_assert(sf_worker_ctxt.worker_count == 0, "invalid number of calls to run_tti(tti, cc)"); // All the workers of the same TTI have finished. Synchronize scheduling decisions with UEs state - for (auto& worker : sf_worker_ctxt.workers) { + for (slot_cc_worker& worker : sf_worker_ctxt.workers) { worker.end_tti(); } - sf_worker_ctxt.sf_result = {}; sem_post(&sf_worker_ctxt.sf_sem); } diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index 75c2d7522..df68cbbbd 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -32,12 +32,12 @@ struct task_job_manager { } tasks++; } - void finish_task(const sched_nr_res_t& res) + void finish_task(const sched_nr_interface::tti_request_t& res) { std::unique_lock lock(mutex); - TESTASSERT(res.dl_res.data.size() <= 1); + TESTASSERT(res.dl_res.pdsch.size() <= 1); res_count++; - pdsch_count += res.dl_res.data.size(); + pdsch_count += res.dl_res.pdsch.size(); if (tasks-- >= max_tasks or tasks == 0) { cond_var.notify_one(); } @@ -57,24 +57,24 @@ void sched_nr_cfg_serialized_test() uint32_t max_nof_ttis = 1000; task_job_manager tasks; - sched_nr_cfg cfg; - std::vector cells_cfg; - cells_cfg.resize(1); + sched_nr_interface::sched_cfg_t cfg; + std::vector cells_cfg(2); sched_nr sched(cfg); sched.cell_cfg(cells_cfg); - sched_nr_ue_cfg uecfg; - uecfg.carriers.resize(1); + sched_nr_interface::ue_cfg_t uecfg; + uecfg.carriers.resize(2); uecfg.carriers[0].active = true; + uecfg.carriers[1].active = true; sched.ue_cfg(0x46, uecfg); for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { tti_point tti(nof_ttis % 10240); - sched.new_tti(tti); + sched.slot_indication(tti); for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { tasks.start_task(); - sched_nr_res_t res; + sched_nr_interface::tti_request_t res; TESTASSERT(sched.generate_sched_result(tti, cc, res) == SRSRAN_SUCCESS); tasks.finish_task(res); } @@ -88,14 +88,13 @@ void sched_nr_cfg_parallel_cc_test() uint32_t max_nof_ttis = 1000; task_job_manager tasks; - sched_nr_cfg cfg; - std::vector cells_cfg; - cells_cfg.resize(4); + sched_nr_interface::sched_cfg_t cfg; + std::vector cells_cfg(4); sched_nr sched(cfg); sched.cell_cfg(cells_cfg); - sched_nr_ue_cfg uecfg; + sched_nr_interface::ue_cfg_t uecfg; uecfg.carriers.resize(cells_cfg.size()); for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { uecfg.carriers[cc].active = true; @@ -104,11 +103,11 @@ void sched_nr_cfg_parallel_cc_test() for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { tti_point tti(nof_ttis % 10240); - sched.new_tti(tti); + sched.slot_indication(tti); for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { tasks.start_task(); srsran::get_background_workers().push_task([cc, &sched, tti, &tasks]() { - sched_nr_res_t res; + sched_nr_interface::tti_request_t res; TESTASSERT(sched.generate_sched_result(tti, cc, res) == SRSRAN_SUCCESS); tasks.finish_task(res); }); @@ -126,15 +125,15 @@ void sched_nr_cfg_parallel_sf_test() uint32_t nof_sectors = 2; task_job_manager tasks; - sched_nr_cfg cfg; + sched_nr_interface::sched_cfg_t cfg; cfg.nof_concurrent_subframes = 2; - std::vector cells_cfg; + std::vector cells_cfg; cells_cfg.resize(nof_sectors); sched_nr sched(cfg); sched.cell_cfg(cells_cfg); - sched_nr_ue_cfg uecfg; + sched_nr_interface::ue_cfg_t uecfg; uecfg.carriers.resize(cells_cfg.size()); for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { uecfg.carriers[cc].active = true; @@ -143,11 +142,11 @@ void sched_nr_cfg_parallel_sf_test() for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { tti_point tti(nof_ttis % 10240); - sched.new_tti(tti); + sched.slot_indication(tti); for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { tasks.start_task(); srsran::get_background_workers().push_task([cc, &sched, tti, &tasks]() { - sched_nr_res_t res; + sched_nr_interface::tti_request_t res; TESTASSERT(sched.generate_sched_result(tti, cc, res) == SRSRAN_SUCCESS); tasks.finish_task(res); }); From 75153c7c83b420ea4aa5a1a001356de952b62d91 Mon Sep 17 00:00:00 2001 From: Francisco Date: Thu, 24 Jun 2021 12:38:17 +0100 Subject: [PATCH 20/43] sched,nr: implementation of sched sim test class --- srsenb/hdr/stack/mac/nr/sched_nr.h | 4 +- srsenb/hdr/stack/mac/nr/sched_nr_harq.h | 6 +- srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 10 +- srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h | 24 ++- srsenb/src/stack/mac/nr/sched_nr.cc | 5 +- srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 10 +- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 10 +- srsenb/test/mac/nr/CMakeLists.txt | 2 +- srsenb/test/mac/nr/sched_nr_sim_ue.cc | 211 +++++++++++++++++++ srsenb/test/mac/nr/sched_nr_sim_ue.h | 128 +++++++++++ srsenb/test/mac/nr/sched_nr_test.cc | 50 +++-- srsenb/test/mac/sched_test_rand.cc | 2 +- 12 files changed, 428 insertions(+), 34 deletions(-) create mode 100644 srsenb/test/mac/nr/sched_nr_sim_ue.cc create mode 100644 srsenb/test/mac/nr/sched_nr_sim_ue.h diff --git a/srsenb/hdr/stack/mac/nr/sched_nr.h b/srsenb/hdr/stack/mac/nr/sched_nr.h index 11e1ba082..5f04a6668 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr.h @@ -36,11 +36,11 @@ class sched_nr final : public sched_nr_interface public: explicit sched_nr(const sched_cfg_t& sched_cfg); ~sched_nr() override; - int cell_cfg(const std::vector& cell_list); + int cell_cfg(srsran::const_span cell_list) override; void ue_cfg(uint16_t rnti, const ue_cfg_t& cfg) override; void slot_indication(tti_point tti_rx) override; - int generate_sched_result(tti_point tti_rx, uint32_t cc, tti_request_t& tti_req); + int generate_sched_result(tti_point tti_rx, uint32_t cc, tti_request_t& tti_req) override; void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) override; void ul_sr_info(tti_point tti_rx, uint16_t rnti) override; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h index 17bdd0adb..ef7d5f930 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h @@ -27,9 +27,9 @@ public: bool empty() const { - return std::none_of(tb.begin(), tb.end(), [](const tb_t& t) { return t.active; }); + return std::all_of(tb.begin(), tb.end(), [](const tb_t& t) { return not t.active; }); } - bool empty(uint32_t tb_idx) const { return tb[tb_idx].active; } + bool empty(uint32_t tb_idx) const { return not tb[tb_idx].active; } bool has_pending_retx(tti_point tti_rx) const { return not empty() and not tb[0].ack_state and tti_ack <= tti_rx; } uint32_t nof_retx() const { return tb[0].n_rtx; } uint32_t max_nof_retx() const { return max_retx; } @@ -67,7 +67,7 @@ private: class harq_entity { public: - explicit harq_entity(uint32_t nof_harq_procs = 16); + explicit harq_entity(uint32_t nof_harq_procs = SCHED_NR_MAX_HARQ); void new_tti(tti_point tti_rx_); void dl_ack_info(uint32_t pid, uint32_t tb_idx, bool ack) { dl_harqs[pid].ack_info(tb_idx, ack); } diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index e56355f97..73e4b5412 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -15,6 +15,7 @@ #include "srsran/adt/bounded_bitset.h" #include "srsran/adt/bounded_vector.h" +#include "srsran/adt/span.h" #include "srsran/common/tti_point.h" #include "srsran/phy/phch/dci_nr.h" @@ -26,6 +27,7 @@ const static size_t SCHED_NR_MAX_PDSCH_DATA = 16; const static size_t SCHED_NR_MAX_NOF_RBGS = 25; const static size_t SCHED_NR_MAX_UL_ALLOCS = 16; const static size_t SCHED_NR_MAX_TB = 1; +const static size_t SCHED_NR_MAX_HARQ = 16; class sched_nr_interface { @@ -94,9 +96,11 @@ public: ul_tti_request_t ul_res; }; - virtual ~sched_nr_interface() = default; - virtual void ue_cfg(uint16_t rnti, const ue_cfg_t& ue_cfg) = 0; - virtual void slot_indication(tti_point tti_rx) = 0; + virtual ~sched_nr_interface() = default; + virtual int cell_cfg(srsran::const_span ue_cfg) = 0; + virtual void ue_cfg(uint16_t rnti, const ue_cfg_t& ue_cfg) = 0; + virtual void slot_indication(tti_point tti_rx) = 0; + virtual int generate_sched_result(tti_point tti_rx, uint32_t cc, tti_request_t& result) = 0; virtual void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) = 0; virtual void ul_sr_info(tti_point, uint16_t rnti) = 0; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h index 831923e0a..0619a184a 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h @@ -29,12 +29,30 @@ struct pusch_t {}; struct pucch_t {}; struct phy_slot_grid { + const sched_cell_params* cell_cfg = nullptr; pdcchmask_t pdcch_tot_mask; rbgmask_t pdsch_tot_mask; rbgmask_t ul_tot_mask; pdsch_list pdsch_grants; pusch_list pusch_grants; srsran::bounded_vector pucch_grants; + + phy_slot_grid() = default; + explicit phy_slot_grid(const sched_cell_params& cell_cfg_) : + cell_cfg(&cell_cfg_), + pdcch_tot_mask(cell_cfg->cell_cfg.nof_rbg), + pdsch_tot_mask(cell_cfg->cell_cfg.nof_rbg), + ul_tot_mask(cell_cfg->cell_cfg.nof_rbg) + {} + void reset() + { + pdcch_tot_mask.reset(); + pdsch_tot_mask.reset(); + ul_tot_mask.reset(); + pdsch_grants.clear(); + pusch_grants.clear(); + pucch_grants.clear(); + } }; using phy_cell_rb_grid = srsran::circular_array; @@ -80,7 +98,9 @@ class slot_sched { public: explicit slot_sched(const sched_cell_params& cfg_, phy_cell_rb_grid& phy_grid_); - void new_tti(tti_point tti_rx_); + void new_tti(tti_point tti_rx_); + void reset(); + alloc_result alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask); alloc_result alloc_pusch(slot_ue& ue, const rbgmask_t& dl_mask); @@ -90,7 +110,7 @@ public: private: srslog::basic_logger& logger; - phy_cell_rb_grid phy_grid; + phy_cell_rb_grid& phy_grid; tti_point tti_rx; }; diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsenb/src/stack/mac/nr/sched_nr.cc index d7638de0f..193a54e1e 100644 --- a/srsenb/src/stack/mac/nr/sched_nr.cc +++ b/srsenb/src/stack/mac/nr/sched_nr.cc @@ -58,6 +58,7 @@ public: if (ue_db.contains(e.rnti) and ue_db[e.rnti]->carriers[e.cc] != nullptr) { ue_db[e.rnti]->carriers[e.cc]->push_feedback(std::move(e.callback)); } + feedback_list_tmp.pop_front(); } } @@ -82,7 +83,7 @@ sched_nr::sched_nr(const sched_cfg_t& sched_cfg) : cfg(sched_cfg), pending_event sched_nr::~sched_nr() {} -int sched_nr::cell_cfg(const std::vector& cell_list) +int sched_nr::cell_cfg(srsran::const_span cell_list) { cfg.cells.reserve(cell_list.size()); for (uint32_t cc = 0; cc < cell_list.size(); ++cc) { @@ -137,7 +138,7 @@ int sched_nr::generate_sched_result(tti_point tti_rx, uint32_t cc, tti_request_t return SRSRAN_SUCCESS; } -void sched_nr::dl_ack_info(uint16_t rnti, uint32_t pid, uint32_t cc, uint32_t tb_idx, bool ack) +void sched_nr::dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) { pending_events->push_cc_feedback( rnti, cc, [pid, tb_idx, ack](ue_carrier& ue_cc) { ue_cc.harq_ent.dl_ack_info(pid, tb_idx, ack); }); diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc index 3374b399e..b36a2d129 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -45,11 +45,13 @@ alloc_result slot_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) int mcs = -1, tbs = -1; if (ue.h_dl->empty()) { - mcs = 20; - tbs = 100; - srsran_assert(ue.h_dl->new_tx(ue.pdsch_tti, ue.uci_tti, dl_mask, mcs, tbs, 4), "Failed to allocate DL HARQ"); + mcs = 20; + tbs = 100; + bool ret = ue.h_dl->new_tx(ue.pdsch_tti, ue.uci_tti, dl_mask, mcs, tbs, 4); + srsran_assert(ret, "Failed to allocate DL HARQ"); } else { - srsran_assert(ue.h_dl->new_retx(ue.pdsch_tti, ue.uci_tti, dl_mask, &mcs, &tbs), "Failed to allocate DL HARQ retx"); + bool ret = ue.h_dl->new_retx(ue.pdsch_tti, ue.uci_tti, dl_mask, &mcs, &tbs); + srsran_assert(ret, "Failed to allocate DL HARQ retx"); } // Allocation Successful diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index 24b047ba2..bf04032c0 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -19,6 +19,8 @@ namespace sched_nr_impl { void slot_cc_worker::start(tti_point tti_rx_, ue_map_t& ue_db) { srsran_assert(not running(), "scheduler worker::start() called for active worker"); + tti_rx = tti_rx_; + // Try reserve UE cells for this worker for (auto& ue_pair : ue_db) { uint16_t rnti = ue_pair.first; @@ -97,6 +99,12 @@ void slot_cc_worker::alloc_ul_ues() sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, const sched_params& cfg_) : cfg(cfg_), ue_db(ue_db_) { + for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { + for (auto& slot_grid : phy_grid[cc]) { + slot_grid = phy_slot_grid(cfg.cells[cc]); + } + } + // Note: For now, we only allow parallelism at the sector level slot_ctxts.resize(cfg.sched_cfg.nof_concurrent_subframes); for (size_t i = 0; i < cfg.sched_cfg.nof_concurrent_subframes; ++i) { @@ -166,7 +174,7 @@ bool sched_worker_manager::run_tti(tti_point tti_rx_, uint32_t cc, slot_res_t& t if (rem_workers == 0) { // Clear one slot of PHY grid, so it can be reused in the next TTIs - phy_grid[cc][sf_worker_ctxt.tti_rx.to_uint()] = {}; + phy_grid[cc][sf_worker_ctxt.tti_rx.to_uint()].reset(); } return rem_workers == 0; } diff --git a/srsenb/test/mac/nr/CMakeLists.txt b/srsenb/test/mac/nr/CMakeLists.txt index d9e97fe56..1e1b70747 100644 --- a/srsenb/test/mac/nr/CMakeLists.txt +++ b/srsenb/test/mac/nr/CMakeLists.txt @@ -6,7 +6,7 @@ # the distribution. # -add_executable(sched_nr_test sched_nr_test.cc) +add_executable(sched_nr_test sched_nr_test.cc sched_nr_sim_ue.cc) target_link_libraries(sched_nr_test srsgnb_mac srsran_common diff --git a/srsenb/test/mac/nr/sched_nr_sim_ue.cc b/srsenb/test/mac/nr/sched_nr_sim_ue.cc new file mode 100644 index 000000000..86e9bbef9 --- /dev/null +++ b/srsenb/test/mac/nr/sched_nr_sim_ue.cc @@ -0,0 +1,211 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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 "sched_nr_sim_ue.h" +#include "lib/include/srsran/common/test_common.h" + +namespace srsenb { + +sched_nr_ue_sim::sched_nr_ue_sim(uint16_t rnti_, + const sched_nr_interface::ue_cfg_t& ue_cfg_, + tti_point prach_tti_rx, + uint32_t preamble_idx) : + logger(srslog::fetch_basic_logger("MAC")) +{ + ctxt.rnti = rnti_; + ctxt.prach_tti_rx = prach_tti_rx; + ctxt.preamble_idx = preamble_idx; + ctxt.ue_cfg = ue_cfg_; + + ctxt.cc_list.resize(ue_cfg_.carriers.size()); + for (auto& cc : ctxt.cc_list) { + for (size_t pid = 0; pid < SCHED_NR_MAX_HARQ; ++pid) { + cc.ul_harqs[pid].pid = pid; + cc.dl_harqs[pid].pid = pid; + } + } +} + +int sched_nr_ue_sim::update(const sched_nr_cc_output_res_t& cc_out) +{ + update_dl_harqs(cc_out); + return SRSRAN_SUCCESS; +} + +void sched_nr_ue_sim::update_dl_harqs(const sched_nr_cc_output_res_t& cc_out) +{ + uint32_t cc = cc_out.cc; + for (uint32_t i = 0; i < cc_out.dl_cc_result->pdsch.size(); ++i) { + const auto& data = cc_out.dl_cc_result->pdsch[i]; + if (data.dci.ctx.rnti != ctxt.rnti) { + continue; + } + auto& h = ctxt.cc_list[cc].dl_harqs[data.dci.pid]; + if (h.nof_txs == 0 or h.ndi != data.dci.ndi) { + // It is newtx + h.nof_retxs = 0; + h.ndi = data.dci.ndi; + h.first_tti_rx = cc_out.tti_rx; + h.dci_loc = data.dci.ctx.location; + h.tbs = 100; // TODO + } else { + // it is retx + h.nof_retxs++; + } + h.active = true; + h.last_tti_rx = cc_out.tti_rx; + h.nof_txs++; + } +} + +sched_nr_sim_base::sched_nr_sim_base(const sched_nr_interface::sched_cfg_t& sched_args, + const std::vector& cell_cfg_list, + std::string test_name_) : + logger(srslog::fetch_basic_logger("TEST")), + mac_logger(srslog::fetch_basic_logger("MAC")), + sched_ptr(new sched_nr(sched_args)), + test_name(std::move(test_name_)) +{ + logger.info("\n=========== Start %s ===========", test_name.c_str()); + cell_params.reserve(cell_cfg_list.size()); + for (uint32_t cc = 0; cc < cell_cfg_list.size(); ++cc) { + cell_params.emplace_back(cc, cell_cfg_list[cc], sched_args); + } + sched_ptr->cell_cfg(cell_cfg_list); // call parent cfg + TESTASSERT(cell_params.size() > 0); +} + +sched_nr_sim_base::~sched_nr_sim_base() +{ + logger.info("=========== End %s ==========\n", test_name.c_str()); +} + +int sched_nr_sim_base::add_user(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg_, uint32_t preamble_idx) +{ + TESTASSERT(ue_db.count(rnti) == 0); + + ue_db.insert(std::make_pair(rnti, sched_nr_ue_sim(rnti, ue_cfg_, current_tti_rx, preamble_idx))); + sched_ptr->ue_cfg(rnti, ue_cfg_); + return SRSRAN_SUCCESS; +} + +void sched_nr_sim_base::slot_indication(srsran::tti_point tti_rx) +{ + { + std::unique_lock lock(mutex); + logger.set_context(tti_rx.to_uint()); + mac_logger.set_context(tti_rx.to_uint()); + current_tti_rx = tti_rx; + logger.info("---------------- TTI=%d ---------------", tti_rx.to_uint()); + for (auto& ue : ue_db) { + ue_tti_events events; + set_default_tti_events(ue.second.get_ctxt(), events); + set_external_tti_events(ue.second.get_ctxt(), events); + apply_tti_events(ue.second.get_ctxt(), events); + } + } + sched_ptr->slot_indication(tti_rx); +} + +void sched_nr_sim_base::update(sched_nr_cc_output_res_t& cc_out) +{ + std::unique_lock lock(mutex); + for (auto& ue_pair : ue_db) { + ue_pair.second.update(cc_out); + } +} + +int sched_nr_sim_base::set_default_tti_events(const sim_nr_ue_ctxt_t& ue_ctxt, ue_tti_events& pending_events) +{ + pending_events.cc_list.clear(); + pending_events.cc_list.resize(cell_params.size()); + pending_events.tti_rx = current_tti_rx; + + for (uint32_t enb_cc_idx = 0; enb_cc_idx < pending_events.cc_list.size(); ++enb_cc_idx) { + auto& cc_feedback = pending_events.cc_list[enb_cc_idx]; + + cc_feedback.configured = true; + cc_feedback.ue_cc_idx = enb_cc_idx; + for (uint32_t pid = 0; pid < SCHED_NR_MAX_HARQ; ++pid) { + auto& dl_h = ue_ctxt.cc_list[cc_feedback.ue_cc_idx].dl_harqs[pid]; + auto& ul_h = ue_ctxt.cc_list[cc_feedback.ue_cc_idx].ul_harqs[pid]; + + // Set default DL ACK + if (dl_h.active and (dl_h.last_tti_rx + 8) == current_tti_rx) { + cc_feedback.dl_pid = pid; + cc_feedback.dl_ack = true; // default is ACK + } + + // Set default UL ACK + if (ul_h.active and (ul_h.last_tti_rx + 8) == current_tti_rx) { + cc_feedback.ul_pid = pid; + cc_feedback.ul_ack = true; + } + + // TODO: other CSI + } + } + + return SRSRAN_SUCCESS; +} + +int sched_nr_sim_base::apply_tti_events(sim_nr_ue_ctxt_t& ue_ctxt, const ue_tti_events& events) +{ + for (uint32_t enb_cc_idx = 0; enb_cc_idx < events.cc_list.size(); ++enb_cc_idx) { + const auto& cc_feedback = events.cc_list[enb_cc_idx]; + if (not cc_feedback.configured) { + continue; + } + + if (cc_feedback.dl_pid >= 0) { + auto& h = ue_ctxt.cc_list[cc_feedback.ue_cc_idx].dl_harqs[cc_feedback.dl_pid]; + + if (cc_feedback.dl_ack) { + logger.info("DL ACK rnti=0x%x tti_dl_tx=%u cc=%d pid=%d", + ue_ctxt.rnti, + to_tx_dl(h.last_tti_rx).to_uint(), + enb_cc_idx, + cc_feedback.dl_pid); + } + + // update scheduler + sched_ptr->dl_ack_info(ue_ctxt.rnti, enb_cc_idx, cc_feedback.dl_pid, cc_feedback.tb, cc_feedback.dl_ack); + + // update UE sim context + if (cc_feedback.dl_ack or ue_ctxt.is_last_dl_retx(cc_feedback.ue_cc_idx, cc_feedback.dl_pid)) { + h.active = false; + } + } + + if (cc_feedback.ul_pid >= 0) { + auto& h = ue_ctxt.cc_list[cc_feedback.ue_cc_idx].ul_harqs[cc_feedback.ul_pid]; + + if (cc_feedback.ul_ack) { + logger.info("UL ACK rnti=0x%x, tti_ul_tx=%u, cc=%d pid=%d", + ue_ctxt.rnti, + to_tx_ul(h.last_tti_rx).to_uint(), + enb_cc_idx, + cc_feedback.ul_pid); + } + + // // update scheduler + // if (sched_ptr->ul_crc_info(events.tti_rx.to_uint(), ue_ctxt.rnti, enb_cc_idx, cc_feedback.ul_ack) < 0) { + // logger.error("The ACKed UL Harq pid=%d does not exist.", cc_feedback.ul_pid); + // error_counter++; + // } + } + } + + return SRSRAN_SUCCESS; +} + +} // namespace srsenb \ No newline at end of file diff --git a/srsenb/test/mac/nr/sched_nr_sim_ue.h b/srsenb/test/mac/nr/sched_nr_sim_ue.h new file mode 100644 index 000000000..b6daa86be --- /dev/null +++ b/srsenb/test/mac/nr/sched_nr_sim_ue.h @@ -0,0 +1,128 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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. + * + */ + +#ifndef SRSRAN_SCHED_NR_SIM_UE_H +#define SRSRAN_SCHED_NR_SIM_UE_H + +#include "../sched_sim_ue.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr.h" +#include + +namespace srsenb { + +struct sched_nr_cc_output_res_t { + tti_point tti_rx; + uint32_t cc; + sched_nr_interface::dl_tti_request_t* dl_cc_result; + sched_nr_interface::ul_tti_request_t* ul_cc_result; +}; + +struct sim_nr_ue_ctxt_t { + uint16_t rnti; + uint32_t preamble_idx; + srsran::tti_point prach_tti_rx; + sched_nr_interface::ue_cfg_t ue_cfg; + std::vector cc_list; + + bool is_last_dl_retx(uint32_t ue_cc_idx, uint32_t pid) const + { + auto& h = cc_list.at(ue_cc_idx).dl_harqs[pid]; + return h.nof_retxs + 1 >= ue_cfg.maxharq_tx; + } +}; + +class sched_nr_ue_sim +{ +public: + sched_nr_ue_sim(uint16_t rnti_, + const sched_nr_interface::ue_cfg_t& ue_cfg_, + tti_point prach_tti_rx, + uint32_t preamble_idx); + + int update(const sched_nr_cc_output_res_t& cc_out); + + const sim_nr_ue_ctxt_t& get_ctxt() const { return ctxt; } + sim_nr_ue_ctxt_t& get_ctxt() { return ctxt; } + +private: + void update_dl_harqs(const sched_nr_cc_output_res_t& sf_out); + + srslog::basic_logger& logger; + sim_nr_ue_ctxt_t ctxt; +}; + +class sched_nr_sim_base +{ +public: + sched_nr_sim_base(const sched_nr_interface::sched_cfg_t& sched_args, + const std::vector& cell_params_, + std::string test_name); + virtual ~sched_nr_sim_base(); + + int add_user(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg_, uint32_t preamble_idx); + + void slot_indication(srsran::tti_point tti_rx); + void update(sched_nr_cc_output_res_t& cc_out); + + sched_nr_ue_sim& at(uint16_t rnti) { return ue_db.at(rnti); } + const sched_nr_ue_sim& at(uint16_t rnti) const { return ue_db.at(rnti); } + sched_nr_ue_sim* find_rnti(uint16_t rnti) + { + auto it = ue_db.find(rnti); + return it != ue_db.end() ? &it->second : nullptr; + } + const sched_nr_ue_sim* find_rnti(uint16_t rnti) const + { + auto it = ue_db.find(rnti); + return it != ue_db.end() ? &it->second : nullptr; + } + bool user_exists(uint16_t rnti) const { return ue_db.count(rnti) > 0; } + const sched_nr_interface::ue_cfg_t* get_user_cfg(uint16_t rnti) const + { + const sched_nr_ue_sim* ret = find_rnti(rnti); + return ret == nullptr ? nullptr : &ret->get_ctxt().ue_cfg; + } + sched_nr* get_sched() { return sched_ptr.get(); } + srsran::const_span get_cell_params() { return cell_params; } + tti_point get_tti_rx() const + { + std::lock_guard lock(mutex); + return current_tti_rx; + } + + std::map::iterator begin() { return ue_db.begin(); } + std::map::iterator end() { return ue_db.end(); } + + // configurable by simulator concrete implementation + virtual void set_external_tti_events(const sim_nr_ue_ctxt_t& ue_ctxt, ue_tti_events& pending_events) {} + +private: + int set_default_tti_events(const sim_nr_ue_ctxt_t& ue_ctxt, ue_tti_events& pending_events); + int apply_tti_events(sim_nr_ue_ctxt_t& ue_ctxt, const ue_tti_events& events); + + std::string test_name; + srslog::basic_logger& logger; + srslog::basic_logger& mac_logger; + std::unique_ptr sched_ptr; + std::vector cell_params; + + srsran::tti_point current_tti_rx; + std::map ue_db; + int error_counter = 0; + + mutable std::mutex mutex; + std::condition_variable cond_var; +}; + +} // namespace srsenb + +#endif // SRSRAN_SCHED_NR_SIM_UE_H diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index df68cbbbd..b3638c5c9 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -10,6 +10,7 @@ * */ +#include "sched_nr_sim_ue.h" #include "srsenb/hdr/stack/mac/nr/sched_nr.h" #include "srsran/common/test_common.h" #include "srsran/common/thread_pool.h" @@ -23,6 +24,7 @@ struct task_job_manager { int res_count = 0; int pdsch_count = 0; int max_tasks = std::numeric_limits::max() / 2; + srslog::basic_logger& test_logger = srslog::fetch_basic_logger("TEST"); void start_task() { @@ -49,66 +51,79 @@ struct task_job_manager { cond_var.wait(lock); } } - void print_results() const { printf("TESTER: %f PDSCH/{slot,cc} were allocated\n", pdsch_count / (double)res_count); } + void print_results() const + { + test_logger.info("TESTER: %f PDSCH/{slot,cc} were allocated", pdsch_count / (double)res_count); + srslog::flush(); + } }; void sched_nr_cfg_serialized_test() { - uint32_t max_nof_ttis = 1000; + auto& mac_logger = srslog::fetch_basic_logger("MAC"); + + uint32_t max_nof_ttis = 1000, nof_sectors = 2; task_job_manager tasks; sched_nr_interface::sched_cfg_t cfg; - std::vector cells_cfg(2); + std::vector cells_cfg(nof_sectors); - sched_nr sched(cfg); - sched.cell_cfg(cells_cfg); + sched_nr_sim_base sched_tester(cfg, cells_cfg, "Serialized Test"); sched_nr_interface::ue_cfg_t uecfg; - uecfg.carriers.resize(2); + uecfg.carriers.resize(nof_sectors); uecfg.carriers[0].active = true; uecfg.carriers[1].active = true; - sched.ue_cfg(0x46, uecfg); + + sched_tester.add_user(0x46, uecfg, 0); for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { tti_point tti(nof_ttis % 10240); - sched.slot_indication(tti); + sched_tester.slot_indication(tti); for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { tasks.start_task(); sched_nr_interface::tti_request_t res; - TESTASSERT(sched.generate_sched_result(tti, cc, res) == SRSRAN_SUCCESS); + TESTASSERT(sched_tester.get_sched()->generate_sched_result(tti, cc, res) == SRSRAN_SUCCESS); + sched_nr_cc_output_res_t out{tti, cc, &res.dl_res, &res.ul_res}; + sched_tester.update(out); tasks.finish_task(res); + TESTASSERT(res.dl_res.pdsch.size() == 1); } } tasks.print_results(); + TESTASSERT(tasks.pdsch_count == (int)(max_nof_ttis * nof_sectors)); } void sched_nr_cfg_parallel_cc_test() { + auto& mac_logger = srslog::fetch_basic_logger("MAC"); + uint32_t max_nof_ttis = 1000; task_job_manager tasks; sched_nr_interface::sched_cfg_t cfg; std::vector cells_cfg(4); - sched_nr sched(cfg); - sched.cell_cfg(cells_cfg); + sched_nr_sim_base sched_tester(cfg, cells_cfg, "Parallel CC Test"); sched_nr_interface::ue_cfg_t uecfg; uecfg.carriers.resize(cells_cfg.size()); for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { uecfg.carriers[cc].active = true; } - sched.ue_cfg(0x46, uecfg); + sched_tester.add_user(0x46, uecfg, 0); for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { tti_point tti(nof_ttis % 10240); - sched.slot_indication(tti); + sched_tester.slot_indication(tti); for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { tasks.start_task(); - srsran::get_background_workers().push_task([cc, &sched, tti, &tasks]() { + srsran::get_background_workers().push_task([cc, tti, &tasks, &sched_tester]() { sched_nr_interface::tti_request_t res; - TESTASSERT(sched.generate_sched_result(tti, cc, res) == SRSRAN_SUCCESS); + TESTASSERT(sched_tester.get_sched()->generate_sched_result(tti, cc, res) == SRSRAN_SUCCESS); + sched_nr_cc_output_res_t out{tti, cc, &res.dl_res, &res.ul_res}; + sched_tester.update(out); tasks.finish_task(res); }); } @@ -162,11 +177,16 @@ void sched_nr_cfg_parallel_sf_test() int main() { + auto& test_logger = srslog::fetch_basic_logger("TEST"); + test_logger.set_level(srslog::basic_levels::debug); auto& mac_logger = srslog::fetch_basic_logger("MAC"); mac_logger.set_level(srslog::basic_levels::debug); auto& pool_logger = srslog::fetch_basic_logger("POOL"); pool_logger.set_level(srslog::basic_levels::debug); + // Start the log backend. + srslog::init(); + srsran::get_background_workers().set_nof_workers(8); srsenb::sched_nr_cfg_serialized_test(); diff --git a/srsenb/test/mac/sched_test_rand.cc b/srsenb/test/mac/sched_test_rand.cc index f26a05566..766230bea 100644 --- a/srsenb/test/mac/sched_test_rand.cc +++ b/srsenb/test/mac/sched_test_rand.cc @@ -347,7 +347,7 @@ int main() } auto& mac_log = srslog::fetch_basic_logger("MAC"); - mac_log.set_level(srslog::basic_levels::info); + mac_log.set_level(srslog::basic_levels::debug); auto& test_log = srslog::fetch_basic_logger("TEST", *spy, false); test_log.set_level(srslog::basic_levels::info); From de05e1e54938e77d49c24369867c15547a2fb39c Mon Sep 17 00:00:00 2001 From: Francisco Date: Thu, 24 Jun 2021 14:53:55 +0100 Subject: [PATCH 21/43] sched,nr: fix invalid memory write --- srsenb/hdr/stack/mac/nr/sched_nr_harq.h | 4 +--- srsenb/test/mac/nr/sched_nr_sim_ue.h | 8 ++++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h index ef7d5f930..3b7fa4280 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h @@ -23,7 +23,7 @@ namespace sched_nr_impl { class harq_proc { public: - explicit harq_proc(uint32_t id_, uint32_t max_nof_tb_ = 1) : pid(id_), max_nof_tb(max_nof_tb_) {} + explicit harq_proc(uint32_t id_) : pid(id_) {} bool empty() const { @@ -55,8 +55,6 @@ private: uint32_t tbs = 0; }; - const uint32_t max_nof_tb; - uint32_t max_retx = 1; tti_point tti_tx; tti_point tti_ack; diff --git a/srsenb/test/mac/nr/sched_nr_sim_ue.h b/srsenb/test/mac/nr/sched_nr_sim_ue.h index b6daa86be..b6c8e5755 100644 --- a/srsenb/test/mac/nr/sched_nr_sim_ue.h +++ b/srsenb/test/mac/nr/sched_nr_sim_ue.h @@ -26,12 +26,17 @@ struct sched_nr_cc_output_res_t { sched_nr_interface::ul_tti_request_t* ul_cc_result; }; +struct ue_nr_cc_ctxt_t { + std::array dl_harqs; + std::array ul_harqs; +}; + struct sim_nr_ue_ctxt_t { uint16_t rnti; uint32_t preamble_idx; srsran::tti_point prach_tti_rx; sched_nr_interface::ue_cfg_t ue_cfg; - std::vector cc_list; + std::vector cc_list; bool is_last_dl_retx(uint32_t ue_cc_idx, uint32_t pid) const { @@ -117,7 +122,6 @@ private: srsran::tti_point current_tti_rx; std::map ue_db; - int error_counter = 0; mutable std::mutex mutex; std::condition_variable cond_var; From 567c7c9c777ee047a488447407f57c08028c9557 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 18 Jun 2021 15:40:28 +0200 Subject: [PATCH 22/43] Create TTI semaphpore default constructor --- lib/include/srsran/common/tti_sempahore.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/include/srsran/common/tti_sempahore.h b/lib/include/srsran/common/tti_sempahore.h index f3a80fe9d..3815349f2 100644 --- a/lib/include/srsran/common/tti_sempahore.h +++ b/lib/include/srsran/common/tti_sempahore.h @@ -37,6 +37,8 @@ private: std::deque fifo; ///< Queue to keep order public: + tti_semaphore() = default; + /** * Waits for the first element of the queue match the element identifier provided. * From e98a6f9eeaa3503a25f4a50f3d1e98a961f4af42 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 18 Jun 2021 15:41:18 +0200 Subject: [PATCH 23/43] Make ACK M constant i UEDLNR --- lib/include/srsran/phy/ue/ue_dl_nr.h | 2 +- lib/src/phy/ue/ue_dl_nr.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/include/srsran/phy/ue/ue_dl_nr.h b/lib/include/srsran/phy/ue/ue_dl_nr.h index ded651383..3fecb8008 100644 --- a/lib/include/srsran/phy/ue/ue_dl_nr.h +++ b/lib/include/srsran/phy/ue/ue_dl_nr.h @@ -169,7 +169,7 @@ SRSRAN_API int srsran_ue_dl_nr_gen_ack(const srsran_ue_dl_nr_harq_ack_cfg_t* cfg const srsran_pdsch_ack_nr_t* ack_info, srsran_uci_data_nr_t* uci_data); -SRSRAN_API int srsran_ue_dl_nr_ack_insert_m(srsran_pdsch_ack_nr_t* ack_info, srsran_pdsch_ack_m_nr_t* m); +SRSRAN_API int srsran_ue_dl_nr_ack_insert_m(srsran_pdsch_ack_nr_t* ack_info, const srsran_pdsch_ack_m_nr_t* m); SRSRAN_API uint32_t srsran_ue_dl_nr_ack_info(const srsran_pdsch_ack_nr_t* ack_info, char* str, uint32_t str_len); diff --git a/lib/src/phy/ue/ue_dl_nr.c b/lib/src/phy/ue/ue_dl_nr.c index 0611f5993..9693b55bd 100644 --- a/lib/src/phy/ue/ue_dl_nr.c +++ b/lib/src/phy/ue/ue_dl_nr.c @@ -770,7 +770,7 @@ int srsran_ue_dl_nr_gen_ack(const srsran_ue_dl_nr_harq_ack_cfg_t* cfg, return SRSRAN_ERROR; } -int srsran_ue_dl_nr_ack_insert_m(srsran_pdsch_ack_nr_t* ack_info, srsran_pdsch_ack_m_nr_t* m) +int srsran_ue_dl_nr_ack_insert_m(srsran_pdsch_ack_nr_t* ack_info, const srsran_pdsch_ack_m_nr_t* m) { // Check inputs if (ack_info == NULL || m == NULL) { From d49734b1bc81ec2c1cbe0d4ffe2ad5b440d76c5e Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 21 Jun 2021 07:59:57 +0200 Subject: [PATCH 24/43] SRSENB: Refactor to accomodate 5G NR --- .../srsran/interfaces/gnb_interfaces.h | 29 +- srsenb/hdr/phy/nr/cc_worker.h | 51 +- srsenb/hdr/phy/nr/phy_nr_state.h | 101 ++++ srsenb/hdr/phy/nr/sf_worker.h | 7 +- srsenb/hdr/phy/nr/worker_pool.h | 18 +- srsenb/hdr/phy/phy.h | 10 +- srsenb/hdr/stack/gnb_stack_nr.h | 2 + srsenb/hdr/stack/mac/mac_nr.h | 6 +- srsenb/src/phy/CMakeLists.txt | 5 +- srsenb/src/phy/nr/cc_worker.cc | 66 +- srsenb/src/phy/nr/phy_nr_state.cc | 79 +++ srsenb/src/phy/nr/sf_worker.cc | 71 +-- srsenb/src/phy/nr/worker_pool.cc | 29 +- srsenb/src/phy/phy.cc | 10 +- srsenb/src/phy/txrx.cc | 16 +- srsenb/src/stack/gnb_stack_nr.cc | 8 + srsenb/src/stack/mac/nr/mac_nr.cc | 8 + srsue/hdr/phy/nr/sf_worker.h | 9 +- srsue/src/phy/nr/sf_worker.cc | 12 +- test/phy/CMakeLists.txt | 4 +- test/phy/dummy_phy_common.h | 233 ++++++++ test/phy/nr_dl_flood.cc | 563 ++++++++++++++++++ test/phy/nr_phy_test.cc | 113 ---- test/phy/test_bench.h | 131 ++++ 24 files changed, 1297 insertions(+), 284 deletions(-) create mode 100644 srsenb/hdr/phy/nr/phy_nr_state.h create mode 100644 srsenb/src/phy/nr/phy_nr_state.cc create mode 100644 test/phy/dummy_phy_common.h create mode 100644 test/phy/nr_dl_flood.cc delete mode 100644 test/phy/nr_phy_test.cc create mode 100644 test/phy/test_bench.h diff --git a/lib/include/srsran/interfaces/gnb_interfaces.h b/lib/include/srsran/interfaces/gnb_interfaces.h index 91eae09c4..f8f41b677 100644 --- a/lib/include/srsran/interfaces/gnb_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_interfaces.h @@ -224,15 +224,40 @@ public: /** * DL Scheduling result per cell/carrier */ - typedef struct { + struct dl_sched_t { dl_sched_grant_t pdsch[MAX_GRANTS]; //< DL Grants uint32_t nof_grants; //< Number of DL grants - } dl_sched_t; + }; /** * List of DL scheduling results, one entry per cell/carrier */ typedef std::vector dl_sched_list_t; + + /** + * UL grant structure per UE + */ + struct ul_sched_grant_t { + srsran_dci_ul_nr_t dci = {}; + uint8_t* data = nullptr; + srsran_softbuffer_rx_t* softbuffer_rx = nullptr; + }; + + /** + * UL Scheduling result per cell/carrier + */ + struct ul_sched_t { + ul_sched_grant_t pusch[MAX_GRANTS]; //< UL Grants + uint32_t nof_grants; //< Number of UL grants + }; + + /** + * List of UL scheduling results, one entry per cell/carrier + */ + typedef std::vector ul_sched_list_t; + + virtual int get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res) = 0; + virtual int get_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res) = 0; }; class stack_interface_phy_nr : public mac_interface_phy_nr, public srsran::stack_interface_phy_nr diff --git a/srsenb/hdr/phy/nr/cc_worker.h b/srsenb/hdr/phy/nr/cc_worker.h index 26667f1f4..e08eaf961 100644 --- a/srsenb/hdr/phy/nr/cc_worker.h +++ b/srsenb/hdr/phy/nr/cc_worker.h @@ -13,6 +13,7 @@ #ifndef SRSENB_NR_CC_WORKER_H #define SRSENB_NR_CC_WORKER_H +#include "phy_nr_state.h" #include "srsenb/hdr/phy/phy_interfaces.h" #include "srsran/interfaces/gnb_interfaces.h" #include "srsran/interfaces/rrc_nr_interface_types.h" @@ -25,56 +26,40 @@ namespace srsenb { namespace nr { -struct phy_nr_args_t { - uint32_t nof_carriers = 1; - uint32_t nof_ports = 1; - srsran_enb_dl_nr_args_t dl = {}; -}; - -class phy_nr_state -{ -public: - phy_cell_cfg_list_nr_t cell_list = {}; - phy_nr_args_t args; - srsran::phy_cfg_nr_t cfg; - - phy_nr_state() - { - args.nof_carriers = 1; - args.dl.nof_max_prb = 100; - args.dl.nof_tx_antennas = 1; - args.dl.pdsch.measure_evm = true; - args.dl.pdsch.measure_time = true; - args.dl.pdsch.sch.disable_simd = false; - } -}; - class cc_worker { public: - cc_worker(uint32_t cc_idx, srslog::basic_logger& logger, phy_nr_state& phy_state_); + struct args_t { + uint32_t cc_idx = 0; + srsran_carrier_nr_t carrier = {}; + srsran_enb_dl_nr_args_t dl = {}; + }; + + cc_worker(const args_t& args, srslog::basic_logger& logger, phy_nr_state& phy_state_); ~cc_worker(); - bool set_carrier(const srsran_carrier_nr_t* carrier); void set_tti(uint32_t tti); cf_t* get_tx_buffer(uint32_t antenna_idx); cf_t* get_rx_buffer(uint32_t antenna_idx); uint32_t get_buffer_len(); - bool work_dl(const srsran_slot_cfg_t& dl_slot_cfg, stack_interface_phy_nr::dl_sched_t& dl_grants); + bool work_dl(stack_interface_phy_nr::dl_sched_t& dl_grants, stack_interface_phy_nr::ul_sched_t& ul_grants); + bool work_ul(); private: int encode_pdsch(stack_interface_phy_nr::dl_sched_grant_t* grants, uint32_t nof_grants); int encode_pdcch_dl(stack_interface_phy_nr::dl_sched_grant_t* grants, uint32_t nof_grants); - srsran_slot_cfg_t dl_slot_cfg = {}; - uint32_t cc_idx = 0; - std::array tx_buffer = {}; - std::array rx_buffer = {}; - uint32_t buffer_sz = 0; + uint32_t nof_tx_antennas = 0; + srsran_slot_cfg_t dl_slot_cfg = {}; + srsran_slot_cfg_t ul_slot_cfg = {}; + uint32_t cc_idx = 0; + std::array tx_buffer = {}; + std::array rx_buffer = {}; + uint32_t buffer_sz = 0; phy_nr_state& phy_state; - srsran_enb_dl_nr_t enb_dl = {}; + srsran_enb_dl_nr_t gnb_dl = {}; srslog::basic_logger& logger; }; diff --git a/srsenb/hdr/phy/nr/phy_nr_state.h b/srsenb/hdr/phy/nr/phy_nr_state.h new file mode 100644 index 000000000..ac1783374 --- /dev/null +++ b/srsenb/hdr/phy/nr/phy_nr_state.h @@ -0,0 +1,101 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2020 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. + * + */ + +#ifndef SRSENB_PHY_NR_UE_DB_H_ +#define SRSENB_PHY_NR_UE_DB_H_ + +#include +#include +#include +#include +#include +#include + +namespace srsenb { +namespace nr { + +class phy_nr_state +{ +private: + /** + * UE object stored in the PHY common database + */ + struct common_ue { + srsran::phy_cfg_nr_t cfg; + }; + + /** + * UE database indexed by RNTI + */ + std::map ue_db; + + /** + * Concurrency protection mutex, allowed modifications from const methods. + */ + mutable std::mutex mutex; + + /** + * Stack interface + */ + stack_interface_phy_nr& stack; + + /** + * Cell list + */ + const phy_cell_cfg_list_nr_t& cell_cfg_list; + + /** + * Internal RNTI addition, it is not thread safe protected + * + * @param rnti identifier of the UE + * @return SRSRAN_SUCCESS if the RNTI is not duplicated and is added successfully, SRSRAN_ERROR code if it exists + */ + inline int _add_rnti(uint16_t rnti); + + /** + * Checks if a given RNTI exists in the database + * @param rnti provides UE identifier + * @return SRSRAN_SUCCESS if the indicated RNTI exists, otherwise it returns SRSRAN_ERROR + */ + inline int _assert_rnti(uint16_t rnti) const; + + /** + * Internal eNb general configuration getter, returns default configuration if the UE does not exist in the given cell + * + * @param rnti provides UE identifier + * @param[out] phy_cfg The PHY configuration of the indicated UE for the indicated eNb carrier/call index. + * @return SRSRAN_SUCCESS if provided context is correct, SRSRAN_ERROR code otherwise + */ + inline int _get_rnti_config(uint16_t rnti, srsran::phy_cfg_nr_t& phy_cfg) const; + +public: + phy_nr_state(const phy_cell_cfg_list_nr_t& cell_cfg_list_, stack_interface_phy_nr& stack_); + + void addmod_rnti(uint16_t rnti, const srsran::phy_cfg_nr_t& phy_cfg); + + /** + * Removes a whole UE entry from the UE database + * + * @param rnti identifier of the UE + * @return SRSRAN_SUCCESS if provided RNTI exists, SRSRAN_ERROR code otherwise + */ + int rem_rnti(uint16_t rnti); + + const phy_cell_cfg_list_nr_t& get_carrier_list() const { return cell_cfg_list; } + + stack_interface_phy_nr& get_stack() { return stack; } +}; + +} // namespace nr +} // namespace srsenb + +#endif // SRSENB_PHY_NR_UE_DB_H_ diff --git a/srsenb/hdr/phy/nr/sf_worker.h b/srsenb/hdr/phy/nr/sf_worker.h index 2c41a6eb6..0d4b16501 100644 --- a/srsenb/hdr/phy/nr/sf_worker.h +++ b/srsenb/hdr/phy/nr/sf_worker.h @@ -35,13 +35,11 @@ public: sf_worker(srsran::phy_common_interface& common_, phy_nr_state& phy_state_, srslog::basic_logger& logger); ~sf_worker(); - bool set_carrier_unlocked(uint32_t cc_idx, const srsran_carrier_nr_t* carrier_); - /* Functions used by main PHY thread */ cf_t* get_buffer_rx(uint32_t cc_idx, uint32_t antenna_idx); cf_t* get_buffer_tx(uint32_t cc_idx, uint32_t antenna_idx); uint32_t get_buffer_len(); - void set_tti(uint32_t tti); + void set_time(const uint32_t& tti, const srsran::rf_timestamp_t& timestamp); private: /* Inherited from thread_pool::worker. Function called every subframe to run the DL/UL processing */ @@ -52,6 +50,9 @@ private: srsran::phy_common_interface& common; phy_nr_state& phy_state; srslog::basic_logger& logger; + srsran_slot_cfg_t dl_slot_cfg = {}; + srsran_slot_cfg_t ul_slot_cfg = {}; + srsran::rf_timestamp_t tx_time = {}; // Temporal attributes srsran_softbuffer_tx_t softbuffer_tx = {}; diff --git a/srsenb/hdr/phy/nr/worker_pool.h b/srsenb/hdr/phy/nr/worker_pool.h index 37df6bb33..9c99d2e38 100644 --- a/srsenb/hdr/phy/nr/worker_pool.h +++ b/srsenb/hdr/phy/nr/worker_pool.h @@ -13,6 +13,7 @@ #ifndef SRSENB_NR_WORKER_POOL_H #define SRSENB_NR_WORKER_POOL_H +#include "phy_nr_state.h" #include "sf_worker.h" #include "srsenb/hdr/phy/phy_interfaces.h" #include "srsran/common/thread_pool.h" @@ -27,14 +28,19 @@ class worker_pool phy_nr_state phy_state; public: + struct args_t { + uint32_t nof_workers = 3; + uint32_t prio = 52; + std::string log_level = "info"; + uint32_t log_hex_limit = 64; + }; sf_worker* operator[](std::size_t pos) { return workers.at(pos).get(); } - worker_pool(uint32_t max_workers); - bool init(const phy_cell_cfg_list_nr_t& cell_list, - const phy_args_t& args, - srsran::phy_common_interface& common, - srslog::sink& log_sink, - int prio); + worker_pool(const phy_cell_cfg_list_nr_t& cell_list, + const args_t& args, + srsran::phy_common_interface& common, + stack_interface_phy_nr& stack, + srslog::sink& log_sink); sf_worker* wait_worker(uint32_t tti); sf_worker* wait_worker_id(uint32_t id); void start_worker(sf_worker* w); diff --git a/srsenb/hdr/phy/phy.h b/srsenb/hdr/phy/phy.h index 5a46315bd..8048f6af0 100644 --- a/srsenb/hdr/phy/phy.h +++ b/srsenb/hdr/phy/phy.h @@ -77,11 +77,11 @@ private: srslog::basic_logger& phy_log; srslog::basic_logger& phy_lib_log; - lte::worker_pool lte_workers; - nr::worker_pool nr_workers; - phy_common workers_common; - prach_worker_pool prach; - txrx tx_rx; + lte::worker_pool lte_workers; + std::unique_ptr nr_workers; + phy_common workers_common; + prach_worker_pool prach; + txrx tx_rx; bool initialized = false; diff --git a/srsenb/hdr/stack/gnb_stack_nr.h b/srsenb/hdr/stack/gnb_stack_nr.h index a53b37fc6..90b108807 100644 --- a/srsenb/hdr/stack/gnb_stack_nr.h +++ b/srsenb/hdr/stack/gnb_stack_nr.h @@ -72,6 +72,8 @@ public: void process_pdus() final; void toggle_padding() { srsran::console("padding not available for NR\n"); } + int get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res) override; + int get_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res) override; private: void run_thread() final; diff --git a/srsenb/hdr/stack/mac/mac_nr.h b/srsenb/hdr/stack/mac/mac_nr.h index ae557544b..274efb74b 100644 --- a/srsenb/hdr/stack/mac/mac_nr.h +++ b/srsenb/hdr/stack/mac/mac_nr.h @@ -53,18 +53,20 @@ public: void get_metrics(srsenb::mac_metrics_t& metrics); // MAC interface for RRC - int cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg); + int cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg) override; int read_pdu_bcch_bch(uint8_t* payload); // MAC interface for RLC // TODO: - int rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue) { return 0; } + int rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue) override { return 0; } // Interface for PHY int sf_indication(const uint32_t tti); int rx_data_indication(stack_interface_phy_nr::rx_data_ind_t& grant); void process_pdus(); + int get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res) override; + int get_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res) override; private: void get_dl_config(const uint32_t tti, diff --git a/srsenb/src/phy/CMakeLists.txt b/srsenb/src/phy/CMakeLists.txt index 8371549b2..60061af9f 100644 --- a/srsenb/src/phy/CMakeLists.txt +++ b/srsenb/src/phy/CMakeLists.txt @@ -13,6 +13,7 @@ set(SOURCES nr/cc_worker.cc nr/sf_worker.cc nr/worker_pool.cc + nr/phy_nr_state.cc phy.cc phy_common.cc phy_ue_db.cc @@ -22,6 +23,6 @@ add_library(srsenb_phy STATIC ${SOURCES}) add_library(srsgnb_phy STATIC vnf_phy_nr.cc) -if(ENABLE_GUI AND SRSGUI_FOUND) +if (ENABLE_GUI AND SRSGUI_FOUND) target_link_libraries(srsenb_phy ${SRSGUI_LIBRARIES}) -endif() +endif () diff --git a/srsenb/src/phy/nr/cc_worker.cc b/srsenb/src/phy/nr/cc_worker.cc index 66f686800..93a8e1e5a 100644 --- a/srsenb/src/phy/nr/cc_worker.cc +++ b/srsenb/src/phy/nr/cc_worker.cc @@ -15,28 +15,32 @@ namespace srsenb { namespace nr { -cc_worker::cc_worker(uint32_t cc_idx_, srslog::basic_logger& log, phy_nr_state& phy_state_) : - cc_idx(cc_idx_), phy_state(phy_state_), logger(log) +cc_worker::cc_worker(const args_t& args, srslog::basic_logger& log, phy_nr_state& phy_state_) : + cc_idx(args.cc_idx), phy_state(phy_state_), logger(log), nof_tx_antennas(args.dl.nof_tx_antennas) { cf_t* buffer_c[SRSRAN_MAX_PORTS] = {}; // Allocate buffers - buffer_sz = SRSRAN_SF_LEN_PRB(phy_state.args.dl.nof_max_prb); - for (uint32_t i = 0; i < phy_state.args.dl.nof_tx_antennas; i++) { + buffer_sz = SRSRAN_SF_LEN_PRB(args.dl.nof_max_prb); + for (uint32_t i = 0; i < args.dl.nof_tx_antennas; i++) { tx_buffer[i] = srsran_vec_cf_malloc(buffer_sz); rx_buffer[i] = srsran_vec_cf_malloc(buffer_sz); buffer_c[i] = tx_buffer[i]; } - if (srsran_enb_dl_nr_init(&enb_dl, buffer_c, &phy_state.args.dl)) { - ERROR("Error initiating UE DL NR"); + if (srsran_enb_dl_nr_init(&gnb_dl, buffer_c, &args.dl)) { + ERROR("Error initiating GNB DL NR"); return; } + + if (srsran_enb_dl_nr_set_carrier(&gnb_dl, &args.carrier) < SRSRAN_SUCCESS) { + ERROR("Error setting carrier"); + } } cc_worker::~cc_worker() { - srsran_enb_dl_nr_free(&enb_dl); + srsran_enb_dl_nr_free(&gnb_dl); for (cf_t* p : rx_buffer) { if (p != nullptr) { free(p); @@ -49,34 +53,15 @@ cc_worker::~cc_worker() } } -bool cc_worker::set_carrier(const srsran_carrier_nr_t* carrier) -{ - if (srsran_enb_dl_nr_set_carrier(&enb_dl, carrier) < SRSRAN_SUCCESS) { - ERROR("Error setting carrier"); - return false; - } - - srsran_coreset_t coreset = {}; - coreset.freq_resources[0] = true; // Enable the bottom 6 PRB for PDCCH - coreset.duration = 2; - - srsran_dci_cfg_nr_t dci_cfg = phy_state.cfg.get_dci_cfg(); - if (srsran_enb_dl_nr_set_pdcch_config(&enb_dl, &phy_state.cfg.pdcch, &dci_cfg) < SRSRAN_SUCCESS) { - ERROR("Error setting coreset"); - return false; - } - - return true; -} - void cc_worker::set_tti(uint32_t tti) { + ul_slot_cfg.idx = tti; dl_slot_cfg.idx = TTI_ADD(tti, FDD_HARQ_DELAY_UL_MS); } cf_t* cc_worker::get_tx_buffer(uint32_t antenna_idx) { - if (antenna_idx >= phy_state.args.dl.nof_tx_antennas) { + if (antenna_idx >= nof_tx_antennas) { return nullptr; } @@ -85,7 +70,7 @@ cf_t* cc_worker::get_tx_buffer(uint32_t antenna_idx) cf_t* cc_worker::get_rx_buffer(uint32_t antenna_idx) { - if (antenna_idx >= phy_state.args.dl.nof_tx_antennas) { + if (antenna_idx >= nof_tx_antennas) { return nullptr; } @@ -104,7 +89,7 @@ int cc_worker::encode_pdcch_dl(stack_interface_phy_nr::dl_sched_grant_t* grants, // ... // Put actual DCI - if (srsran_enb_dl_nr_pdcch_put(&enb_dl, &dl_slot_cfg, &grants[i].dci) < SRSRAN_SUCCESS) { + if (srsran_enb_dl_nr_pdcch_put(&gnb_dl, &dl_slot_cfg, &grants[i].dci) < SRSRAN_SUCCESS) { ERROR("Error putting PDCCH"); return SRSRAN_ERROR; } @@ -127,10 +112,10 @@ int cc_worker::encode_pdsch(stack_interface_phy_nr::dl_sched_grant_t* grants, ui // Compute DL grant if (srsran_ra_dl_dci_to_grant_nr( - &enb_dl.carrier, &dl_slot_cfg, &pdsch_hl_cfg, &grants[i].dci, &pdsch_cfg, &pdsch_cfg.grant) < + &gnb_dl.carrier, &dl_slot_cfg, &pdsch_hl_cfg, &grants[i].dci, &pdsch_cfg, &pdsch_cfg.grant) < SRSRAN_SUCCESS) { ERROR("Computing DL grant"); - return false; + return SRSRAN_ERROR; } // Set soft buffer @@ -138,15 +123,15 @@ int cc_worker::encode_pdsch(stack_interface_phy_nr::dl_sched_grant_t* grants, ui pdsch_cfg.grant.tb[j].softbuffer.tx = grants[i].softbuffer_tx[j]; } - if (srsran_enb_dl_nr_pdsch_put(&enb_dl, &dl_slot_cfg, &pdsch_cfg, grants[i].data) < SRSRAN_SUCCESS) { + if (srsran_enb_dl_nr_pdsch_put(&gnb_dl, &dl_slot_cfg, &pdsch_cfg, grants[i].data) < SRSRAN_SUCCESS) { ERROR("Error putting PDSCH"); - return false; + return SRSRAN_ERROR; } // Logging if (logger.info.enabled()) { char str[512]; - srsran_enb_dl_nr_pdsch_info(&enb_dl, &pdsch_cfg, str, sizeof(str)); + srsran_enb_dl_nr_pdsch_info(&gnb_dl, &pdsch_cfg, str, sizeof(str)); logger.info("PDSCH: cc=%d, %s", cc_idx, str); } } @@ -154,10 +139,15 @@ int cc_worker::encode_pdsch(stack_interface_phy_nr::dl_sched_grant_t* grants, ui return SRSRAN_SUCCESS; } -bool cc_worker::work_dl(const srsran_slot_cfg_t& dl_sf_cfg, stack_interface_phy_nr::dl_sched_t& dl_grants) +bool cc_worker::work_ul() +{ + return true; +} + +bool cc_worker::work_dl(stack_interface_phy_nr::dl_sched_t& dl_grants, stack_interface_phy_nr::ul_sched_t& ul_grants) { // Reset resource grid - if (srsran_enb_dl_nr_base_zero(&enb_dl) < SRSRAN_SUCCESS) { + if (srsran_enb_dl_nr_base_zero(&gnb_dl) < SRSRAN_SUCCESS) { ERROR("Error setting base to zero"); return SRSRAN_ERROR; } @@ -167,7 +157,7 @@ bool cc_worker::work_dl(const srsran_slot_cfg_t& dl_sf_cfg, stack_interface_phy_ encode_pdsch(dl_grants.pdsch, dl_grants.nof_grants); // Generate signal - srsran_enb_dl_nr_gen_signal(&enb_dl); + srsran_enb_dl_nr_gen_signal(&gnb_dl); return true; } diff --git a/srsenb/src/phy/nr/phy_nr_state.cc b/srsenb/src/phy/nr/phy_nr_state.cc new file mode 100644 index 000000000..9135c0885 --- /dev/null +++ b/srsenb/src/phy/nr/phy_nr_state.cc @@ -0,0 +1,79 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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 "srsenb/hdr/phy/nr/phy_nr_state.h" + +namespace srsenb { +namespace nr { + +int phy_nr_state::_add_rnti(uint16_t rnti) +{ + if (ue_db.count(rnti) > 0) { + return SRSRAN_ERROR; + } + + // Access UE to create + // Set defaults + ue_db[rnti] = {}; + + return SRSRAN_SUCCESS; +} + +int phy_nr_state::_assert_rnti(uint16_t rnti) const +{ + return ue_db.count(rnti) > 0 ? SRSRAN_SUCCESS : SRSRAN_ERROR; +} + +int phy_nr_state::_get_rnti_config(uint16_t rnti, srsran::phy_cfg_nr_t& phy_cfg) const +{ + std::lock_guard lock(mutex); + + if (_assert_rnti(rnti) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + phy_cfg = ue_db.at(rnti).cfg; + + return SRSRAN_SUCCESS; +} + +phy_nr_state::phy_nr_state(const phy_cell_cfg_list_nr_t& cell_cfg_list_, stack_interface_phy_nr& stack_) : + cell_cfg_list(cell_cfg_list_), stack(stack_) +{} + +void phy_nr_state::addmod_rnti(uint16_t rnti, const srsran::phy_cfg_nr_t& phy_cfg) +{ + std::lock_guard lock(mutex); + + // Create UE if it does not exist + if (_assert_rnti(rnti) < SRSRAN_SUCCESS) { + _add_rnti(rnti); + } + + // Set UE configuration + ue_db[rnti].cfg = phy_cfg; +} +int phy_nr_state::rem_rnti(uint16_t rnti) +{ + std::lock_guard lock(mutex); + + if (_assert_rnti(rnti) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + ue_db.erase(rnti); + + return SRSRAN_SUCCESS; +} + +} // namespace nr +} // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/phy/nr/sf_worker.cc b/srsenb/src/phy/nr/sf_worker.cc index 6e9118c72..e165b8f0a 100644 --- a/srsenb/src/phy/nr/sf_worker.cc +++ b/srsenb/src/phy/nr/sf_worker.cc @@ -17,8 +17,15 @@ namespace nr { sf_worker::sf_worker(srsran::phy_common_interface& common_, phy_nr_state& phy_state_, srslog::basic_logger& logger) : common(common_), phy_state(phy_state_), logger(logger) { - for (uint32_t i = 0; i < phy_state.args.nof_carriers; i++) { - cc_worker* w = new cc_worker(i, logger, phy_state); + const phy_cell_cfg_list_nr_t& carrier_list = phy_state.get_carrier_list(); + for (uint32_t i = 0; i < (uint32_t)carrier_list.size(); i++) { + cc_worker::args_t cc_args = {}; + cc_args.cc_idx = i; + cc_args.carrier = carrier_list[i].carrier; + cc_args.dl.nof_tx_antennas = 1; + cc_args.dl.nof_max_prb = cc_args.carrier.nof_prb; + + cc_worker* w = new cc_worker(cc_args, logger, phy_state); cc_workers.push_back(std::unique_ptr(w)); } @@ -37,15 +44,6 @@ sf_worker::~sf_worker() srsran_softbuffer_tx_free(&softbuffer_tx); } -bool sf_worker::set_carrier_unlocked(uint32_t cc_idx, const srsran_carrier_nr_t* carrier_) -{ - if (cc_idx >= cc_workers.size()) { - return false; - } - - return cc_workers.at(cc_idx)->set_carrier(carrier_); -} - cf_t* sf_worker::get_buffer_rx(uint32_t cc_idx, uint32_t antenna_idx) { if (cc_idx >= cc_workers.size()) { @@ -69,12 +67,15 @@ uint32_t sf_worker::get_buffer_len() return cc_workers.at(0)->get_buffer_len(); } -void sf_worker::set_tti(uint32_t tti) +void sf_worker::set_time(const uint32_t& tti, const srsran::rf_timestamp_t& timestamp) { logger.set_context(tti); for (auto& w : cc_workers) { w->set_tti(tti); } + ul_slot_cfg.idx = tti; + dl_slot_cfg.idx = TTI_ADD(tti, FDD_HARQ_DELAY_UL_MS); + tx_time.copy(timestamp); } void sf_worker::work_imp() @@ -82,38 +83,30 @@ void sf_worker::work_imp() // Get Transmission buffers srsran::rf_buffer_t tx_buffer = {}; srsran::rf_timestamp_t dummy_ts = {}; - for (uint32_t cc = 0; cc < phy_state.args.nof_carriers; cc++) { - for (uint32_t ant = 0; ant < phy_state.args.nof_ports; ant++) { - tx_buffer.set(cc, ant, phy_state.args.nof_ports, cc_workers[cc]->get_tx_buffer(ant)); - } + for (uint32_t cc = 0; cc < (uint32_t)phy_state.get_carrier_list().size(); cc++) { + tx_buffer.set(cc, 0, 1, cc_workers[cc]->get_tx_buffer(0)); } - // Configure user - phy_state.cfg.pdsch.rbg_size_cfg_1 = false; - - // Fill grant (this comes from the scheduler) - srsran_slot_cfg_t dl_cfg = {}; - stack_interface_phy_nr::dl_sched_t grants = {}; - - grants.nof_grants = 1; - grants.pdsch[0].data[0] = data.data(); - grants.pdsch[0].softbuffer_tx[0] = &softbuffer_tx; - srsran_softbuffer_tx_reset(&softbuffer_tx); - - grants.pdsch[0].dci.ctx.rnti = 0x1234; - grants.pdsch[0].dci.ctx.format = srsran_dci_format_nr_1_0; - - grants.pdsch[0].dci.freq_domain_assigment = 0x1FFF; - grants.pdsch[0].dci.time_domain_assigment = 0; - grants.pdsch[0].dci.mcs = 27; + // Get UL Scheduling + mac_interface_phy_nr::ul_sched_list_t ul_sched_list = {}; + ul_sched_list.resize(1); + if (phy_state.get_stack().get_ul_sched(ul_slot_cfg.idx, ul_sched_list) < SRSRAN_SUCCESS) { + logger.error("DL Scheduling error"); + common.worker_end(this, true, tx_buffer, dummy_ts, true); + return; + } - grants.pdsch[0].dci.ctx.ss_type = srsran_search_space_type_ue; - grants.pdsch[0].dci.ctx.coreset_id = 1; - grants.pdsch[0].dci.ctx.location.L = 0; - grants.pdsch[0].dci.ctx.location.ncce = 0; + // Get DL scheduling + mac_interface_phy_nr::dl_sched_list_t dl_sched_list = {}; + dl_sched_list.resize(1); + if (phy_state.get_stack().get_dl_sched(ul_slot_cfg.idx, dl_sched_list) < SRSRAN_SUCCESS) { + logger.error("DL Scheduling error"); + common.worker_end(this, true, tx_buffer, dummy_ts, true); + return; + } for (auto& w : cc_workers) { - w->work_dl(dl_cfg, grants); + w->work_dl(dl_sched_list[0], ul_sched_list[0]); } common.worker_end(this, true, tx_buffer, dummy_ts, true); diff --git a/srsenb/src/phy/nr/worker_pool.cc b/srsenb/src/phy/nr/worker_pool.cc index 30eddcdcb..12a0c8edf 100644 --- a/srsenb/src/phy/nr/worker_pool.cc +++ b/srsenb/src/phy/nr/worker_pool.cc @@ -14,33 +14,24 @@ namespace srsenb { namespace nr { -worker_pool::worker_pool(uint32_t max_workers) : pool(max_workers) {} - -bool worker_pool::init(const phy_cell_cfg_list_nr_t& cell_list, - const phy_args_t& args, - srsran::phy_common_interface& common, - srslog::sink& log_sink, - int prio) +worker_pool::worker_pool(const phy_cell_cfg_list_nr_t& cell_list, + const args_t& args, + srsran::phy_common_interface& common, + stack_interface_phy_nr& stack, + srslog::sink& log_sink) : + pool(args.nof_workers), phy_state(cell_list, stack) { - // Save cell list - phy_state.cell_list = cell_list; - // Add workers to workers pool and start threads - srslog::basic_levels log_level = srslog::str_to_basic_level(args.log.phy_level); - for (uint32_t i = 0; i < args.nof_phy_threads; i++) { + srslog::basic_levels log_level = srslog::str_to_basic_level(args.log_level); + for (uint32_t i = 0; i < args.nof_workers; i++) { auto& log = srslog::fetch_basic_logger(fmt::format("PHY{}-NR", i), log_sink); log.set_level(log_level); - log.set_hex_dump_max_size(args.log.phy_hex_limit); + log.set_hex_dump_max_size(args.log_hex_limit); auto w = new sf_worker(common, phy_state, log); - pool.init_worker(i, w, prio); + pool.init_worker(i, w, args.prio); workers.push_back(std::unique_ptr(w)); - - srsran_carrier_nr_t c = phy_state.cell_list[0].carrier; - w->set_carrier_unlocked(0, &c); } - - return true; } void worker_pool::start_worker(sf_worker* w) diff --git a/srsenb/src/phy/phy.cc b/srsenb/src/phy/phy.cc index 8243b5e53..ee8dadcbe 100644 --- a/srsenb/src/phy/phy.cc +++ b/srsenb/src/phy/phy.cc @@ -66,7 +66,6 @@ phy::phy(srslog::sink& log_sink) : phy_log(srslog::fetch_basic_logger("PHY", log_sink)), phy_lib_log(srslog::fetch_basic_logger("PHY_LIB", log_sink)), lte_workers(MAX_WORKERS), - nr_workers(MAX_WORKERS), workers_common(), nof_workers(0), tx_rx(phy_log) @@ -132,7 +131,10 @@ int phy::init(const phy_args_t& args, lte_workers.init(args, &workers_common, log_sink, WORKERS_THREAD_PRIO); } if (not cfg.phy_cell_cfg_nr.empty()) { - nr_workers.init(cfg.phy_cell_cfg_nr, args, workers_common, log_sink, WORKERS_THREAD_PRIO); + // Not implemented + // nr_workers = std::unique_ptr( + // new nr::worker_pool(cfg.phy_cell_cfg_nr, workers_common, stack_, log_sink, MAX_WORKERS, + // WORKERS_THREAD_PRIO)); } // For each carrier, initialise PRACH worker @@ -144,7 +146,7 @@ int phy::init(const phy_args_t& args, prach.set_max_prach_offset_us(args.max_prach_offset_us); // Warning this must be initialized after all workers have been added to the pool - tx_rx.init(stack_, radio, <e_workers, &nr_workers, &workers_common, &prach, SF_RECV_THREAD_PRIO); + tx_rx.init(stack_, radio, <e_workers, nr_workers.get(), &workers_common, &prach, SF_RECV_THREAD_PRIO); initialized = true; @@ -157,7 +159,7 @@ void phy::stop() tx_rx.stop(); workers_common.stop(); lte_workers.stop(); - nr_workers.stop(); + nr_workers->stop(); prach.stop(); initialized = false; diff --git a/srsenb/src/phy/txrx.cc b/srsenb/src/phy/txrx.cc index d78393550..326114faa 100644 --- a/srsenb/src/phy/txrx.cc +++ b/srsenb/src/phy/txrx.cc @@ -47,13 +47,13 @@ bool txrx::init(stack_interface_phy_lte* stack_, prach_worker_pool* prach_, uint32_t prio_) { - stack = stack_; - radio_h = radio_h_; - lte_workers = lte_workers_; - nr_workers = nr_workers_; - worker_com = worker_com_; - prach = prach_; - running = true; + stack = stack_; + radio_h = radio_h_; + lte_workers = lte_workers_; + nr_workers = nr_workers_; + worker_com = worker_com_; + prach = prach_; + running = true; // Instantiate UL channel emulator if (worker_com->params.ul_channel_args.enable) { @@ -179,7 +179,7 @@ void txrx::run_thread() // Launch NR worker only if available if (nr_worker != nullptr) { - nr_worker->set_tti(tti); + nr_worker->set_time(tti, timestamp); worker_com->semaphore.push(nr_worker); nr_workers->start_worker(nr_worker); } diff --git a/srsenb/src/stack/gnb_stack_nr.cc b/srsenb/src/stack/gnb_stack_nr.cc index 9f3d93f06..cf90c2393 100644 --- a/srsenb/src/stack/gnb_stack_nr.cc +++ b/srsenb/src/stack/gnb_stack_nr.cc @@ -182,5 +182,13 @@ bool gnb_stack_nr::has_active_radio_bearer(uint32_t eps_bearer_id) { return (eps_bearer_id == args.coreless.drb_lcid); } +int gnb_stack_nr::get_dl_sched(uint32_t tti, mac_interface_phy_nr::dl_sched_list_t& dl_sched_res) +{ + return m_mac->get_dl_sched(tti, dl_sched_res); +} +int gnb_stack_nr::get_ul_sched(uint32_t tti, mac_interface_phy_nr::ul_sched_list_t& ul_sched_res) +{ + return m_mac->get_ul_sched(tti, ul_sched_res); +} } // namespace srsenb diff --git a/srsenb/src/stack/mac/nr/mac_nr.cc b/srsenb/src/stack/mac/nr/mac_nr.cc index eafe1e7cb..4ae51e0e3 100644 --- a/srsenb/src/stack/mac/nr/mac_nr.cc +++ b/srsenb/src/stack/mac/nr/mac_nr.cc @@ -267,5 +267,13 @@ int mac_nr::cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg) return SRSRAN_SUCCESS; } +int mac_nr::get_dl_sched(uint32_t tti, mac_interface_phy_nr::dl_sched_list_t& dl_sched_res) +{ + return 0; +} +int mac_nr::get_ul_sched(uint32_t tti, mac_interface_phy_nr::ul_sched_list_t& ul_sched_res) +{ + return 0; +} } // namespace srsenb diff --git a/srsue/hdr/phy/nr/sf_worker.h b/srsue/hdr/phy/nr/sf_worker.h index e2dc1637f..9c595d1ef 100644 --- a/srsue/hdr/phy/nr/sf_worker.h +++ b/srsue/hdr/phy/nr/sf_worker.h @@ -40,6 +40,7 @@ public: cf_t* get_buffer(uint32_t cc_idx, uint32_t antenna_idx); uint32_t get_buffer_len(); void set_tti(uint32_t tti); + void set_tx_time(const srsran::rf_timestamp_t& tx_time_); int read_pdsch_d(cf_t* pdsch_d); void start_plot(); @@ -54,10 +55,10 @@ private: srsran::phy_common_interface& common; state& phy_state; srslog::basic_logger& logger; - - uint32_t tti_rx = 0; - cf_t* prach_ptr = nullptr; - float prach_power = 0; + srsran::rf_timestamp_t tx_time = {}; + uint32_t tti_rx = 0; + cf_t* prach_ptr = nullptr; + float prach_power = 0; }; } // namespace nr diff --git a/srsue/src/phy/nr/sf_worker.cc b/srsue/src/phy/nr/sf_worker.cc index da303e6fe..b761c0c8a 100644 --- a/srsue/src/phy/nr/sf_worker.cc +++ b/srsue/src/phy/nr/sf_worker.cc @@ -68,10 +68,14 @@ void sf_worker::set_tti(uint32_t tti) } } +void sf_worker::set_tx_time(const srsran::rf_timestamp_t& tx_time_) +{ + tx_time.copy(tx_time_); +} + void sf_worker::work_imp() { - srsran::rf_buffer_t tx_buffer = {}; - srsran::rf_timestamp_t dummy_ts = {}; + srsran::rf_buffer_t tx_buffer = {}; // Perform DL processing for (auto& w : cc_workers) { @@ -95,7 +99,7 @@ void sf_worker::work_imp() 0); // Transmit NR PRACH - common.worker_end(this, true, tx_buffer, dummy_ts, true); + common.worker_end(this, true, tx_buffer, tx_time, true); // Reset PRACH pointer prach_ptr = nullptr; @@ -114,7 +118,7 @@ void sf_worker::work_imp() } // Always call worker_end before returning - common.worker_end(this, true, tx_buffer, dummy_ts, true); + common.worker_end(this, true, tx_buffer, tx_time, true); // Tell the plotting thread to draw the plots #ifdef ENABLE_GUI diff --git a/test/phy/CMakeLists.txt b/test/phy/CMakeLists.txt index fd5f8e3f5..959bd21bb 100644 --- a/test/phy/CMakeLists.txt +++ b/test/phy/CMakeLists.txt @@ -7,7 +7,7 @@ # if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) - add_executable(nr_phy_test nr_phy_test.cc) + add_executable(nr_phy_test nr_dl_flood.cc) target_link_libraries(nr_phy_test srsue_phy_nr srsue_phy @@ -22,4 +22,4 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) ${ATOMIC_LIBS}) add_nr_test(nr_phy_test nr_phy_test) -endif () \ No newline at end of file +endif () diff --git a/test/phy/dummy_phy_common.h b/test/phy/dummy_phy_common.h new file mode 100644 index 000000000..389b8022b --- /dev/null +++ b/test/phy/dummy_phy_common.h @@ -0,0 +1,233 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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. + * + */ + +#ifndef SRSRAN_DUMMY_PHY_COMMON_H +#define SRSRAN_DUMMY_PHY_COMMON_H + +#include +#include +#include +#include +#include + +class phy_common : public srsran::phy_common_interface +{ +private: + const uint32_t RINGBUFFER_TIMEOUT_MS = 10; + bool quit = false; + srslog::basic_logger& logger; + double srate_hz; + uint64_t write_ts = 0; + uint64_t read_ts = 0; + std::vector zero_buffer; ///< Zero buffer for Tx + std::vector sink_buffer; ///< Dummy buffer for Rx + std::vector ringbuffers; + srsran::tti_semaphore semaphore; + + void write_zero_padding(uint32_t nof_zeros) + { + // Skip if no pading is required + if (nof_zeros == 0) { + return; + } + + logger.debug("Padding %d zeros", nof_zeros); + + // For each ringbuffer, padd zero + int nof_bytes = (int)(nof_zeros * sizeof(cf_t)); + for (srsran_ringbuffer_t& rb : ringbuffers) { + // If quit is flagged, return instantly + if (quit) { + return; + } + + // Actual write + int err = SRSRAN_SUCCESS; + do { + err = srsran_ringbuffer_write_timed(&rb, zero_buffer.data(), nof_bytes, RINGBUFFER_TIMEOUT_MS); + if (err < SRSRAN_SUCCESS and err != SRSRAN_ERROR_TIMEOUT) { + logger.error("Error writing zeros in ringbuffer"); + } + } while (err < SRSRAN_SUCCESS and not quit); + } + + // Increment write timestamp + write_ts += nof_zeros; + } + + void write_baseband(srsran::rf_buffer_t& buffer) + { + // skip if baseband is not available + if (buffer.get_nof_samples() == 0) { + return; + } + + // For each ringbuffer, write + int nof_bytes = (int)(buffer.get_nof_samples() * sizeof(cf_t)); + uint32_t channel_idx = 0; + for (srsran_ringbuffer_t& rb : ringbuffers) { + // If quit is flagged, return instantly + if (quit) { + return; + } + + // Extract channel buffer pointer + cf_t* channel_buffer = buffer.get(channel_idx); + + // If the pointer is not set, use the zero buffer + if (channel_buffer == nullptr) { + channel_buffer = zero_buffer.data(); + } + + // Actual write + int err = SRSRAN_SUCCESS; + do { + err = srsran_ringbuffer_write_timed(&rb, channel_buffer, nof_bytes, RINGBUFFER_TIMEOUT_MS); + if (err < SRSRAN_SUCCESS and err != SRSRAN_ERROR_TIMEOUT) { + logger.error("Error writing zeros in ringbuffer"); + } + } while (err < SRSRAN_SUCCESS and not quit); + + // Increment channel counter + channel_idx++; + } + + // Increment write timestamp + write_ts += buffer.get_nof_samples(); + } + + void read_baseband(std::vector& buffers, uint32_t nof_samples) + { + // For each ringbuffer, read + int nof_bytes = (int)(nof_samples * sizeof(cf_t)); + uint32_t channel_idx = 0; + for (srsran_ringbuffer_t& rb : ringbuffers) { + // If quit is flagged, return instantly + if (quit) { + return; + } + + // Extract channel buffer pointer + cf_t* channel_buffer = buffers[channel_idx]; + + // If the pointer is not set, use the zero buffer + if (channel_buffer == nullptr) { + channel_buffer = sink_buffer.data(); + } + + // Actual write + int err = SRSRAN_SUCCESS; + do { + err = srsran_ringbuffer_read_timed(&rb, channel_buffer, nof_bytes, RINGBUFFER_TIMEOUT_MS); + if (err < SRSRAN_SUCCESS and err != SRSRAN_ERROR_TIMEOUT) { + logger.error("Error reading zeros in ringbuffer"); + } + } while (err < SRSRAN_SUCCESS and not quit); + + // Increment channel counter + channel_idx++; + } + } + +public: + struct args_t { + double srate_hz = 11.52e6; + uint32_t buffer_sz_ms = 10; ///< Buffer size in milliseconds + uint32_t nof_channels = 1; + + args_t(double srate_hz_, uint32_t buffer_sz_ms_, uint32_t nof_channels_) : + srate_hz(srate_hz_), buffer_sz_ms(buffer_sz_ms_), nof_channels(nof_channels_) + {} + }; + + phy_common(const args_t& args, srslog::basic_logger& logger_) : srate_hz(args.srate_hz), logger(logger_) + { + uint32_t buffer_sz = std::ceil((double)args.buffer_sz_ms * srate_hz * 1e-3); + uint32_t buffer_sz_bytes = sizeof(cf_t) * buffer_sz; + + // Allocate data buffer + zero_buffer.resize(buffer_sz); + sink_buffer.resize(buffer_sz); + + // Allocate ring buffers + ringbuffers.resize(args.nof_channels); + + // Initialise buffers + for (srsran_ringbuffer_t& rb : ringbuffers) { + if (srsran_ringbuffer_init(&rb, buffer_sz_bytes) < SRSRAN_SUCCESS) { + logger.error("Error ringbuffer init"); + } + } + } + + ~phy_common() + { + for (srsran_ringbuffer_t& rb : ringbuffers) { + srsran_ringbuffer_free(&rb); + } + } + + void push_semaphore(void* worker_ptr) { semaphore.push(worker_ptr); } + + void + worker_end(void* h, bool tx_enable, srsran::rf_buffer_t& buffer, srsran::rf_timestamp_t& tx_time, bool is_nr) override + { + // Synchronize worker + semaphore.wait(h); + + uint64_t tx_ts = srsran_timestamp_uint64(&tx_time.get(0), srate_hz); + + // Check transmit timestamp is not in the past + if (tx_ts < write_ts) { + logger.error("Tx time is %d samples in the past", (uint32_t)(write_ts - tx_ts)); + semaphore.release(); + return; + } + + // Write zero padding if necessary + write_zero_padding((uint32_t)(tx_ts - write_ts)); + + // Write baseband + if (tx_enable) { + write_baseband(buffer); + } else { + write_zero_padding(buffer.get_nof_samples()); + } + + // Release semaphore, so next worker can be used + semaphore.release(); + } + + void read(std::vector& buffers, uint32_t nof_samples, srsran::rf_timestamp_t& timestamp) + { + // Detect if zero padding is necessary + if (read_ts + nof_samples > write_ts) { + uint32_t nof_zero_pading = (uint32_t)((read_ts + nof_samples) - write_ts); + write_zero_padding(nof_zero_pading); + } + + // Actual baseband read + read_baseband(buffers, nof_samples); + + // Write timestamp + srsran_timestamp_init_uint64(timestamp.get_ptr(0), read_ts, srate_hz); + + // Increment Rx timestamp + read_ts += nof_samples; + } + + void stop() { + quit = true; + } +}; + +#endif // SRSRAN_DUMMY_PHY_COMMON_H diff --git a/test/phy/nr_dl_flood.cc b/test/phy/nr_dl_flood.cc new file mode 100644 index 000000000..b005fd5a6 --- /dev/null +++ b/test/phy/nr_dl_flood.cc @@ -0,0 +1,563 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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/common/test_common.h" +#include "test_bench.h" + +test_bench::args_t::args_t(int argc, char** argv) +{ + // Flag configuration as valid + valid = true; + + cell_list.resize(1); + cell_list[0].carrier.nof_prb = 52; + + phy_cfg.carrier = cell_list[0].carrier; + phy_cfg.carrier.pci = 500; + + phy_cfg.carrier.absolute_frequency_point_a = 633928; + phy_cfg.carrier.absolute_frequency_ssb = 634176; + phy_cfg.carrier.offset_to_carrier = 0; + phy_cfg.carrier.scs = srsran_subcarrier_spacing_15kHz; + phy_cfg.carrier.nof_prb = 52; + + phy_cfg.ssb.periodicity_ms = 5; + phy_cfg.ssb.position_in_burst[0] = true; + phy_cfg.ssb.scs = srsran_subcarrier_spacing_30kHz; + + phy_cfg.pdcch.coreset_present[1] = true; + phy_cfg.pdcch.coreset[1].id = 1; + phy_cfg.pdcch.coreset[1].freq_resources[0] = true; + phy_cfg.pdcch.coreset[1].freq_resources[1] = true; + phy_cfg.pdcch.coreset[1].freq_resources[2] = true; + phy_cfg.pdcch.coreset[1].freq_resources[3] = true; + phy_cfg.pdcch.coreset[1].freq_resources[4] = true; + phy_cfg.pdcch.coreset[1].freq_resources[5] = true; + phy_cfg.pdcch.coreset[1].freq_resources[6] = true; + phy_cfg.pdcch.coreset[1].freq_resources[7] = true; + phy_cfg.pdcch.coreset[1].duration = 1; + phy_cfg.pdcch.coreset[1].mapping_type = srsran_coreset_mapping_type_non_interleaved; + phy_cfg.pdcch.coreset[1].precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle; + phy_cfg.pdcch.coreset_present[2] = true; + phy_cfg.pdcch.coreset[2].id = 2; + phy_cfg.pdcch.coreset[2].freq_resources[0] = true; + phy_cfg.pdcch.coreset[2].freq_resources[1] = true; + phy_cfg.pdcch.coreset[2].freq_resources[2] = true; + phy_cfg.pdcch.coreset[2].freq_resources[3] = true; + phy_cfg.pdcch.coreset[2].freq_resources[4] = true; + phy_cfg.pdcch.coreset[2].freq_resources[5] = true; + phy_cfg.pdcch.coreset[2].freq_resources[6] = true; + phy_cfg.pdcch.coreset[2].freq_resources[7] = true; + phy_cfg.pdcch.coreset[2].duration = 1; + phy_cfg.pdcch.coreset[2].mapping_type = srsran_coreset_mapping_type_non_interleaved; + phy_cfg.pdcch.coreset[2].precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle; + + phy_cfg.pdcch.search_space_present[1] = true; + phy_cfg.pdcch.search_space[1].id = 1; + phy_cfg.pdcch.search_space[1].coreset_id = 1; + phy_cfg.pdcch.search_space[1].duration = 1; + phy_cfg.pdcch.search_space[1].nof_candidates[0] = 1; + phy_cfg.pdcch.search_space[1].nof_candidates[1] = 1; + phy_cfg.pdcch.search_space[1].nof_candidates[2] = 1; + phy_cfg.pdcch.search_space[1].nof_candidates[3] = 0; + phy_cfg.pdcch.search_space[1].nof_candidates[4] = 0; + phy_cfg.pdcch.search_space[1].formats[0] = srsran_dci_format_nr_0_0; + phy_cfg.pdcch.search_space[1].formats[1] = srsran_dci_format_nr_1_0; + phy_cfg.pdcch.search_space[1].nof_formats = 2; + phy_cfg.pdcch.search_space[1].type = srsran_search_space_type_common_3; + + phy_cfg.pdcch.search_space_present[2] = true; + phy_cfg.pdcch.search_space[2].id = 2; + phy_cfg.pdcch.search_space[2].coreset_id = 2; + phy_cfg.pdcch.search_space[2].duration = 1; + phy_cfg.pdcch.search_space[2].nof_candidates[0] = 0; + phy_cfg.pdcch.search_space[2].nof_candidates[1] = 2; + phy_cfg.pdcch.search_space[2].nof_candidates[2] = 1; + phy_cfg.pdcch.search_space[2].nof_candidates[3] = 0; + phy_cfg.pdcch.search_space[2].nof_candidates[4] = 0; + phy_cfg.pdcch.search_space[2].formats[0] = srsran_dci_format_nr_0_0; + phy_cfg.pdcch.search_space[2].formats[1] = srsran_dci_format_nr_1_0; + phy_cfg.pdcch.search_space[2].nof_formats = 2; + phy_cfg.pdcch.search_space[2].type = srsran_search_space_type_ue; + + phy_cfg.pdcch.ra_search_space_present = true; + phy_cfg.pdcch.ra_search_space = phy_cfg.pdcch.search_space[1]; + phy_cfg.pdcch.ra_search_space.type = srsran_search_space_type_common_1; + + phy_cfg.pdsch.common_time_ra[0].mapping_type = srsran_sch_mapping_type_A; + phy_cfg.pdsch.common_time_ra[0].sliv = 40; + phy_cfg.pdsch.common_time_ra[1].mapping_type = srsran_sch_mapping_type_A; + phy_cfg.pdsch.common_time_ra[1].sliv = 57; + phy_cfg.pdsch.nof_common_time_ra = 2; + + phy_cfg.pusch.common_time_ra[0].k = 4; + phy_cfg.pusch.common_time_ra[0].mapping_type = srsran_sch_mapping_type_A; + phy_cfg.pusch.common_time_ra[0].sliv = 27; + phy_cfg.pusch.common_time_ra[1].k = 5; + phy_cfg.pusch.common_time_ra[1].mapping_type = srsran_sch_mapping_type_A; + phy_cfg.pusch.common_time_ra[1].sliv = 27; + phy_cfg.pusch.nof_common_time_ra = 2; + + phy_cfg.pdsch.typeA_pos = srsran_dmrs_sch_typeA_pos_2; + phy_cfg.pusch.typeA_pos = srsran_dmrs_sch_typeA_pos_2; + + phy_cfg.tdd.pattern1.period_ms = 10; + phy_cfg.tdd.pattern1.nof_dl_slots = 7; + phy_cfg.tdd.pattern1.nof_dl_symbols = 6; + phy_cfg.tdd.pattern1.nof_ul_slots = 4; + phy_cfg.tdd.pattern1.nof_ul_symbols = 4; + + phy_cfg.pdsch.dmrs_typeA.additional_pos = srsran_dmrs_sch_add_pos_1; + phy_cfg.pdsch.dmrs_typeA.present = true; + phy_cfg.pdsch.alloc = srsran_resource_alloc_type1; + + phy_cfg.pucch.enabled = true; + srsran_pucch_nr_resource_t& pucch0 = phy_cfg.pucch.sets[0].resources[0]; + srsran_pucch_nr_resource_t& pucch1 = phy_cfg.pucch.sets[0].resources[1]; + srsran_pucch_nr_resource_t& pucch2 = phy_cfg.pucch.sets[0].resources[2]; + srsran_pucch_nr_resource_t& pucch3 = phy_cfg.pucch.sets[0].resources[3]; + srsran_pucch_nr_resource_t& pucch4 = phy_cfg.pucch.sets[0].resources[4]; + srsran_pucch_nr_resource_t& pucch5 = phy_cfg.pucch.sets[0].resources[5]; + srsran_pucch_nr_resource_t& pucch6 = phy_cfg.pucch.sets[0].resources[6]; + srsran_pucch_nr_resource_t& pucch7 = phy_cfg.pucch.sets[0].resources[7]; + phy_cfg.pucch.sets[0].nof_resources = 8; + srsran_pucch_nr_resource_t& pucch8 = phy_cfg.pucch.sets[1].resources[0]; + srsran_pucch_nr_resource_t& pucch9 = phy_cfg.pucch.sets[1].resources[1]; + srsran_pucch_nr_resource_t& pucch10 = phy_cfg.pucch.sets[1].resources[2]; + srsran_pucch_nr_resource_t& pucch11 = phy_cfg.pucch.sets[1].resources[3]; + srsran_pucch_nr_resource_t& pucch12 = phy_cfg.pucch.sets[1].resources[4]; + srsran_pucch_nr_resource_t& pucch13 = phy_cfg.pucch.sets[1].resources[5]; + srsran_pucch_nr_resource_t& pucch14 = phy_cfg.pucch.sets[1].resources[6]; + srsran_pucch_nr_resource_t& pucch15 = phy_cfg.pucch.sets[1].resources[7]; + phy_cfg.pucch.sets[1].nof_resources = 8; + + pucch0.starting_prb = 0; + pucch0.format = SRSRAN_PUCCH_NR_FORMAT_1; + pucch0.initial_cyclic_shift = 0; + pucch0.nof_symbols = 14; + pucch0.start_symbol_idx = 0; + pucch0.time_domain_occ = 0; + pucch1 = pucch0; + pucch1.initial_cyclic_shift = 4; + pucch1.time_domain_occ = 0; + pucch2 = pucch0; + pucch2.initial_cyclic_shift = 8; + pucch2.time_domain_occ = 0; + pucch3 = pucch0; + pucch3.initial_cyclic_shift = 0; + pucch3.time_domain_occ = 1; + pucch4 = pucch0; + pucch4.initial_cyclic_shift = 0; + pucch4.time_domain_occ = 1; + pucch5 = pucch0; + pucch5.initial_cyclic_shift = 4; + pucch5.time_domain_occ = 1; + pucch6 = pucch0; + pucch6.initial_cyclic_shift = 0; + pucch6.time_domain_occ = 2; + pucch7 = pucch0; + pucch7.initial_cyclic_shift = 4; + pucch7.time_domain_occ = 2; + + pucch8.starting_prb = 51; + pucch8.format = SRSRAN_PUCCH_NR_FORMAT_2; + pucch8.nof_prb = 1; + pucch8.nof_symbols = 2; + pucch8.start_symbol_idx = 0; + + pucch9 = pucch8; + pucch9.start_symbol_idx = 2; + pucch10 = pucch8; + pucch10.start_symbol_idx = 4; + pucch11 = pucch8; + pucch11.start_symbol_idx = 6; + pucch12 = pucch8; + pucch12.start_symbol_idx = 8; + pucch13 = pucch8; + pucch13.start_symbol_idx = 10; + pucch14 = pucch8; + pucch14.start_symbol_idx = 12; + pucch15 = pucch8; + pucch15.starting_prb = 1; + pucch15.start_symbol_idx = 0; + + srsran_pucch_nr_resource_t& pucch16 = phy_cfg.pucch.sr_resources[1].resource; + pucch16.starting_prb = 0; + pucch16.format = SRSRAN_PUCCH_NR_FORMAT_1; + pucch16.initial_cyclic_shift = 8; + pucch16.nof_symbols = 14; + pucch16.start_symbol_idx = 0; + pucch16.time_domain_occ = 2; + + phy_cfg.pucch.sr_resources[1].configured = true; + phy_cfg.pucch.sr_resources[1].sr_id = 0; + phy_cfg.pucch.sr_resources[1].period = 40; + phy_cfg.pucch.sr_resources[1].offset = 8; + phy_cfg.pucch.sr_resources[1].resource = pucch16; + + phy_cfg.harq_ack.dl_data_to_ul_ack[0] = 8; + phy_cfg.harq_ack.dl_data_to_ul_ack[1] = 7; + phy_cfg.harq_ack.dl_data_to_ul_ack[2] = 6; + phy_cfg.harq_ack.dl_data_to_ul_ack[3] = 5; + phy_cfg.harq_ack.dl_data_to_ul_ack[4] = 4; + phy_cfg.harq_ack.dl_data_to_ul_ack[5] = 12; + phy_cfg.harq_ack.dl_data_to_ul_ack[6] = 11; + + phy_cfg.prach.freq_offset = 2; + + // pusch-Config: setup (1) + // setup + // dmrs-UplinkForPUSCH-MappingTypeA: setup (1) + // setup + // dmrs-AdditionalPosition: pos1 (1) + // transformPrecodingDisabled + // pusch-PowerControl + // msg3-Alpha: alpha1 (7) + // p0-NominalWithoutGrant: -90dBm + // p0-AlphaSets: 1 item + // Item 0 + // P0-PUSCH-AlphaSet + // p0-PUSCH-AlphaSetId: 0 + // p0: 0dB + // alpha: alpha1 (7) + // pathlossReferenceRSToAddModList: 1 item + // Item 0 + // PUSCH-PathlossReferenceRS + // pusch-PathlossReferenceRS-Id: 0 + // referenceSignal: ssb-Index (0) + // ssb-Index: 0 + // sri-PUSCH-MappingToAddModList: 1 item + // Item 0 + // SRI-PUSCH-PowerControl + // sri-PUSCH-PowerControlId: 0 + // sri-PUSCH-PathlossReferenceRS-Id: 0 + // sri-P0-PUSCH-AlphaSetId: 0 + // sri-PUSCH-ClosedLoopIndex: i0 (0) + // resourceAllocation: resourceAllocationType1 (1) + // uci-OnPUSCH: setup (1) + // setup + // betaOffsets: semiStatic (1) + // semiStatic + // betaOffsetACK-Index1: 9 + // betaOffsetACK-Index2: 9 + // betaOffsetACK-Index3: 9 + // betaOffsetCSI-Part1-Index1: 6 + // betaOffsetCSI-Part1-Index2: 6 + // betaOffsetCSI-Part2-Index1: 6 + // betaOffsetCSI-Part2-Index2: 6 + // scaling: f1 (3) + // srs-Config: setup (1) + // setup + // srs-ResourceSetToAddModList: 1 item + // Item 0 + // SRS-ResourceSet + // srs-ResourceSetId: 0 + // srs-ResourceIdList: 1 item + // Item 0 + // SRS-ResourceId: 0 + // resourceType: aperiodic (0) + // aperiodic + // aperiodicSRS-ResourceTrigger: 1 + // slotOffset: 7 + // usage: codebook (1) + // p0: -90dBm + // pathlossReferenceRS: ssb-Index (0) + // ssb-Index: 0 + // srs-ResourceToAddModList: 1 item + // Item 0 + // SRS-Resource + // srs-ResourceId: 0 + // nrofSRS-Ports: port1 (0) + // transmissionComb: n2 (0) + // n2 + // combOffset-n2: 0 + // cyclicShift-n2: 0 + // resourceMapping + // startPosition: 0 + // nrofSymbols: n1 (0) + // repetitionFactor: n1 (0) + // freqDomainPosition: 0 + // freqDomainShift: 6 + // freqHopping + // c-SRS: 11 + // b-SRS: 3 + // b-hop: 0 + // groupOrSequenceHopping: neither (0) + // resourceType: aperiodic (0) + // aperiodic + // sequenceId: 500 + // firstActiveUplinkBWP-Id: 0 + // pusch-ServingCellConfig: setup (1) + // setup + // pdcch-ServingCellConfig: setup (1) + // setup + // pdsch-ServingCellConfig: setup (1) + // setup + // nrofHARQ-ProcessesForPDSCH: n16 (5) + // csi-MeasConfig: setup (1) + // setup + // nzp-CSI-RS-ResourceToAddModList: 5 items + // Item 0 + // NZP-CSI-RS-Resource + // nzp-CSI-RS-ResourceId: 0 + // resourceMapping + // frequencyDomainAllocation: row2 (1) + // row2: 8000 [bit length 12, 4 LSB pad bits, 1000 0000 0000 + // .... decimal value 2048] + // nrofPorts: p1 (0) + // firstOFDMSymbolInTimeDomain: 4 + // cdm-Type: noCDM (0) + // density: one (1) + // one: NULL + // freqBand + // startingRB: 0 + // nrofRBs: 52 + // powerControlOffset: 0dB + // powerControlOffsetSS: db0 (1) + // scramblingID: 0 + // periodicityAndOffset: slots80 (9) + // slots80: 1 + // qcl-InfoPeriodicCSI-RS: 0 + // Item 1 + // NZP-CSI-RS-Resource + // nzp-CSI-RS-ResourceId: 1 + // resourceMapping + // frequencyDomainAllocation: row1 (0) + // row1: 10 [bit length 4, 4 LSB pad bits, 0001 .... decimal + // value 1] + // nrofPorts: p1 (0) + // firstOFDMSymbolInTimeDomain: 4 + // cdm-Type: noCDM (0) + // density: three (2) + // three: NULL + // freqBand + // startingRB: 0 + // nrofRBs: 52 + // powerControlOffset: 0dB + // powerControlOffsetSS: db0 (1) + // scramblingID: 0 + // periodicityAndOffset: slots40 (7) + // slots40: 11 + // qcl-InfoPeriodicCSI-RS: 0 + // Item 2 + // NZP-CSI-RS-Resource + // nzp-CSI-RS-ResourceId: 2 + // resourceMapping + // frequencyDomainAllocation: row1 (0) + // row1: 10 [bit length 4, 4 LSB pad bits, 0001 .... decimal + // value 1] + // nrofPorts: p1 (0) + // firstOFDMSymbolInTimeDomain: 8 + // cdm-Type: noCDM (0) + // density: three (2) + // three: NULL + // freqBand + // startingRB: 0 + // nrofRBs: 52 + // powerControlOffset: 0dB + // powerControlOffsetSS: db0 (1) + // scramblingID: 0 + // periodicityAndOffset: slots40 (7) + // slots40: 11 + // qcl-InfoPeriodicCSI-RS: 0 + // Item 3 + // NZP-CSI-RS-Resource + // nzp-CSI-RS-ResourceId: 3 + // resourceMapping + // frequencyDomainAllocation: row1 (0) + // row1: 10 [bit length 4, 4 LSB pad bits, 0001 .... decimal + // value 1] + // nrofPorts: p1 (0) + // firstOFDMSymbolInTimeDomain: 4 + // cdm-Type: noCDM (0) + // density: three (2) + // three: NULL + // freqBand + // startingRB: 0 + // nrofRBs: 52 + // powerControlOffset: 0dB + // powerControlOffsetSS: db0 (1) + // scramblingID: 0 + // periodicityAndOffset: slots40 (7) + // slots40: 12 + // qcl-InfoPeriodicCSI-RS: 0 + // Item 4 + // NZP-CSI-RS-Resource + // nzp-CSI-RS-ResourceId: 4 + // resourceMapping + // frequencyDomainAllocation: row1 (0) + // row1: 10 [bit length 4, 4 LSB pad bits, 0001 .... decimal + // value 1] + // nrofPorts: p1 (0) + // firstOFDMSymbolInTimeDomain: 8 + // cdm-Type: noCDM (0) + // density: three (2) + // three: NULL + // freqBand + // startingRB: 0 + // nrofRBs: 52 + // powerControlOffset: 0dB + // powerControlOffsetSS: db0 (1) + // scramblingID: 0 + // periodicityAndOffset: slots40 (7) + // slots40: 12 + // qcl-InfoPeriodicCSI-RS: 0 + // nzp-CSI-RS-ResourceSetToAddModList: 2 items + // Item 0 + // NZP-CSI-RS-ResourceSet + // nzp-CSI-ResourceSetId: 0 + // nzp-CSI-RS-Resources: 1 item + // Item 0 + // NZP-CSI-RS-ResourceId: 0 + // Item 1 + // NZP-CSI-RS-ResourceSet + // nzp-CSI-ResourceSetId: 1 + // nzp-CSI-RS-Resources: 4 items + // Item 0 + // NZP-CSI-RS-ResourceId: 1 + // Item 1 + // NZP-CSI-RS-ResourceId: 2 + // Item 2 + // NZP-CSI-RS-ResourceId: 3 + // Item 3 + // NZP-CSI-RS-ResourceId: 4 + // trs-Info: true (0) + // csi-IM-ResourceToAddModList: 1 item + // Item 0 + // CSI-IM-Resource + // csi-IM-ResourceId: 0 + // csi-IM-ResourceElementPattern: pattern1 (1) + // pattern1 + // subcarrierLocation-p1: s8 (2) + // symbolLocation-p1: 8 + // freqBand + // startingRB: 0 + // nrofRBs: 52 + // periodicityAndOffset: slots80 (9) + // slots80: 1 + // csi-IM-ResourceSetToAddModList: 1 item + // Item 0 + // CSI-IM-ResourceSet + // csi-IM-ResourceSetId: 0 + // csi-IM-Resources: 1 item + // Item 0 + // CSI-IM-ResourceId: 0 + // csi-ResourceConfigToAddModList: 3 items + // Item 0 + // CSI-ResourceConfig + // csi-ResourceConfigId: 0 + // csi-RS-ResourceSetList: nzp-CSI-RS-SSB (0) + // nzp-CSI-RS-SSB + // nzp-CSI-RS-ResourceSetList: 1 item + // Item 0 + // NZP-CSI-RS-ResourceSetId: 0 + // bwp-Id: 0 + // resourceType: periodic (2) + // Item 1 + // CSI-ResourceConfig + // csi-ResourceConfigId: 1 + // csi-RS-ResourceSetList: csi-IM-ResourceSetList (1) + // csi-IM-ResourceSetList: 1 item + // Item 0 + // CSI-IM-ResourceSetId: 0 + // bwp-Id: 0 + // resourceType: periodic (2) + // Item 2 + // CSI-ResourceConfig + // csi-ResourceConfigId: 2 + // csi-RS-ResourceSetList: nzp-CSI-RS-SSB (0) + // nzp-CSI-RS-SSB + // nzp-CSI-RS-ResourceSetList: 1 item + // Item 0 + // NZP-CSI-RS-ResourceSetId: 1 + // bwp-Id: 0 + // resourceType: periodic (2) + // csi-ReportConfigToAddModList: 1 item + // Item 0 + // CSI-ReportConfig + // reportConfigId: 0 + // resourcesForChannelMeasurement: 0 + // csi-IM-ResourcesForInterference: 1 + // reportConfigType: periodic (0) + // periodic + // reportSlotConfig: slots80 (7) + // slots80: 9 + // pucch-CSI-ResourceList: 1 item + // Item 0 + // PUCCH-CSI-Resource + // uplinkBandwidthPartId: 0 + // pucch-Resource: 17 + // reportQuantity: cri-RI-PMI-CQI (1) + // cri-RI-PMI-CQI: NULL + // reportFreqConfiguration + // cqi-FormatIndicator: widebandCQI (0) + // timeRestrictionForChannelMeasurements: notConfigured (1) + // timeRestrictionForInterferenceMeasurements: notConfigured (1) + // groupBasedBeamReporting: disabled (1) + // disabled + // cqi-Table: table2 (1) + // subbandSize: value1 (0) + // tag-Id: 0 +} + +class ue_dummy_stack : public srsue::stack_interface_phy_nr +{ +public: + void in_sync() override {} + void out_of_sync() override {} + void run_tti(const uint32_t tti) override {} + int sf_indication(const uint32_t tti) override { return 0; } + sched_rnti_t get_dl_sched_rnti_nr(const uint32_t tti) override { return sched_rnti_t(); } + sched_rnti_t get_ul_sched_rnti_nr(const uint32_t tti) override { return sched_rnti_t(); } + void new_grant_dl(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_t* action) override {} + void tb_decoded(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_result_t result) override {} + void new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant, tb_action_ul_t* action) override {} + void prach_sent(uint32_t tti, uint32_t s_id, uint32_t t_id, uint32_t f_id, uint32_t ul_carrier_id) override {} + bool sr_opportunity(uint32_t tti, uint32_t sr_id, bool meas_gap, bool ul_sch_tx) override { return false; } +}; + +class gnb_dummy_stack : public srsenb::stack_interface_phy_nr +{ +public: + int sf_indication(const uint32_t tti) override { return 0; } + int rx_data_indication(rx_data_ind_t& grant) override { return 0; } + int get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res) override + { + dl_sched_res[0].nof_grants = 0; + return SRSRAN_SUCCESS; + } + int get_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res) override { return 0; } +}; + +int main(int argc, char** argv) +{ + test_bench::args_t args(argc, argv); + + // Parse arguments + TESTASSERT(args.valid); + + ue_dummy_stack ue_stack; + gnb_dummy_stack gnb_stack; + + // Create test bench + test_bench tb(args, gnb_stack, ue_stack); + + // Assert bench is initialised correctly + TESTASSERT(tb.is_initialised()); + + for (uint32_t i = 0; i < 1000; i++) { + TESTASSERT(tb.run_tti()); + } + + // If reached here, the test is successful + return SRSRAN_SUCCESS; +} \ No newline at end of file diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc deleted file mode 100644 index 7d4f7b825..000000000 --- a/test/phy/nr_phy_test.cc +++ /dev/null @@ -1,113 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 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 "srsenb/hdr/phy/nr/worker_pool.h" -#include "srsran/common/test_common.h" -#include "srsue/hdr/phy/nr/worker_pool.h" - -class phy_common : public srsran::phy_common_interface -{ -public: - void - worker_end(void* h, bool tx_enable, srsran::rf_buffer_t& buffer, srsran::rf_timestamp_t& tx_time, bool is_nr) override - {} -}; - -class ue_dummy_stack : public srsue::stack_interface_phy_nr -{ -public: - void in_sync() override {} - void out_of_sync() override {} - void run_tti(const uint32_t tti) override {} - int sf_indication(const uint32_t tti) override { return 0; } - sched_rnti_t get_dl_sched_rnti_nr(const uint32_t tti) override { return sched_rnti_t(); } - sched_rnti_t get_ul_sched_rnti_nr(const uint32_t tti) override { return sched_rnti_t(); } - void new_grant_dl(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_t* action) override {} - void tb_decoded(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_result_t result) override {} - void new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant, tb_action_ul_t* action) override {} - void prach_sent(uint32_t tti, uint32_t s_id, uint32_t t_id, uint32_t f_id, uint32_t ul_carrier_id) override {} - bool sr_opportunity(uint32_t tti, uint32_t sr_id, bool meas_gap, bool ul_sch_tx) override { return false; } -}; - -class test_bench -{ -private: - srsenb::nr::worker_pool gnb_phy; - phy_common gnb_phy_com; - srsue::nr::worker_pool ue_phy; - phy_common ue_phy_com; - ue_dummy_stack ue_stack; - bool initialised = false; - -public: - struct args_t { - uint32_t nof_threads = 6; - uint32_t nof_prb = 52; - - bool parse(int argc, char** argv); - }; - - test_bench(const args_t& args) : ue_phy(args.nof_threads), gnb_phy(args.nof_threads) - { - // Prepare cell list - srsenb::phy_cell_cfg_list_nr_t cell_list(1); - cell_list[0].carrier.nof_prb = args.nof_prb; - - // Prepare gNb PHY arguments - srsenb::phy_args_t gnb_phy_args = {}; - - // Initialise gnb - if (not gnb_phy.init(cell_list, gnb_phy_args, gnb_phy_com, srslog::get_default_sink(), 31)) { - return; - } - - // Prepare PHY - srsue::phy_args_nr_t ue_phy_args = {}; - - // Initialise UE PHY - if (not ue_phy.init(ue_phy_args, ue_phy_com, &ue_stack, 31)) { - return; - } - - initialised = true; - } - - ~test_bench() - { - gnb_phy.stop(); - ue_phy.stop(); - } - - bool is_initialised() const { return initialised; } -}; - -bool test_bench::args_t::parse(int argc, char** argv) -{ - return true; -} - -int main(int argc, char** argv) -{ - test_bench::args_t args = {}; - - // Parse arguments - TESTASSERT(args.parse(argc, argv)); - - // Create test bench - test_bench tb(args); - - // Assert bench is initialised correctly - TESTASSERT(tb.is_initialised()); - - // If reached here, the test is successful - return SRSRAN_SUCCESS; -} \ No newline at end of file diff --git a/test/phy/test_bench.h b/test/phy/test_bench.h new file mode 100644 index 000000000..ff572d958 --- /dev/null +++ b/test/phy/test_bench.h @@ -0,0 +1,131 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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. + * + */ + +#ifndef SRSRAN_TEST_BENCH_H +#define SRSRAN_TEST_BENCH_H + +#include "dummy_phy_common.h" +#include "srsenb/hdr/phy/nr/worker_pool.h" +#include "srsue/hdr/phy/nr/worker_pool.h" + +class test_bench +{ +private: + uint32_t tti = 0; + srsenb::nr::worker_pool gnb_phy; + phy_common gnb_phy_com; + srsue::nr::worker_pool ue_phy; + phy_common ue_phy_com; + bool initialised = false; + uint32_t sf_sz = 0; + +public: + struct args_t { + double srate_hz = 11.52e6; + uint32_t nof_threads = 6; + uint32_t nof_channels = 1; + uint32_t buffer_sz_ms = 10; + bool valid = false; + srsran::phy_cfg_nr_t phy_cfg = {}; + srsenb::phy_cell_cfg_list_nr_t cell_list = {}; + srsenb::nr::worker_pool::args_t gnb_args; + uint16_t rnti = 0x1234; + + args_t(int argc, char** argv); + }; + + test_bench(const args_t& args, srsenb::stack_interface_phy_nr& gnb_stack, srsue::stack_interface_phy_nr& ue_stack) : + ue_phy(args.nof_threads), + gnb_phy(args.cell_list, args.gnb_args, gnb_phy_com, gnb_stack, srslog::get_default_sink()), + ue_phy_com(phy_common::args_t(args.srate_hz, args.buffer_sz_ms, args.nof_channels), + srslog::fetch_basic_logger("UE /PHY/COM")), + gnb_phy_com(phy_common::args_t(args.srate_hz, args.buffer_sz_ms, args.nof_channels), + srslog::fetch_basic_logger("GNB/PHY/COM")) + { + // Calculate subframe length + sf_sz = (uint32_t)std::round(args.srate_hz * 1e-3); + + // Prepare PHY + srsue::phy_args_nr_t ue_phy_args = {}; + + // Initialise UE PHY + if (not ue_phy.init(ue_phy_args, ue_phy_com, &ue_stack, 31)) { + return; + } + + // Set UE configuration + if (not ue_phy.set_config(args.phy_cfg)) { + return; + } + + initialised = true; + } + + ~test_bench() + { + ue_phy_com.stop(); + gnb_phy_com.stop(); + gnb_phy.stop(); + ue_phy.stop(); + } + + bool is_initialised() const { return initialised; } + + bool run_tti() + { + // Get gNb worker + srsenb::nr::sf_worker* gnb_worker = gnb_phy.wait_worker(tti); + if (gnb_worker == nullptr) { + return false; + } + + // Feed gNb the UE transmitted signal + srsran::rf_timestamp_t gnb_time = {}; + std::vector gnb_rx_buffers(1); + gnb_rx_buffers[0] = gnb_worker->get_buffer_rx(0, 0); + ue_phy_com.read(gnb_rx_buffers, sf_sz, gnb_time); + + // Set gNb time + gnb_time.add(TX_ENB_DELAY * 1e-3); + gnb_worker->set_time(tti, gnb_time); + + // Start gNb work + gnb_phy_com.push_semaphore(gnb_worker); + gnb_phy.start_worker(gnb_worker); + + // Get UE worker + srsue::nr::sf_worker* ue_worker = ue_phy.wait_worker(tti); + if (ue_worker == nullptr) { + return false; + } + + // Feed UE the gNb transmitted signal + srsran::rf_timestamp_t ue_time = {}; + std::vector ue_rx_buffers(1); + ue_rx_buffers[0] = ue_worker->get_buffer(0, 0); + gnb_phy_com.read(ue_rx_buffers, sf_sz, ue_time); + + // Set UE time + ue_time.add(TX_ENB_DELAY * 1e-3); + ue_worker->set_tti(tti); + ue_worker->set_tx_time(ue_time); + + // Start gNb work + ue_phy_com.push_semaphore(ue_worker); + ue_phy.start_worker(ue_worker); + + tti++; + return true; + } +}; + +#endif // SRSRAN_TEST_BENCH_H From 9126ad3b8bbf464d98c1e50903e6d2944caf58cb Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 21 Jun 2021 18:09:28 +0200 Subject: [PATCH 25/43] Added NR type1 RIV function helper --- lib/include/srsran/phy/phch/ra_nr.h | 9 +++++++++ lib/src/phy/phch/ra_dl_nr.c | 5 +++++ lib/src/phy/phch/ra_helper.h | 8 ++++++++ 3 files changed, 22 insertions(+) diff --git a/lib/include/srsran/phy/phch/ra_nr.h b/lib/include/srsran/phy/phch/ra_nr.h index a2ddd5042..eb008ed1d 100644 --- a/lib/include/srsran/phy/phch/ra_nr.h +++ b/lib/include/srsran/phy/phch/ra_nr.h @@ -139,4 +139,13 @@ SRSRAN_API int srsran_ra_ul_set_grant_uci_nr(const srsran_carrier_nr_t* carri const srsran_uci_cfg_nr_t* uci_cfg, srsran_sch_cfg_nr_t* pusch_cfg); +/** + * @brief Calculates frequency allocation type 1 RIV field + * @param N_rb Number of resource blocks + * @param start_rb Start resource block index + * @param length_rb Number of resource blocks + * @return The RIV field with the encoded value + */ +SRSRAN_API uint32_t srsran_ra_nr_type1_riv(uint32_t N_rb, uint32_t start_rb, uint32_t length_rb); + #endif // SRSRAN_RA_NR_H diff --git a/lib/src/phy/phch/ra_dl_nr.c b/lib/src/phy/phch/ra_dl_nr.c index d3bf524e3..78eb6856f 100644 --- a/lib/src/phy/phch/ra_dl_nr.c +++ b/lib/src/phy/phch/ra_dl_nr.c @@ -319,3 +319,8 @@ int srsran_ra_dl_nr_freq(const srsran_carrier_nr_t* carrier, ERROR("Unhandled case"); return SRSRAN_ERROR; } + +uint32_t srsran_ra_nr_type1_riv(uint32_t N_prb, uint32_t start_rb, uint32_t length_rb) +{ + return ra_helper_from_s_and_l(N_prb, start_rb, length_rb); +} \ No newline at end of file diff --git a/lib/src/phy/phch/ra_helper.h b/lib/src/phy/phch/ra_helper.h index 029bb6ad6..004bf6075 100644 --- a/lib/src/phy/phch/ra_helper.h +++ b/lib/src/phy/phch/ra_helper.h @@ -73,6 +73,14 @@ static inline void ra_helper_compute_s_and_l(uint32_t N, uint32_t v, uint32_t* S } } +static inline uint32_t ra_helper_from_s_and_l(uint32_t N, uint32_t S, uint32_t L) +{ + if ((L - 1) <= N / 2) { + return N * (L - 1) + S; + } + return N * (N - L + 1) + (N - 1 - S); +} + static int ra_helper_freq_type1(uint32_t N_bwp_size, uint32_t riv, srsran_sch_grant_nr_t* grant) { uint32_t start = 0; From aef3e5a40acd996130aa4d85ac0bc2140b23c8f0 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 21 Jun 2021 18:10:41 +0200 Subject: [PATCH 26/43] More NR PHY test and GNB PHY development --- lib/include/srsran/common/interfaces_common.h | 1 + .../interfaces/rrc_nr_interface_types.h | 6 +- srsenb/hdr/phy/nr/phy_nr_state.h | 2 + srsenb/hdr/phy/nr/sf_worker.h | 1 + srsenb/hdr/phy/nr/worker_pool.h | 10 +- srsenb/src/phy/nr/cc_worker.cc | 38 +- srsenb/src/phy/nr/phy_nr_state.cc | 12 +- srsenb/src/phy/nr/sf_worker.cc | 37 +- srsenb/src/phy/nr/worker_pool.cc | 12 +- srsue/src/phy/nr/cc_worker.cc | 4 +- srsue/src/phy/nr/worker_pool.cc | 2 +- test/phy/dummy_phy_common.h | 12 +- test/phy/nr_dl_flood.cc | 578 +++++++++--------- test/phy/test_bench.h | 25 +- 14 files changed, 385 insertions(+), 355 deletions(-) diff --git a/lib/include/srsran/common/interfaces_common.h b/lib/include/srsran/common/interfaces_common.h index ce7996205..d2372a58d 100644 --- a/lib/include/srsran/common/interfaces_common.h +++ b/lib/include/srsran/common/interfaces_common.h @@ -23,6 +23,7 @@ namespace srsran { typedef struct { std::string phy_level = "none"; std::string phy_lib_level = "none"; + std::string id_preamble = ""; int phy_hex_limit = -1; } phy_log_args_t; diff --git a/lib/include/srsran/interfaces/rrc_nr_interface_types.h b/lib/include/srsran/interfaces/rrc_nr_interface_types.h index a1725e734..436cbb3da 100644 --- a/lib/include/srsran/interfaces/rrc_nr_interface_types.h +++ b/lib/include/srsran/interfaces/rrc_nr_interface_types.h @@ -29,9 +29,9 @@ struct phy_cfg_nr_t { * SSB configuration */ struct ssb_cfg_t { - uint32_t periodicity_ms; - std::array position_in_burst; - srsran_subcarrier_spacing_t scs; + uint32_t periodicity_ms = 0; + std::array position_in_burst = {}; + srsran_subcarrier_spacing_t scs = srsran_subcarrier_spacing_30kHz; }; srsran_tdd_config_nr_t tdd = {}; diff --git a/srsenb/hdr/phy/nr/phy_nr_state.h b/srsenb/hdr/phy/nr/phy_nr_state.h index ac1783374..64468a80f 100644 --- a/srsenb/hdr/phy/nr/phy_nr_state.h +++ b/srsenb/hdr/phy/nr/phy_nr_state.h @@ -90,6 +90,8 @@ public: */ int rem_rnti(uint16_t rnti); + int get_config(uint16_t rnti, srsran::phy_cfg_nr_t& phy_cfg); + const phy_cell_cfg_list_nr_t& get_carrier_list() const { return cell_cfg_list; } stack_interface_phy_nr& get_stack() { return stack; } diff --git a/srsenb/hdr/phy/nr/sf_worker.h b/srsenb/hdr/phy/nr/sf_worker.h index 0d4b16501..20189e8d9 100644 --- a/srsenb/hdr/phy/nr/sf_worker.h +++ b/srsenb/hdr/phy/nr/sf_worker.h @@ -53,6 +53,7 @@ private: srsran_slot_cfg_t dl_slot_cfg = {}; srsran_slot_cfg_t ul_slot_cfg = {}; srsran::rf_timestamp_t tx_time = {}; + uint32_t sf_len = 0; // Temporal attributes srsran_softbuffer_tx_t softbuffer_tx = {}; diff --git a/srsenb/hdr/phy/nr/worker_pool.h b/srsenb/hdr/phy/nr/worker_pool.h index 9c99d2e38..d909e4be1 100644 --- a/srsenb/hdr/phy/nr/worker_pool.h +++ b/srsenb/hdr/phy/nr/worker_pool.h @@ -29,10 +29,11 @@ class worker_pool public: struct args_t { - uint32_t nof_workers = 3; - uint32_t prio = 52; - std::string log_level = "info"; - uint32_t log_hex_limit = 64; + uint32_t nof_workers = 3; + uint32_t prio = 52; + std::string log_level = "info"; + uint32_t log_hex_limit = 64; + std::string log_id_preamble = ""; }; sf_worker* operator[](std::size_t pos) { return workers.at(pos).get(); } @@ -45,6 +46,7 @@ public: sf_worker* wait_worker_id(uint32_t id); void start_worker(sf_worker* w); void stop(); + bool addmod_rnti(uint16_t rnti, const srsran::phy_cfg_nr_t& phy_cfg); }; } // namespace nr diff --git a/srsenb/src/phy/nr/cc_worker.cc b/srsenb/src/phy/nr/cc_worker.cc index 93a8e1e5a..cadb736fb 100644 --- a/srsenb/src/phy/nr/cc_worker.cc +++ b/srsenb/src/phy/nr/cc_worker.cc @@ -16,7 +16,10 @@ namespace srsenb { namespace nr { cc_worker::cc_worker(const args_t& args, srslog::basic_logger& log, phy_nr_state& phy_state_) : - cc_idx(args.cc_idx), phy_state(phy_state_), logger(log), nof_tx_antennas(args.dl.nof_tx_antennas) + cc_idx(args.cc_idx), + phy_state(phy_state_), + logger(log), + nof_tx_antennas(args.dl.nof_tx_antennas) { cf_t* buffer_c[SRSRAN_MAX_PORTS] = {}; @@ -85,8 +88,20 @@ uint32_t cc_worker::get_buffer_len() int cc_worker::encode_pdcch_dl(stack_interface_phy_nr::dl_sched_grant_t* grants, uint32_t nof_grants) { for (uint32_t i = 0; i < nof_grants; i++) { + uint16_t rnti = grants->dci.ctx.rnti; + // Get PHY config for UE - // ... + srsran::phy_cfg_nr_t cfg = {}; + if (phy_state.get_config(rnti, cfg) < SRSRAN_SUCCESS) { + logger.error("Invalid RNTI 0x%x", rnti); + return SRSRAN_ERROR; + } + + srsran_dci_cfg_nr_t dci_cfg = cfg.get_dci_cfg(); + if (srsran_enb_dl_nr_set_pdcch_config(&gnb_dl, &cfg.pdcch, &dci_cfg) < SRSRAN_SUCCESS) { + logger.error("Invalid CORESET setting"); + return SRSRAN_ERROR; + } // Put actual DCI if (srsran_enb_dl_nr_pdcch_put(&gnb_dl, &dl_slot_cfg, &grants[i].dci) < SRSRAN_SUCCESS) { @@ -95,7 +110,11 @@ int cc_worker::encode_pdcch_dl(stack_interface_phy_nr::dl_sched_grant_t* grants, } if (logger.info.enabled()) { - logger.info("PDCCH: cc=%d, ...", cc_idx); + std::array str = {}; + srsran_dci_dl_nr_to_str(&gnb_dl.dci, &grants[i].dci, str.data(), (uint32_t)str.size()); + if (logger.info.enabled()) { + logger.info("PDCCH: cc=%d %s tti_tx=%d", cc_idx, str.data(), dl_slot_cfg.idx); + } } } @@ -106,14 +125,15 @@ int cc_worker::encode_pdsch(stack_interface_phy_nr::dl_sched_grant_t* grants, ui { for (uint32_t i = 0; i < nof_grants; i++) { // Get PHY config for UE - // ... - srsran_sch_hl_cfg_nr_t pdsch_hl_cfg = {}; - srsran_sch_cfg_nr_t pdsch_cfg = {}; + srsran::phy_cfg_nr_t cfg = {}; + if (phy_state.get_config(grants[i].dci.ctx.rnti, cfg) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } // Compute DL grant + srsran_sch_cfg_nr_t pdsch_cfg = {}; if (srsran_ra_dl_dci_to_grant_nr( - &gnb_dl.carrier, &dl_slot_cfg, &pdsch_hl_cfg, &grants[i].dci, &pdsch_cfg, &pdsch_cfg.grant) < - SRSRAN_SUCCESS) { + &gnb_dl.carrier, &dl_slot_cfg, &cfg.pdsch, &grants[i].dci, &pdsch_cfg, &pdsch_cfg.grant) < SRSRAN_SUCCESS) { ERROR("Computing DL grant"); return SRSRAN_ERROR; } @@ -132,7 +152,7 @@ int cc_worker::encode_pdsch(stack_interface_phy_nr::dl_sched_grant_t* grants, ui if (logger.info.enabled()) { char str[512]; srsran_enb_dl_nr_pdsch_info(&gnb_dl, &pdsch_cfg, str, sizeof(str)); - logger.info("PDSCH: cc=%d, %s", cc_idx, str); + logger.info("PDSCH: cc=%d, %s tti_tx=%d", cc_idx, str, dl_slot_cfg.idx); } } diff --git a/srsenb/src/phy/nr/phy_nr_state.cc b/srsenb/src/phy/nr/phy_nr_state.cc index 9135c0885..80c271b28 100644 --- a/srsenb/src/phy/nr/phy_nr_state.cc +++ b/srsenb/src/phy/nr/phy_nr_state.cc @@ -35,8 +35,6 @@ int phy_nr_state::_assert_rnti(uint16_t rnti) const int phy_nr_state::_get_rnti_config(uint16_t rnti, srsran::phy_cfg_nr_t& phy_cfg) const { - std::lock_guard lock(mutex); - if (_assert_rnti(rnti) < SRSRAN_SUCCESS) { return SRSRAN_ERROR; } @@ -47,7 +45,8 @@ int phy_nr_state::_get_rnti_config(uint16_t rnti, srsran::phy_cfg_nr_t& phy_cfg) } phy_nr_state::phy_nr_state(const phy_cell_cfg_list_nr_t& cell_cfg_list_, stack_interface_phy_nr& stack_) : - cell_cfg_list(cell_cfg_list_), stack(stack_) + cell_cfg_list(cell_cfg_list_), + stack(stack_) {} void phy_nr_state::addmod_rnti(uint16_t rnti, const srsran::phy_cfg_nr_t& phy_cfg) @@ -75,5 +74,12 @@ int phy_nr_state::rem_rnti(uint16_t rnti) return SRSRAN_SUCCESS; } +int phy_nr_state::get_config(uint16_t rnti, srsran::phy_cfg_nr_t& phy_cfg) +{ + std::lock_guard lock(mutex); + + return _get_rnti_config(rnti, phy_cfg); +} + } // namespace nr } // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/phy/nr/sf_worker.cc b/srsenb/src/phy/nr/sf_worker.cc index e165b8f0a..662b77ca9 100644 --- a/srsenb/src/phy/nr/sf_worker.cc +++ b/srsenb/src/phy/nr/sf_worker.cc @@ -14,18 +14,25 @@ namespace srsenb { namespace nr { -sf_worker::sf_worker(srsran::phy_common_interface& common_, phy_nr_state& phy_state_, srslog::basic_logger& logger) : - common(common_), phy_state(phy_state_), logger(logger) +sf_worker::sf_worker(srsran::phy_common_interface& common_, phy_nr_state& phy_state_, srslog::basic_logger& logger_) : + common(common_), + phy_state(phy_state_), + logger(logger_) { + // Set subframe length + sf_len = SRSRAN_SF_LEN_PRB_NR(phy_state.get_carrier_list()[0].carrier.nof_prb); + const phy_cell_cfg_list_nr_t& carrier_list = phy_state.get_carrier_list(); for (uint32_t i = 0; i < (uint32_t)carrier_list.size(); i++) { - cc_worker::args_t cc_args = {}; - cc_args.cc_idx = i; - cc_args.carrier = carrier_list[i].carrier; - cc_args.dl.nof_tx_antennas = 1; - cc_args.dl.nof_max_prb = cc_args.carrier.nof_prb; - - cc_worker* w = new cc_worker(cc_args, logger, phy_state); + cc_worker::args_t cc_args = {}; + cc_args.cc_idx = i; + cc_args.carrier = carrier_list[i].carrier; + cc_args.dl.nof_tx_antennas = 1; + cc_args.dl.nof_max_prb = cc_args.carrier.nof_prb; + cc_args.dl.pdsch.max_prb = cc_args.carrier.nof_prb; + cc_args.dl.pdsch.max_layers = 1; + + cc_worker* w = new cc_worker(cc_args, logger_, phy_state); cc_workers.push_back(std::unique_ptr(w)); } @@ -81,18 +88,20 @@ void sf_worker::set_time(const uint32_t& tti, const srsran::rf_timestamp_t& time void sf_worker::work_imp() { // Get Transmission buffers - srsran::rf_buffer_t tx_buffer = {}; - srsran::rf_timestamp_t dummy_ts = {}; + srsran::rf_buffer_t tx_buffer = {}; for (uint32_t cc = 0; cc < (uint32_t)phy_state.get_carrier_list().size(); cc++) { tx_buffer.set(cc, 0, 1, cc_workers[cc]->get_tx_buffer(0)); } + // Set number of samples + tx_buffer.set_nof_samples(sf_len); + // Get UL Scheduling mac_interface_phy_nr::ul_sched_list_t ul_sched_list = {}; ul_sched_list.resize(1); if (phy_state.get_stack().get_ul_sched(ul_slot_cfg.idx, ul_sched_list) < SRSRAN_SUCCESS) { logger.error("DL Scheduling error"); - common.worker_end(this, true, tx_buffer, dummy_ts, true); + common.worker_end(this, true, tx_buffer, tx_time, true); return; } @@ -101,7 +110,7 @@ void sf_worker::work_imp() dl_sched_list.resize(1); if (phy_state.get_stack().get_dl_sched(ul_slot_cfg.idx, dl_sched_list) < SRSRAN_SUCCESS) { logger.error("DL Scheduling error"); - common.worker_end(this, true, tx_buffer, dummy_ts, true); + common.worker_end(this, true, tx_buffer, tx_time, true); return; } @@ -109,7 +118,7 @@ void sf_worker::work_imp() w->work_dl(dl_sched_list[0], ul_sched_list[0]); } - common.worker_end(this, true, tx_buffer, dummy_ts, true); + common.worker_end(this, true, tx_buffer, tx_time, true); } } // namespace nr diff --git a/srsenb/src/phy/nr/worker_pool.cc b/srsenb/src/phy/nr/worker_pool.cc index 12a0c8edf..dd8726334 100644 --- a/srsenb/src/phy/nr/worker_pool.cc +++ b/srsenb/src/phy/nr/worker_pool.cc @@ -19,12 +19,13 @@ worker_pool::worker_pool(const phy_cell_cfg_list_nr_t& cell_list, srsran::phy_common_interface& common, stack_interface_phy_nr& stack, srslog::sink& log_sink) : - pool(args.nof_workers), phy_state(cell_list, stack) + pool(args.nof_workers), + phy_state(cell_list, stack) { // Add workers to workers pool and start threads srslog::basic_levels log_level = srslog::str_to_basic_level(args.log_level); for (uint32_t i = 0; i < args.nof_workers; i++) { - auto& log = srslog::fetch_basic_logger(fmt::format("PHY{}-NR", i), log_sink); + auto& log = srslog::fetch_basic_logger(fmt::format("{}PHY{}-NR", args.log_id_preamble, i), log_sink); log.set_level(log_level); log.set_hex_dump_max_size(args.log_hex_limit); @@ -54,5 +55,12 @@ void worker_pool::stop() pool.stop(); } +bool worker_pool::addmod_rnti(uint16_t rnti, const srsran::phy_cfg_nr_t& phy_cfg) +{ + phy_state.addmod_rnti(rnti, phy_cfg); + + return true; +} + } // namespace nr } // namespace srsenb \ No newline at end of file diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 1b2269a61..0fa3c1bbf 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -18,7 +18,9 @@ namespace srsue { namespace nr { cc_worker::cc_worker(uint32_t cc_idx_, srslog::basic_logger& log, state& phy_state_) : - cc_idx(cc_idx_), phy(phy_state_), logger(log) + cc_idx(cc_idx_), + phy(phy_state_), + logger(log) { cf_t* rx_buffer_c[SRSRAN_MAX_PORTS] = {}; diff --git a/srsue/src/phy/nr/worker_pool.cc b/srsue/src/phy/nr/worker_pool.cc index 44a30b656..9ac4daede 100644 --- a/srsue/src/phy/nr/worker_pool.cc +++ b/srsue/src/phy/nr/worker_pool.cc @@ -42,7 +42,7 @@ bool worker_pool::init(const phy_args_nr_t& args, // Add workers to workers pool and start threads for (uint32_t i = 0; i < args.nof_phy_threads; i++) { - auto& log = srslog::fetch_basic_logger(fmt::format("PHY{}-NR", i)); + auto& log = srslog::fetch_basic_logger(fmt::format("{}PHY{}-NR", args.log.id_preamble, i)); log.set_level(srslog::str_to_basic_level(args.log.phy_level)); log.set_hex_dump_max_size(args.log.phy_hex_limit); diff --git a/test/phy/dummy_phy_common.h b/test/phy/dummy_phy_common.h index 389b8022b..2f898e90b 100644 --- a/test/phy/dummy_phy_common.h +++ b/test/phy/dummy_phy_common.h @@ -145,7 +145,9 @@ public: uint32_t nof_channels = 1; args_t(double srate_hz_, uint32_t buffer_sz_ms_, uint32_t nof_channels_) : - srate_hz(srate_hz_), buffer_sz_ms(buffer_sz_ms_), nof_channels(nof_channels_) + srate_hz(srate_hz_), + buffer_sz_ms(buffer_sz_ms_), + nof_channels(nof_channels_) {} }; @@ -188,7 +190,9 @@ public: // Check transmit timestamp is not in the past if (tx_ts < write_ts) { - logger.error("Tx time is %d samples in the past", (uint32_t)(write_ts - tx_ts)); + logger.error("Tx time (%f) is %d samples in the past", + srsran_timestamp_real(tx_time.get_ptr(0)), + (uint32_t)(write_ts - tx_ts)); semaphore.release(); return; } @@ -225,9 +229,7 @@ public: read_ts += nof_samples; } - void stop() { - quit = true; - } + void stop() { quit = true; } }; #endif // SRSRAN_DUMMY_PHY_COMMON_H diff --git a/test/phy/nr_dl_flood.cc b/test/phy/nr_dl_flood.cc index b005fd5a6..2407b3b18 100644 --- a/test/phy/nr_dl_flood.cc +++ b/test/phy/nr_dl_flood.cc @@ -19,10 +19,11 @@ test_bench::args_t::args_t(int argc, char** argv) valid = true; cell_list.resize(1); - cell_list[0].carrier.nof_prb = 52; + cell_list[0].carrier.nof_prb = 52; + cell_list[0].carrier.max_mimo_layers = 1; + cell_list[0].carrier.pci = 500; - phy_cfg.carrier = cell_list[0].carrier; - phy_cfg.carrier.pci = 500; + phy_cfg.carrier = cell_list[0].carrier; phy_cfg.carrier.absolute_frequency_point_a = 633928; phy_cfg.carrier.absolute_frequency_ssb = 634176; @@ -213,340 +214,307 @@ test_bench::args_t::args_t(int argc, char** argv) phy_cfg.harq_ack.dl_data_to_ul_ack[6] = 11; phy_cfg.prach.freq_offset = 2; - - // pusch-Config: setup (1) - // setup - // dmrs-UplinkForPUSCH-MappingTypeA: setup (1) - // setup - // dmrs-AdditionalPosition: pos1 (1) - // transformPrecodingDisabled - // pusch-PowerControl - // msg3-Alpha: alpha1 (7) - // p0-NominalWithoutGrant: -90dBm - // p0-AlphaSets: 1 item - // Item 0 - // P0-PUSCH-AlphaSet - // p0-PUSCH-AlphaSetId: 0 - // p0: 0dB - // alpha: alpha1 (7) - // pathlossReferenceRSToAddModList: 1 item - // Item 0 - // PUSCH-PathlossReferenceRS - // pusch-PathlossReferenceRS-Id: 0 - // referenceSignal: ssb-Index (0) - // ssb-Index: 0 - // sri-PUSCH-MappingToAddModList: 1 item - // Item 0 - // SRI-PUSCH-PowerControl - // sri-PUSCH-PowerControlId: 0 - // sri-PUSCH-PathlossReferenceRS-Id: 0 - // sri-P0-PUSCH-AlphaSetId: 0 - // sri-PUSCH-ClosedLoopIndex: i0 (0) - // resourceAllocation: resourceAllocationType1 (1) - // uci-OnPUSCH: setup (1) - // setup - // betaOffsets: semiStatic (1) - // semiStatic - // betaOffsetACK-Index1: 9 - // betaOffsetACK-Index2: 9 - // betaOffsetACK-Index3: 9 - // betaOffsetCSI-Part1-Index1: 6 - // betaOffsetCSI-Part1-Index2: 6 - // betaOffsetCSI-Part2-Index1: 6 - // betaOffsetCSI-Part2-Index2: 6 - // scaling: f1 (3) - // srs-Config: setup (1) - // setup - // srs-ResourceSetToAddModList: 1 item - // Item 0 - // SRS-ResourceSet - // srs-ResourceSetId: 0 - // srs-ResourceIdList: 1 item - // Item 0 - // SRS-ResourceId: 0 - // resourceType: aperiodic (0) - // aperiodic - // aperiodicSRS-ResourceTrigger: 1 - // slotOffset: 7 - // usage: codebook (1) - // p0: -90dBm - // pathlossReferenceRS: ssb-Index (0) - // ssb-Index: 0 - // srs-ResourceToAddModList: 1 item - // Item 0 - // SRS-Resource - // srs-ResourceId: 0 - // nrofSRS-Ports: port1 (0) - // transmissionComb: n2 (0) - // n2 - // combOffset-n2: 0 - // cyclicShift-n2: 0 - // resourceMapping - // startPosition: 0 - // nrofSymbols: n1 (0) - // repetitionFactor: n1 (0) - // freqDomainPosition: 0 - // freqDomainShift: 6 - // freqHopping - // c-SRS: 11 - // b-SRS: 3 - // b-hop: 0 - // groupOrSequenceHopping: neither (0) - // resourceType: aperiodic (0) - // aperiodic - // sequenceId: 500 - // firstActiveUplinkBWP-Id: 0 - // pusch-ServingCellConfig: setup (1) - // setup - // pdcch-ServingCellConfig: setup (1) - // setup - // pdsch-ServingCellConfig: setup (1) - // setup - // nrofHARQ-ProcessesForPDSCH: n16 (5) - // csi-MeasConfig: setup (1) - // setup - // nzp-CSI-RS-ResourceToAddModList: 5 items - // Item 0 - // NZP-CSI-RS-Resource - // nzp-CSI-RS-ResourceId: 0 - // resourceMapping - // frequencyDomainAllocation: row2 (1) - // row2: 8000 [bit length 12, 4 LSB pad bits, 1000 0000 0000 - // .... decimal value 2048] - // nrofPorts: p1 (0) - // firstOFDMSymbolInTimeDomain: 4 - // cdm-Type: noCDM (0) - // density: one (1) - // one: NULL - // freqBand - // startingRB: 0 - // nrofRBs: 52 - // powerControlOffset: 0dB - // powerControlOffsetSS: db0 (1) - // scramblingID: 0 - // periodicityAndOffset: slots80 (9) - // slots80: 1 - // qcl-InfoPeriodicCSI-RS: 0 - // Item 1 - // NZP-CSI-RS-Resource - // nzp-CSI-RS-ResourceId: 1 - // resourceMapping - // frequencyDomainAllocation: row1 (0) - // row1: 10 [bit length 4, 4 LSB pad bits, 0001 .... decimal - // value 1] - // nrofPorts: p1 (0) - // firstOFDMSymbolInTimeDomain: 4 - // cdm-Type: noCDM (0) - // density: three (2) - // three: NULL - // freqBand - // startingRB: 0 - // nrofRBs: 52 - // powerControlOffset: 0dB - // powerControlOffsetSS: db0 (1) - // scramblingID: 0 - // periodicityAndOffset: slots40 (7) - // slots40: 11 - // qcl-InfoPeriodicCSI-RS: 0 - // Item 2 - // NZP-CSI-RS-Resource - // nzp-CSI-RS-ResourceId: 2 - // resourceMapping - // frequencyDomainAllocation: row1 (0) - // row1: 10 [bit length 4, 4 LSB pad bits, 0001 .... decimal - // value 1] - // nrofPorts: p1 (0) - // firstOFDMSymbolInTimeDomain: 8 - // cdm-Type: noCDM (0) - // density: three (2) - // three: NULL - // freqBand - // startingRB: 0 - // nrofRBs: 52 - // powerControlOffset: 0dB - // powerControlOffsetSS: db0 (1) - // scramblingID: 0 - // periodicityAndOffset: slots40 (7) - // slots40: 11 - // qcl-InfoPeriodicCSI-RS: 0 - // Item 3 - // NZP-CSI-RS-Resource - // nzp-CSI-RS-ResourceId: 3 - // resourceMapping - // frequencyDomainAllocation: row1 (0) - // row1: 10 [bit length 4, 4 LSB pad bits, 0001 .... decimal - // value 1] - // nrofPorts: p1 (0) - // firstOFDMSymbolInTimeDomain: 4 - // cdm-Type: noCDM (0) - // density: three (2) - // three: NULL - // freqBand - // startingRB: 0 - // nrofRBs: 52 - // powerControlOffset: 0dB - // powerControlOffsetSS: db0 (1) - // scramblingID: 0 - // periodicityAndOffset: slots40 (7) - // slots40: 12 - // qcl-InfoPeriodicCSI-RS: 0 - // Item 4 - // NZP-CSI-RS-Resource - // nzp-CSI-RS-ResourceId: 4 - // resourceMapping - // frequencyDomainAllocation: row1 (0) - // row1: 10 [bit length 4, 4 LSB pad bits, 0001 .... decimal - // value 1] - // nrofPorts: p1 (0) - // firstOFDMSymbolInTimeDomain: 8 - // cdm-Type: noCDM (0) - // density: three (2) - // three: NULL - // freqBand - // startingRB: 0 - // nrofRBs: 52 - // powerControlOffset: 0dB - // powerControlOffsetSS: db0 (1) - // scramblingID: 0 - // periodicityAndOffset: slots40 (7) - // slots40: 12 - // qcl-InfoPeriodicCSI-RS: 0 - // nzp-CSI-RS-ResourceSetToAddModList: 2 items - // Item 0 - // NZP-CSI-RS-ResourceSet - // nzp-CSI-ResourceSetId: 0 - // nzp-CSI-RS-Resources: 1 item - // Item 0 - // NZP-CSI-RS-ResourceId: 0 - // Item 1 - // NZP-CSI-RS-ResourceSet - // nzp-CSI-ResourceSetId: 1 - // nzp-CSI-RS-Resources: 4 items - // Item 0 - // NZP-CSI-RS-ResourceId: 1 - // Item 1 - // NZP-CSI-RS-ResourceId: 2 - // Item 2 - // NZP-CSI-RS-ResourceId: 3 - // Item 3 - // NZP-CSI-RS-ResourceId: 4 - // trs-Info: true (0) - // csi-IM-ResourceToAddModList: 1 item - // Item 0 - // CSI-IM-Resource - // csi-IM-ResourceId: 0 - // csi-IM-ResourceElementPattern: pattern1 (1) - // pattern1 - // subcarrierLocation-p1: s8 (2) - // symbolLocation-p1: 8 - // freqBand - // startingRB: 0 - // nrofRBs: 52 - // periodicityAndOffset: slots80 (9) - // slots80: 1 - // csi-IM-ResourceSetToAddModList: 1 item - // Item 0 - // CSI-IM-ResourceSet - // csi-IM-ResourceSetId: 0 - // csi-IM-Resources: 1 item - // Item 0 - // CSI-IM-ResourceId: 0 - // csi-ResourceConfigToAddModList: 3 items - // Item 0 - // CSI-ResourceConfig - // csi-ResourceConfigId: 0 - // csi-RS-ResourceSetList: nzp-CSI-RS-SSB (0) - // nzp-CSI-RS-SSB - // nzp-CSI-RS-ResourceSetList: 1 item - // Item 0 - // NZP-CSI-RS-ResourceSetId: 0 - // bwp-Id: 0 - // resourceType: periodic (2) - // Item 1 - // CSI-ResourceConfig - // csi-ResourceConfigId: 1 - // csi-RS-ResourceSetList: csi-IM-ResourceSetList (1) - // csi-IM-ResourceSetList: 1 item - // Item 0 - // CSI-IM-ResourceSetId: 0 - // bwp-Id: 0 - // resourceType: periodic (2) - // Item 2 - // CSI-ResourceConfig - // csi-ResourceConfigId: 2 - // csi-RS-ResourceSetList: nzp-CSI-RS-SSB (0) - // nzp-CSI-RS-SSB - // nzp-CSI-RS-ResourceSetList: 1 item - // Item 0 - // NZP-CSI-RS-ResourceSetId: 1 - // bwp-Id: 0 - // resourceType: periodic (2) - // csi-ReportConfigToAddModList: 1 item - // Item 0 - // CSI-ReportConfig - // reportConfigId: 0 - // resourcesForChannelMeasurement: 0 - // csi-IM-ResourcesForInterference: 1 - // reportConfigType: periodic (0) - // periodic - // reportSlotConfig: slots80 (7) - // slots80: 9 - // pucch-CSI-ResourceList: 1 item - // Item 0 - // PUCCH-CSI-Resource - // uplinkBandwidthPartId: 0 - // pucch-Resource: 17 - // reportQuantity: cri-RI-PMI-CQI (1) - // cri-RI-PMI-CQI: NULL - // reportFreqConfiguration - // cqi-FormatIndicator: widebandCQI (0) - // timeRestrictionForChannelMeasurements: notConfigured (1) - // timeRestrictionForInterferenceMeasurements: notConfigured (1) - // groupBasedBeamReporting: disabled (1) - // disabled - // cqi-Table: table2 (1) - // subbandSize: value1 (0) - // tag-Id: 0 } class ue_dummy_stack : public srsue::stack_interface_phy_nr { +private: + uint16_t rnti = 0; + bool valid = false; + + struct dummy_harq_proc { + static const uint32_t MAX_TB_SZ = SRSRAN_LDPC_MAX_LEN_CB * SRSRAN_SCH_NR_MAX_NOF_CB_LDPC; + srsran_softbuffer_rx_t softbuffer = {}; + + dummy_harq_proc() + { + // Initialise softbuffer + if (srsran_softbuffer_rx_init_guru(&softbuffer, SRSRAN_SCH_NR_MAX_NOF_CB_LDPC, SRSRAN_LDPC_MAX_LEN_ENCODED_CB) < + SRSRAN_SUCCESS) { + ERROR("Error Tx buffer"); + } + } + + ~dummy_harq_proc() { srsran_softbuffer_rx_free(&softbuffer); } + }; + srsran::circular_array rx_harq_proc; + public: + struct args_t { + uint16_t rnti = 0x1234; + }; + ue_dummy_stack(const args_t& args) : rnti(args.rnti) { valid = true; } void in_sync() override {} void out_of_sync() override {} void run_tti(const uint32_t tti) override {} int sf_indication(const uint32_t tti) override { return 0; } - sched_rnti_t get_dl_sched_rnti_nr(const uint32_t tti) override { return sched_rnti_t(); } - sched_rnti_t get_ul_sched_rnti_nr(const uint32_t tti) override { return sched_rnti_t(); } - void new_grant_dl(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_t* action) override {} + sched_rnti_t get_dl_sched_rnti_nr(const uint32_t tti) override { return {rnti, srsran_rnti_type_c}; } + sched_rnti_t get_ul_sched_rnti_nr(const uint32_t tti) override { return {rnti, srsran_rnti_type_c}; } + void new_grant_dl(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_t* action) override + { + action->tb.enabled = true; + action->tb.softbuffer = &rx_harq_proc[grant.pid].softbuffer; + } void tb_decoded(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_result_t result) override {} void new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant, tb_action_ul_t* action) override {} void prach_sent(uint32_t tti, uint32_t s_id, uint32_t t_id, uint32_t f_id, uint32_t ul_carrier_id) override {} bool sr_opportunity(uint32_t tti, uint32_t sr_id, bool meas_gap, bool ul_sch_tx) override { return false; } + bool is_valid() const { return valid; } }; class gnb_dummy_stack : public srsenb::stack_interface_phy_nr { +private: + srslog::basic_logger& logger = srslog::fetch_basic_logger("GNB STK"); + const uint16_t rnti = 0x1234; + const uint32_t mcs = 1; + const srsran::circular_array pdsch_mask; + srsran::circular_array dci_dl_location; + srsran::circular_array dci_ul_location; + srsran::circular_array dl_data_to_ul_ack; + bool valid = false; + srsran_search_space_t ss = {}; + srsran_dci_format_nr_t dci_format_ul = SRSRAN_DCI_FORMAT_NR_COUNT; + srsran_dci_format_nr_t dci_format_dl = SRSRAN_DCI_FORMAT_NR_COUNT; + uint32_t dl_freq_res = 0; + uint32_t dl_time_res = 0; + srsran_random_t random_gen = nullptr; + + struct dummy_harq_proc { + static const uint32_t MAX_TB_SZ = SRSRAN_LDPC_MAX_LEN_CB * SRSRAN_SCH_NR_MAX_NOF_CB_LDPC; + std::vector data; + srsran_softbuffer_tx_t softbuffer = {}; + + dummy_harq_proc() + { + // Allocate data + data.resize(MAX_TB_SZ); + + // Initialise softbuffer + if (srsran_softbuffer_tx_init_guru(&softbuffer, SRSRAN_SCH_NR_MAX_NOF_CB_LDPC, SRSRAN_LDPC_MAX_LEN_ENCODED_CB) < + SRSRAN_SUCCESS) { + ERROR("Error Tx buffer"); + } + } + + ~dummy_harq_proc() { srsran_softbuffer_tx_free(&softbuffer); } + }; + srsran::circular_array tx_harq_proc; + public: + struct args_t { + srsran::phy_cfg_nr_t phy_cfg; ///< Physical layer configuration + uint16_t rnti = 0x1234; ///< C-RNTI + uint32_t mcs = 10; ///< Modulation code scheme + srsran::circular_array pdsch_mask = {}; ///< PDSCH scheduling mask + uint32_t ss_id = 1; ///< Search Space identifier + uint32_t pdcch_aggregation_level = 0; ///< PDCCH aggregation level + uint32_t pdcch_dl_candidate_index = 0; ///< PDCCH DL DCI candidate index + uint32_t pdcch_ul_candidate_index = 0; ///< PDCCH UL DCI candidate index + uint32_t dl_start_rb = 0; ///< Start resource block + uint32_t dl_length_rb = 0l; ///< Number of resource blocks + uint32_t dl_time_res = 0; ///< PDSCH time resource + }; + + gnb_dummy_stack(args_t args) : + pdsch_mask(args.pdsch_mask), + mcs(args.mcs), + rnti(args.rnti), + dl_time_res(args.dl_time_res) + { + random_gen = srsran_random_init(0x1234); + + // Select search space + if (args.ss_id >= SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE) { + logger.error("Search Space Id (%d) is out-of-range (%d)", args.ss_id, SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE); + return; + } + if (not args.phy_cfg.pdcch.search_space_present[args.ss_id]) { + logger.error("Search Space Id (%d) is not present", args.ss_id); + return; + } + ss = args.phy_cfg.pdcch.search_space[args.ss_id]; + + // Select CORESET + if (ss.coreset_id >= SRSRAN_UE_DL_NR_MAX_NOF_CORESET) { + logger.error("CORESET Id (%d) is out-of-range (%d)", ss.coreset_id, SRSRAN_UE_DL_NR_MAX_NOF_CORESET); + return; + } + if (not args.phy_cfg.pdcch.coreset_present[ss.coreset_id]) { + logger.error("CORESET Id (%d) is not present", args.ss_id); + return; + } + const srsran_coreset_t& coreset = args.phy_cfg.pdcch.coreset[ss.coreset_id]; + + // Select DCI locations + for (uint32_t slot = 0; slot < SRSRAN_NOF_SF_X_FRAME; slot++) { + std::array ncce = {}; + int n = srsran_pdcch_nr_locations_coreset(&coreset, &ss, rnti, args.pdcch_aggregation_level, slot++, ncce.data()); + if (n < SRSRAN_SUCCESS) { + logger.error( + "Error generating locations for slot %d and aggregation level %d", slot, args.pdcch_aggregation_level); + return; + } + uint32_t nof_candidates = (uint32_t)n; + + // DCI DL + if (args.pdcch_dl_candidate_index >= nof_candidates or + args.pdcch_dl_candidate_index >= SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR) { + logger.error("Candidate index %d exceeds the number of candidates %d for aggregation level %d", + args.pdcch_dl_candidate_index, + n, + args.pdcch_aggregation_level); + return; + } + dci_dl_location[slot].L = args.pdcch_aggregation_level; + dci_dl_location[slot].ncce = ncce[args.pdcch_dl_candidate_index]; + + // DCI UL + if (args.pdcch_ul_candidate_index >= nof_candidates or + args.pdcch_ul_candidate_index >= SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR) { + logger.error("Candidate index %d exceeds the number of candidates %d for aggregation level %d", + args.pdcch_ul_candidate_index, + n, + args.pdcch_aggregation_level); + return; + } + dci_ul_location[slot].L = args.pdcch_aggregation_level; + dci_ul_location[slot].ncce = ncce[args.pdcch_ul_candidate_index]; + } + + // Select DCI formats + for (uint32_t i = 0; i < ss.nof_formats; i++) { + // Select DL format + if (ss.formats[i] == srsran_dci_format_nr_1_0 or ss.formats[i] == srsran_dci_format_nr_1_1) { + dci_format_dl = ss.formats[i]; + } + + // Select DL format + if (ss.formats[i] == srsran_dci_format_nr_0_0 or ss.formats[i] == srsran_dci_format_nr_0_1) { + dci_format_ul = ss.formats[i]; + } + } + + // Validate that a DCI format is selected + if (dci_format_dl == SRSRAN_DCI_FORMAT_NR_COUNT or dci_format_ul == SRSRAN_DCI_FORMAT_NR_COUNT) { + logger.error("Missing valid DL or UL DCI format in search space"); + return; + } + + // Select DL frequency domain resources + dl_freq_res = srsran_ra_nr_type1_riv(args.phy_cfg.carrier.nof_prb, args.dl_start_rb, args.dl_length_rb); + + // Setup DL Data to ACK timing + for (uint32_t i = 0; i < SRSRAN_NOF_SF_X_FRAME; i++) { + dl_data_to_ul_ack[i] = args.phy_cfg.harq_ack.dl_data_to_ul_ack[i % SRSRAN_MAX_NOF_DL_DATA_TO_UL]; + } + + // If reached this point the configuration is valid + valid = true; + } + + ~gnb_dummy_stack() { srsran_random_free(random_gen); } + + bool is_valid() const { return valid; } + int sf_indication(const uint32_t tti) override { return 0; } int rx_data_indication(rx_data_ind_t& grant) override { return 0; } + int get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res) override { - dl_sched_res[0].nof_grants = 0; + // Check input + if (dl_sched_res.size() == 0) { + return SRSRAN_ERROR; + } + + // Check PDSCH mask, if no PDSCH shall be scheduled, do not set any grant and skip + if (not pdsch_mask[tti]) { + dl_sched_res[0].nof_grants = 0; + return SRSRAN_SUCCESS; + } + + // Select grant and set data + dl_sched_grant_t& grant = dl_sched_res[0].pdsch[0]; + grant.data[0] = tx_harq_proc[tti].data.data(); + grant.softbuffer_tx[0] = &tx_harq_proc[tti].softbuffer; + + // Second TB is not used + grant.data[1] = nullptr; + grant.softbuffer_tx[1] = nullptr; + + // Reset Tx softbuffer always + srsran_softbuffer_tx_reset(grant.softbuffer_tx[0]); + + // Generate random data + srsran_random_byte_vector(random_gen, grant.data[0], SRSRAN_LDPC_MAX_LEN_CB * SRSRAN_SCH_NR_MAX_NOF_CB_LDPC / 8); + + // It currently support only one grant + dl_sched_res[0].nof_grants = 1; + + // Fill DCI + srsran_dci_dl_nr_t& dci = grant.dci; + dci.ctx.location = dci_dl_location[tti]; + dci.ctx.ss_type = ss.type; + dci.ctx.coreset_id = ss.coreset_id; + dci.ctx.rnti_type = srsran_rnti_type_c; + dci.ctx.format = dci_format_dl; + dci.ctx.rnti = rnti; + dci.freq_domain_assigment = dl_freq_res; + dci.time_domain_assigment = dl_time_res; + dci.mcs = mcs; + dci.rv = 0; + dci.ndi = (tti / SRSRAN_NOF_SF_X_FRAME) % 2; + dci.pid = tti % SRSRAN_NOF_SF_X_FRAME; + dci.dai = tti % SRSRAN_NOF_SF_X_FRAME; + dci.tpc = 1; + dci.pucch_resource = 0; + dci.harq_feedback = dl_data_to_ul_ack[tti]; + return SRSRAN_SUCCESS; } + int get_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res) override { return 0; } }; int main(int argc, char** argv) { + srslog::init(); + + // Parse test bench arguments test_bench::args_t args(argc, argv); + args.gnb_args.log_id_preamble = "GNB/"; + args.gnb_args.log_level = "warning"; + args.gnb_args.nof_workers = 1; + args.ue_args.log.id_preamble = " UE/"; + args.ue_args.log.phy_level = "warning"; + args.ue_args.log.phy_hex_limit = 0; + args.ue_args.nof_phy_threads = 1; // Parse arguments TESTASSERT(args.valid); - ue_dummy_stack ue_stack; - gnb_dummy_stack gnb_stack; + // Create UE stack arguments + ue_dummy_stack::args_t ue_stack_args = {}; + ue_stack_args.rnti = 0x1234; + + // Create UE stack + ue_dummy_stack ue_stack(ue_stack_args); + TESTASSERT(ue_stack.is_valid()); + + // Create GNB stack arguments + gnb_dummy_stack::args_t gnb_stack_args = {}; + gnb_stack_args.rnti = 0x1234; + gnb_stack_args.mcs = 10; + for (bool& mask : gnb_stack_args.pdsch_mask) { + mask = true; + } + gnb_stack_args.phy_cfg = args.phy_cfg; + gnb_stack_args.dl_start_rb = 0; + gnb_stack_args.dl_length_rb = args.phy_cfg.carrier.nof_prb; + + // Create GNB stack + gnb_dummy_stack gnb_stack(gnb_stack_args); + TESTASSERT(gnb_stack.is_valid()); // Create test bench test_bench tb(args, gnb_stack, ue_stack); @@ -554,10 +522,10 @@ int main(int argc, char** argv) // Assert bench is initialised correctly TESTASSERT(tb.is_initialised()); - for (uint32_t i = 0; i < 1000; i++) { + for (uint32_t i = 0; i < 20; i++) { TESTASSERT(tb.run_tti()); } // If reached here, the test is successful return SRSRAN_SUCCESS; -} \ No newline at end of file +} diff --git a/test/phy/test_bench.h b/test/phy/test_bench.h index ff572d958..b878cb355 100644 --- a/test/phy/test_bench.h +++ b/test/phy/test_bench.h @@ -20,7 +20,9 @@ class test_bench { private: - uint32_t tti = 0; + const std::string UE_PHY_COM_LOG_NAME = "UE /PHY/COM"; + const std::string GNB_PHY_COM_LOG_NAME = "GNB/PHY/COM"; + uint32_t tti = 0; srsenb::nr::worker_pool gnb_phy; phy_common gnb_phy_com; srsue::nr::worker_pool ue_phy; @@ -38,7 +40,9 @@ public: srsran::phy_cfg_nr_t phy_cfg = {}; srsenb::phy_cell_cfg_list_nr_t cell_list = {}; srsenb::nr::worker_pool::args_t gnb_args; - uint16_t rnti = 0x1234; + srsue::phy_args_nr_t ue_args; + uint16_t rnti = 0x1234; + std::string phy_com_log_level = "info"; args_t(int argc, char** argv); }; @@ -47,18 +51,18 @@ public: ue_phy(args.nof_threads), gnb_phy(args.cell_list, args.gnb_args, gnb_phy_com, gnb_stack, srslog::get_default_sink()), ue_phy_com(phy_common::args_t(args.srate_hz, args.buffer_sz_ms, args.nof_channels), - srslog::fetch_basic_logger("UE /PHY/COM")), + srslog::fetch_basic_logger(UE_PHY_COM_LOG_NAME, srslog::get_default_sink(), false)), gnb_phy_com(phy_common::args_t(args.srate_hz, args.buffer_sz_ms, args.nof_channels), - srslog::fetch_basic_logger("GNB/PHY/COM")) + srslog::fetch_basic_logger(GNB_PHY_COM_LOG_NAME, srslog::get_default_sink(), false)) { + srslog::fetch_basic_logger(UE_PHY_COM_LOG_NAME).set_level(srslog::str_to_basic_level(args.phy_com_log_level)); + srslog::fetch_basic_logger(GNB_PHY_COM_LOG_NAME).set_level(srslog::str_to_basic_level(args.phy_com_log_level)); + // Calculate subframe length sf_sz = (uint32_t)std::round(args.srate_hz * 1e-3); - // Prepare PHY - srsue::phy_args_nr_t ue_phy_args = {}; - // Initialise UE PHY - if (not ue_phy.init(ue_phy_args, ue_phy_com, &ue_stack, 31)) { + if (not ue_phy.init(args.ue_args, ue_phy_com, &ue_stack, 31)) { return; } @@ -67,6 +71,11 @@ public: return; } + // Set UE configuration in gNb + if (not gnb_phy.addmod_rnti(args.rnti, args.phy_cfg)) { + return; + } + initialised = true; } From c4e13f70a2a9c497126bceb70ccda427039c63fd Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 22 Jun 2021 10:04:24 +0200 Subject: [PATCH 27/43] SRSENB: fix NR worker pointer check --- srsenb/src/phy/phy.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/srsenb/src/phy/phy.cc b/srsenb/src/phy/phy.cc index ee8dadcbe..76d5f9afe 100644 --- a/srsenb/src/phy/phy.cc +++ b/srsenb/src/phy/phy.cc @@ -159,7 +159,9 @@ void phy::stop() tx_rx.stop(); workers_common.stop(); lte_workers.stop(); - nr_workers->stop(); + if (nr_workers != nullptr) { + nr_workers->stop(); + } prach.stop(); initialized = false; From 8378c85ec45c4e1cf647a08b0d904c2f6ad8489c Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 23 Jun 2021 12:59:32 +0200 Subject: [PATCH 28/43] Refactored gNb PHY --- .../srsran/interfaces/gnb_interfaces.h | 70 +++-- lib/include/srsran/phy/enb/enb_dl_nr.h | 15 +- lib/src/phy/enb/enb_dl_nr.c | 89 ++++-- lib/test/phy/phy_dl_nr_test.c | 2 +- srsenb/hdr/phy/nr/cc_worker.h | 69 ----- srsenb/hdr/phy/nr/phy_nr_state.h | 103 ------- srsenb/hdr/phy/nr/sf_worker.h | 66 ----- srsenb/hdr/phy/nr/slot_worker.h | 90 ++++++ srsenb/hdr/phy/nr/worker_pool.h | 42 +-- srsenb/hdr/phy/phy_interfaces.h | 43 +-- srsenb/hdr/stack/gnb_stack_nr.h | 16 +- srsenb/hdr/stack/mac/mac_nr.h | 5 +- srsenb/src/phy/CMakeLists.txt | 4 +- srsenb/src/phy/nr/cc_worker.cc | 186 ------------- srsenb/src/phy/nr/phy_nr_state.cc | 85 ------ srsenb/src/phy/nr/sf_worker.cc | 125 --------- srsenb/src/phy/nr/slot_worker.cc | 262 ++++++++++++++++++ srsenb/src/phy/nr/worker_pool.cc | 55 ++-- srsenb/src/phy/txrx.cc | 10 +- srsenb/src/stack/gnb_stack_nr.cc | 12 +- srsenb/src/stack/mac/nr/mac_nr.cc | 9 +- srsenb/test/phy/enb_phy_test.cc | 3 +- test/phy/dummy_gnb_stack.h | 239 ++++++++++++++++ test/phy/dummy_phy_common.h | 13 +- test/phy/nr_dl_flood.cc | 244 +--------------- test/phy/test_bench.h | 22 +- 26 files changed, 856 insertions(+), 1023 deletions(-) delete mode 100644 srsenb/hdr/phy/nr/cc_worker.h delete mode 100644 srsenb/hdr/phy/nr/phy_nr_state.h delete mode 100644 srsenb/hdr/phy/nr/sf_worker.h create mode 100644 srsenb/hdr/phy/nr/slot_worker.h delete mode 100644 srsenb/src/phy/nr/cc_worker.cc delete mode 100644 srsenb/src/phy/nr/phy_nr_state.cc delete mode 100644 srsenb/src/phy/nr/sf_worker.cc create mode 100644 srsenb/src/phy/nr/slot_worker.cc create mode 100644 test/phy/dummy_gnb_stack.h diff --git a/lib/include/srsran/interfaces/gnb_interfaces.h b/lib/include/srsran/interfaces/gnb_interfaces.h index f8f41b677..c061c58cc 100644 --- a/lib/include/srsran/interfaces/gnb_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_interfaces.h @@ -212,52 +212,50 @@ class mac_interface_phy_nr public: const static int MAX_GRANTS = 64; - /** - * DL grant structure per UE - */ - struct dl_sched_grant_t { - srsran_dci_dl_nr_t dci = {}; - uint8_t* data[SRSRAN_MAX_TB] = {}; - srsran_softbuffer_tx_t* softbuffer_tx[SRSRAN_MAX_TB] = {}; + struct pdcch_dl_t { + srsran_dci_cfg_nr_t dci_cfg = {}; + srsran_dci_dl_nr_t dci = {}; + }; + + struct pdcch_ul_t { + srsran_dci_cfg_nr_t dci_cfg = {}; + srsran_dci_ul_nr_t dci = {}; + }; + + struct pdsch_t { + srsran_sch_cfg_nr_t sch = {}; ///< PDSCH configuration + std::array data = {}; ///< Data pointer }; - /** - * DL Scheduling result per cell/carrier - */ struct dl_sched_t { - dl_sched_grant_t pdsch[MAX_GRANTS]; //< DL Grants - uint32_t nof_grants; //< Number of DL grants + std::array pdcch_dl; + uint32_t pdcch_dl_count = 0; + std::array pdcch_ul; + uint32_t pdcch_ul_count = 0; + std::array pdsch; + uint32_t pdsch_count = 0; }; - /** - * List of DL scheduling results, one entry per cell/carrier - */ - typedef std::vector dl_sched_list_t; - - /** - * UL grant structure per UE - */ - struct ul_sched_grant_t { - srsran_dci_ul_nr_t dci = {}; - uint8_t* data = nullptr; - srsran_softbuffer_rx_t* softbuffer_rx = nullptr; + struct pusch_t { + srsran_sch_cfg_nr_t sch = {}; ///< PUSCH configuration + std::array data = {}; ///< Data pointer + std::array softbuffer_tx = {}; ///< Tx Softbuffer }; - /** - * UL Scheduling result per cell/carrier - */ - struct ul_sched_t { - ul_sched_grant_t pusch[MAX_GRANTS]; //< UL Grants - uint32_t nof_grants; //< Number of UL grants + struct uci_t { + srsran_uci_cfg_nr_t cfg; }; - /** - * List of UL scheduling results, one entry per cell/carrier - */ - typedef std::vector ul_sched_list_t; + struct ul_sched_t { + std::array pusch; + uint32_t pusch_count = 0; + std::array uci; + uint32_t uci_count; + }; - virtual int get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res) = 0; - virtual int get_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res) = 0; + virtual int slot_indication(const srsran_slot_cfg_t& slot_cfg) = 0; + virtual int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) = 0; + virtual int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) = 0; }; class stack_interface_phy_nr : public mac_interface_phy_nr, public srsran::stack_interface_phy_nr diff --git a/lib/include/srsran/phy/enb/enb_dl_nr.h b/lib/include/srsran/phy/enb/enb_dl_nr.h index 4e5601a1e..edc7c8ac5 100644 --- a/lib/include/srsran/phy/enb/enb_dl_nr.h +++ b/lib/include/srsran/phy/enb/enb_dl_nr.h @@ -57,8 +57,13 @@ SRSRAN_API int srsran_enb_dl_nr_base_zero(srsran_enb_dl_nr_t* q); SRSRAN_API void srsran_enb_dl_nr_gen_signal(srsran_enb_dl_nr_t* q); -SRSRAN_API int -srsran_enb_dl_nr_pdcch_put(srsran_enb_dl_nr_t* q, const srsran_slot_cfg_t* slot_cfg, const srsran_dci_dl_nr_t* dci_dl); +SRSRAN_API int srsran_enb_dl_nr_pdcch_put_dl(srsran_enb_dl_nr_t* q, + const srsran_slot_cfg_t* slot_cfg, + const srsran_dci_dl_nr_t* dci_dl); + +SRSRAN_API int srsran_enb_dl_nr_pdcch_put_ul(srsran_enb_dl_nr_t* q, + const srsran_slot_cfg_t* slot_cfg, + const srsran_dci_ul_nr_t* dci_ul); SRSRAN_API int srsran_enb_dl_nr_pdsch_put(srsran_enb_dl_nr_t* q, const srsran_slot_cfg_t* slot, @@ -68,4 +73,10 @@ SRSRAN_API int srsran_enb_dl_nr_pdsch_put(srsran_enb_dl_nr_t* q, SRSRAN_API int srsran_enb_dl_nr_pdsch_info(const srsran_enb_dl_nr_t* q, const srsran_sch_cfg_nr_t* cfg, char* str, uint32_t str_len); +SRSRAN_API int +srsran_enb_dl_nr_pdcch_dl_info(const srsran_enb_dl_nr_t* q, const srsran_dci_dl_nr_t* dci, char* str, uint32_t str_len); + +SRSRAN_API int +srsran_enb_dl_nr_pdcch_ul_info(const srsran_enb_dl_nr_t* q, const srsran_dci_ul_nr_t* dci, char* str, uint32_t str_len); + #endif // SRSRAN_ENB_DL_NR_H diff --git a/lib/src/phy/enb/enb_dl_nr.c b/lib/src/phy/enb/enb_dl_nr.c index b78928e02..f98cc411c 100644 --- a/lib/src/phy/enb/enb_dl_nr.c +++ b/lib/src/phy/enb/enb_dl_nr.c @@ -180,20 +180,15 @@ int srsran_enb_dl_nr_base_zero(srsran_enb_dl_nr_t* q) return SRSRAN_SUCCESS; } -int srsran_enb_dl_nr_pdcch_put(srsran_enb_dl_nr_t* q, - const srsran_slot_cfg_t* slot_cfg, - const srsran_dci_dl_nr_t* dci_dl) +static int +enb_dl_nr_pdcch_put_msg(srsran_enb_dl_nr_t* q, const srsran_slot_cfg_t* slot_cfg, const srsran_dci_msg_nr_t* dci_msg) { - if (q == NULL || slot_cfg == NULL || dci_dl == NULL) { - return SRSRAN_ERROR_INVALID_INPUTS; - } - - if (dci_dl->ctx.coreset_id >= SRSRAN_UE_DL_NR_MAX_NOF_CORESET || - !q->pdcch_cfg.coreset_present[dci_dl->ctx.coreset_id]) { - ERROR("Invalid CORESET ID %d", dci_dl->ctx.coreset_id); + if (dci_msg->ctx.coreset_id >= SRSRAN_UE_DL_NR_MAX_NOF_CORESET || + !q->pdcch_cfg.coreset_present[dci_msg->ctx.coreset_id]) { + ERROR("Invalid CORESET ID %d", dci_msg->ctx.coreset_id); return SRSRAN_ERROR; } - srsran_coreset_t* coreset = &q->pdcch_cfg.coreset[dci_dl->ctx.coreset_id]; + srsran_coreset_t* coreset = &q->pdcch_cfg.coreset[dci_msg->ctx.coreset_id]; if (srsran_pdcch_nr_set_carrier(&q->pdcch, &q->carrier, coreset) < SRSRAN_SUCCESS) { ERROR("Error setting PDCCH carrier/CORESET"); @@ -201,11 +196,31 @@ int srsran_enb_dl_nr_pdcch_put(srsran_enb_dl_nr_t* q, } // Put DMRS - if (srsran_dmrs_pdcch_put(&q->carrier, coreset, slot_cfg, &dci_dl->ctx.location, q->sf_symbols[0]) < SRSRAN_SUCCESS) { + if (srsran_dmrs_pdcch_put(&q->carrier, coreset, slot_cfg, &dci_msg->ctx.location, q->sf_symbols[0]) < + SRSRAN_SUCCESS) { ERROR("Error putting PDCCH DMRS"); return SRSRAN_ERROR; } + // PDCCH Encode + if (srsran_pdcch_nr_encode(&q->pdcch, dci_msg, q->sf_symbols[0]) < SRSRAN_SUCCESS) { + ERROR("Error encoding PDCCH"); + return SRSRAN_ERROR; + } + + INFO("DCI DL NR: L=%d; ncce=%d;", dci_msg->ctx.location.L, dci_msg->ctx.location.ncce); + + return SRSRAN_SUCCESS; +} + +int srsran_enb_dl_nr_pdcch_put_dl(srsran_enb_dl_nr_t* q, + const srsran_slot_cfg_t* slot_cfg, + const srsran_dci_dl_nr_t* dci_dl) +{ + if (q == NULL || slot_cfg == NULL || dci_dl == NULL) { + return SRSRAN_ERROR_INVALID_INPUTS; + } + // Pack DCI srsran_dci_msg_nr_t dci_msg = {}; if (srsran_dci_nr_dl_pack(&q->dci, dci_dl, &dci_msg) < SRSRAN_SUCCESS) { @@ -213,15 +228,29 @@ int srsran_enb_dl_nr_pdcch_put(srsran_enb_dl_nr_t* q, return SRSRAN_ERROR; } - // PDCCH Encode - if (srsran_pdcch_nr_encode(&q->pdcch, &dci_msg, q->sf_symbols[0]) < SRSRAN_SUCCESS) { - ERROR("Error encoding PDCCH"); + INFO("DCI DL NR: L=%d; ncce=%d;", dci_dl->ctx.location.L, dci_dl->ctx.location.ncce); + + return enb_dl_nr_pdcch_put_msg(q, slot_cfg, &dci_msg); +} + +int srsran_enb_dl_nr_pdcch_put_ul(srsran_enb_dl_nr_t* q, + const srsran_slot_cfg_t* slot_cfg, + const srsran_dci_ul_nr_t* dci_ul) +{ + if (q == NULL || slot_cfg == NULL || dci_ul == NULL) { + return SRSRAN_ERROR_INVALID_INPUTS; + } + + // Pack DCI + srsran_dci_msg_nr_t dci_msg = {}; + if (srsran_dci_nr_ul_pack(&q->dci, dci_ul, &dci_msg) < SRSRAN_SUCCESS) { + ERROR("Error packing UL DCI"); return SRSRAN_ERROR; } - INFO("DCI DL NR: L=%d; ncce=%d;", dci_dl->ctx.location.L, dci_dl->ctx.location.ncce); + INFO("DCI DL NR: L=%d; ncce=%d;", dci_ul->ctx.location.L, dci_ul->ctx.location.ncce); - return SRSRAN_SUCCESS; + return enb_dl_nr_pdcch_put_msg(q, slot_cfg, &dci_msg); } int srsran_enb_dl_nr_pdsch_put(srsran_enb_dl_nr_t* q, @@ -252,3 +281,29 @@ int srsran_enb_dl_nr_pdsch_info(const srsran_enb_dl_nr_t* q, return len; } + +int srsran_enb_dl_nr_pdcch_dl_info(const srsran_enb_dl_nr_t* q, + const srsran_dci_dl_nr_t* dci, + char* str, + uint32_t str_len) +{ + int len = 0; + + // Append PDCCH info + len += srsran_dci_dl_nr_to_str(&q->dci, dci, &str[len], str_len - len); + + return len; +} + +int srsran_enb_dl_nr_pdcch_ul_info(const srsran_enb_dl_nr_t* q, + const srsran_dci_ul_nr_t* dci, + char* str, + uint32_t str_len) +{ + int len = 0; + + // Append PDCCH info + len += srsran_dci_ul_nr_to_str(&q->dci, dci, &str[len], str_len - len); + + return len; +} diff --git a/lib/test/phy/phy_dl_nr_test.c b/lib/test/phy/phy_dl_nr_test.c index d9fd1960f..c07bed2a9 100644 --- a/lib/test/phy/phy_dl_nr_test.c +++ b/lib/test/phy/phy_dl_nr_test.c @@ -170,7 +170,7 @@ static int work_gnb_dl(srsran_enb_dl_nr_t* enb_dl, dci_dl.rv = 0; // Put actual DCI - if (srsran_enb_dl_nr_pdcch_put(enb_dl, slot, &dci_dl) < SRSRAN_SUCCESS) { + if (srsran_enb_dl_nr_pdcch_put_dl(enb_dl, slot, &dci_dl) < SRSRAN_SUCCESS) { ERROR("Error putting PDCCH"); return SRSRAN_ERROR; } diff --git a/srsenb/hdr/phy/nr/cc_worker.h b/srsenb/hdr/phy/nr/cc_worker.h deleted file mode 100644 index e08eaf961..000000000 --- a/srsenb/hdr/phy/nr/cc_worker.h +++ /dev/null @@ -1,69 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 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. - * - */ - -#ifndef SRSENB_NR_CC_WORKER_H -#define SRSENB_NR_CC_WORKER_H - -#include "phy_nr_state.h" -#include "srsenb/hdr/phy/phy_interfaces.h" -#include "srsran/interfaces/gnb_interfaces.h" -#include "srsran/interfaces/rrc_nr_interface_types.h" -#include "srsran/phy/enb/enb_dl_nr.h" -#include "srsran/srslog/srslog.h" -#include "srsran/srsran.h" -#include -#include - -namespace srsenb { -namespace nr { - -class cc_worker -{ -public: - struct args_t { - uint32_t cc_idx = 0; - srsran_carrier_nr_t carrier = {}; - srsran_enb_dl_nr_args_t dl = {}; - }; - - cc_worker(const args_t& args, srslog::basic_logger& logger, phy_nr_state& phy_state_); - ~cc_worker(); - - void set_tti(uint32_t tti); - - cf_t* get_tx_buffer(uint32_t antenna_idx); - cf_t* get_rx_buffer(uint32_t antenna_idx); - uint32_t get_buffer_len(); - - bool work_dl(stack_interface_phy_nr::dl_sched_t& dl_grants, stack_interface_phy_nr::ul_sched_t& ul_grants); - bool work_ul(); - -private: - int encode_pdsch(stack_interface_phy_nr::dl_sched_grant_t* grants, uint32_t nof_grants); - int encode_pdcch_dl(stack_interface_phy_nr::dl_sched_grant_t* grants, uint32_t nof_grants); - - uint32_t nof_tx_antennas = 0; - srsran_slot_cfg_t dl_slot_cfg = {}; - srsran_slot_cfg_t ul_slot_cfg = {}; - uint32_t cc_idx = 0; - std::array tx_buffer = {}; - std::array rx_buffer = {}; - uint32_t buffer_sz = 0; - phy_nr_state& phy_state; - srsran_enb_dl_nr_t gnb_dl = {}; - srslog::basic_logger& logger; -}; - -} // namespace nr -} // namespace srsenb - -#endif // SRSENB_NR_CC_WORKER_H diff --git a/srsenb/hdr/phy/nr/phy_nr_state.h b/srsenb/hdr/phy/nr/phy_nr_state.h deleted file mode 100644 index 64468a80f..000000000 --- a/srsenb/hdr/phy/nr/phy_nr_state.h +++ /dev/null @@ -1,103 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2020 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. - * - */ - -#ifndef SRSENB_PHY_NR_UE_DB_H_ -#define SRSENB_PHY_NR_UE_DB_H_ - -#include -#include -#include -#include -#include -#include - -namespace srsenb { -namespace nr { - -class phy_nr_state -{ -private: - /** - * UE object stored in the PHY common database - */ - struct common_ue { - srsran::phy_cfg_nr_t cfg; - }; - - /** - * UE database indexed by RNTI - */ - std::map ue_db; - - /** - * Concurrency protection mutex, allowed modifications from const methods. - */ - mutable std::mutex mutex; - - /** - * Stack interface - */ - stack_interface_phy_nr& stack; - - /** - * Cell list - */ - const phy_cell_cfg_list_nr_t& cell_cfg_list; - - /** - * Internal RNTI addition, it is not thread safe protected - * - * @param rnti identifier of the UE - * @return SRSRAN_SUCCESS if the RNTI is not duplicated and is added successfully, SRSRAN_ERROR code if it exists - */ - inline int _add_rnti(uint16_t rnti); - - /** - * Checks if a given RNTI exists in the database - * @param rnti provides UE identifier - * @return SRSRAN_SUCCESS if the indicated RNTI exists, otherwise it returns SRSRAN_ERROR - */ - inline int _assert_rnti(uint16_t rnti) const; - - /** - * Internal eNb general configuration getter, returns default configuration if the UE does not exist in the given cell - * - * @param rnti provides UE identifier - * @param[out] phy_cfg The PHY configuration of the indicated UE for the indicated eNb carrier/call index. - * @return SRSRAN_SUCCESS if provided context is correct, SRSRAN_ERROR code otherwise - */ - inline int _get_rnti_config(uint16_t rnti, srsran::phy_cfg_nr_t& phy_cfg) const; - -public: - phy_nr_state(const phy_cell_cfg_list_nr_t& cell_cfg_list_, stack_interface_phy_nr& stack_); - - void addmod_rnti(uint16_t rnti, const srsran::phy_cfg_nr_t& phy_cfg); - - /** - * Removes a whole UE entry from the UE database - * - * @param rnti identifier of the UE - * @return SRSRAN_SUCCESS if provided RNTI exists, SRSRAN_ERROR code otherwise - */ - int rem_rnti(uint16_t rnti); - - int get_config(uint16_t rnti, srsran::phy_cfg_nr_t& phy_cfg); - - const phy_cell_cfg_list_nr_t& get_carrier_list() const { return cell_cfg_list; } - - stack_interface_phy_nr& get_stack() { return stack; } -}; - -} // namespace nr -} // namespace srsenb - -#endif // SRSENB_PHY_NR_UE_DB_H_ diff --git a/srsenb/hdr/phy/nr/sf_worker.h b/srsenb/hdr/phy/nr/sf_worker.h deleted file mode 100644 index 20189e8d9..000000000 --- a/srsenb/hdr/phy/nr/sf_worker.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 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. - * - */ - -#ifndef SRSENB_NR_PHCH_WORKER_H -#define SRSENB_NR_PHCH_WORKER_H - -#include "cc_worker.h" -#include "srsran/common/thread_pool.h" -#include "srsran/interfaces/phy_common_interface.h" -#include "srsran/srslog/srslog.h" - -namespace srsenb { -namespace nr { - -/** - * The sf_worker class handles the PHY processing, UL and DL procedures associated with 1 subframe. - * It contains multiple cc_worker objects, one for each component carrier which may be executed in - * one or multiple threads. - * - * A sf_worker object is executed by a thread within the thread_pool. - */ - -class sf_worker final : public srsran::thread_pool::worker -{ -public: - sf_worker(srsran::phy_common_interface& common_, phy_nr_state& phy_state_, srslog::basic_logger& logger); - ~sf_worker(); - - /* Functions used by main PHY thread */ - cf_t* get_buffer_rx(uint32_t cc_idx, uint32_t antenna_idx); - cf_t* get_buffer_tx(uint32_t cc_idx, uint32_t antenna_idx); - uint32_t get_buffer_len(); - void set_time(const uint32_t& tti, const srsran::rf_timestamp_t& timestamp); - -private: - /* Inherited from thread_pool::worker. Function called every subframe to run the DL/UL processing */ - void work_imp() override; - - std::vector > cc_workers; - - srsran::phy_common_interface& common; - phy_nr_state& phy_state; - srslog::basic_logger& logger; - srsran_slot_cfg_t dl_slot_cfg = {}; - srsran_slot_cfg_t ul_slot_cfg = {}; - srsran::rf_timestamp_t tx_time = {}; - uint32_t sf_len = 0; - - // Temporal attributes - srsran_softbuffer_tx_t softbuffer_tx = {}; - std::vector data; -}; - -} // namespace nr -} // namespace srsenb - -#endif // SRSENB_NR_PHCH_WORKER_H diff --git a/srsenb/hdr/phy/nr/slot_worker.h b/srsenb/hdr/phy/nr/slot_worker.h new file mode 100644 index 000000000..7756b2116 --- /dev/null +++ b/srsenb/hdr/phy/nr/slot_worker.h @@ -0,0 +1,90 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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. + * + */ + +#ifndef SRSENB_NR_SLOT_WORKER_H +#define SRSENB_NR_SLOT_WORKER_H + +#include "srsran/common/thread_pool.h" +#include "srsran/interfaces/gnb_interfaces.h" +#include "srsran/interfaces/phy_common_interface.h" +#include "srsran/srslog/srslog.h" +#include "srsran/srsran.h" + +namespace srsenb { +namespace nr { + +/** + * The slot_worker class handles the PHY processing, UL and DL procedures associated with 1 slot. + * + * A slot_worker object is executed by a thread within the thread_pool. + */ + +class slot_worker final : public srsran::thread_pool::worker +{ +public: + struct args_t { + uint32_t cell_index = 0; + srsran_carrier_nr_t carrier = {}; + uint32_t nof_tx_ports = 1; + uint32_t nof_rx_ports = 1; + uint32_t pusch_max_nof_iter = 10; + srsran_pdcch_cfg_nr_t pdcch_cfg = {}; ///< PDCCH configuration + }; + + slot_worker(srsran::phy_common_interface& common_, stack_interface_phy_nr& stack_, srslog::basic_logger& logger); + ~slot_worker(); + + bool init(const args_t& args); + + /* Functions used by main PHY thread */ + cf_t* get_buffer_rx(uint32_t antenna_idx); + cf_t* get_buffer_tx(uint32_t antenna_idx); + uint32_t get_buffer_len(); + void set_time(const uint32_t& tti, const srsran::rf_timestamp_t& timestamp); + +private: + /** + * @brief Inherited from thread_pool::worker. Function called every slot to run the DL/UL processing + */ + void work_imp() override; + + /** + * @brief Retrieves the scheduling results for the UL processing and performs reception + * @return True if no error occurs, false otherwise + */ + bool work_ul(); + + /** + * @brief Retrieves the scheduling results for the DL processing and performs transmission + * @return True if no error occurs, false otherwise + */ + bool work_dl(); + + srsran::phy_common_interface& common; + stack_interface_phy_nr& stack; + srslog::basic_logger& logger; + + uint32_t sf_len = 0; + uint32_t cell_index = 0; + srsran_slot_cfg_t dl_slot_cfg = {}; + srsran_slot_cfg_t ul_slot_cfg = {}; + srsran_pdcch_cfg_nr_t pdcch_cfg = {}; + srsran::rf_timestamp_t tx_time = {}; + srsran_enb_dl_nr_t gnb_dl = {}; + std::vector tx_buffer; ///< Baseband transmit buffers + std::vector rx_buffer; ///< Baseband receive buffers +}; + +} // namespace nr +} // namespace srsenb + +#endif // SRSENB_NR_PHCH_WORKER_H diff --git a/srsenb/hdr/phy/nr/worker_pool.h b/srsenb/hdr/phy/nr/worker_pool.h index d909e4be1..5d648efbf 100644 --- a/srsenb/hdr/phy/nr/worker_pool.h +++ b/srsenb/hdr/phy/nr/worker_pool.h @@ -13,40 +13,42 @@ #ifndef SRSENB_NR_WORKER_POOL_H #define SRSENB_NR_WORKER_POOL_H -#include "phy_nr_state.h" -#include "sf_worker.h" +#include "slot_worker.h" #include "srsenb/hdr/phy/phy_interfaces.h" #include "srsran/common/thread_pool.h" +#include "srsran/interfaces/gnb_interfaces.h" namespace srsenb { namespace nr { class worker_pool { - srsran::thread_pool pool; - std::vector > workers; - phy_nr_state phy_state; + srsran::phy_common_interface& common; + stack_interface_phy_nr& stack; + srslog::sink& log_sink; + srsran::thread_pool pool; + std::vector > workers; public: struct args_t { - uint32_t nof_workers = 3; - uint32_t prio = 52; - std::string log_level = "info"; - uint32_t log_hex_limit = 64; - std::string log_id_preamble = ""; + uint32_t nof_phy_threads = 3; + uint32_t prio = 52; + std::string log_level = "info"; + uint32_t log_hex_limit = 64; + std::string log_id_preamble = ""; + uint32_t pusch_max_nof_iter = 10; }; - sf_worker* operator[](std::size_t pos) { return workers.at(pos).get(); } + slot_worker* operator[](std::size_t pos) { return workers.at(pos).get(); } - worker_pool(const phy_cell_cfg_list_nr_t& cell_list, - const args_t& args, - srsran::phy_common_interface& common, + worker_pool(srsran::phy_common_interface& common, stack_interface_phy_nr& stack, - srslog::sink& log_sink); - sf_worker* wait_worker(uint32_t tti); - sf_worker* wait_worker_id(uint32_t id); - void start_worker(sf_worker* w); - void stop(); - bool addmod_rnti(uint16_t rnti, const srsran::phy_cfg_nr_t& phy_cfg); + srslog::sink& log_sink, + uint32_t max_workers); + bool init(const args_t& args, const phy_cell_cfg_list_nr_t& cell_list); + slot_worker* wait_worker(uint32_t tti); + slot_worker* wait_worker_id(uint32_t id); + void start_worker(slot_worker* w); + void stop(); }; } // namespace nr diff --git a/srsenb/hdr/phy/phy_interfaces.h b/srsenb/hdr/phy/phy_interfaces.h index b1e8d59cf..35dee14c2 100644 --- a/srsenb/hdr/phy/phy_interfaces.h +++ b/srsenb/hdr/phy/phy_interfaces.h @@ -16,7 +16,7 @@ #include "srsran/asn1/rrc/rr_common.h" #include "srsran/common/interfaces_common.h" #include "srsran/phy/channel/channel.h" -#include "srsran/phy/common/phy_common_nr.h" +#include "srsran/srsran.h" #include #include @@ -34,14 +34,15 @@ struct phy_cell_cfg_t { }; struct phy_cell_cfg_nr_t { - srsran_carrier_nr_t carrier; - uint32_t rf_port; - uint32_t cell_id; - double dl_freq_hz; - double ul_freq_hz; - uint32_t root_seq_idx; - uint32_t num_ra_preambles; - float gain_db; + srsran_carrier_nr_t carrier; + uint32_t rf_port; + uint32_t cell_id; + double dl_freq_hz; + double ul_freq_hz; + uint32_t root_seq_idx; + uint32_t num_ra_preambles; + float gain_db; + srsran_pdcch_cfg_nr_t pdcch = {}; ///< Common CORESET and Search Space configuration }; typedef std::vector phy_cell_cfg_list_t; @@ -51,18 +52,18 @@ struct phy_args_t { std::string type; srsran::phy_log_args_t log; - float max_prach_offset_us = 10; - int pusch_max_its = 10; - bool pusch_8bit_decoder = false; - float tx_amplitude = 1.0f; - uint32_t nof_phy_threads = 1; - std::string equalizer_mode = "mmse"; - float estimator_fil_w = 1.0f; - bool pusch_meas_epre = true; - bool pusch_meas_evm = false; - bool pusch_meas_ta = true; - bool pucch_meas_ta = true; - uint32_t nof_prach_threads = 1; + float max_prach_offset_us = 10; + int pusch_max_its = 10; + bool pusch_8bit_decoder = false; + float tx_amplitude = 1.0f; + uint32_t nof_phy_threads = 1; + std::string equalizer_mode = "mmse"; + float estimator_fil_w = 1.0f; + bool pusch_meas_epre = true; + bool pusch_meas_evm = false; + bool pusch_meas_ta = true; + bool pucch_meas_ta = true; + uint32_t nof_prach_threads = 1; bool extended_cp = false; srsran::channel::args_t dl_channel_args; srsran::channel::args_t ul_channel_args; diff --git a/srsenb/hdr/stack/gnb_stack_nr.h b/srsenb/hdr/stack/gnb_stack_nr.h index 90b108807..549791e32 100644 --- a/srsenb/hdr/stack/gnb_stack_nr.h +++ b/srsenb/hdr/stack/gnb_stack_nr.h @@ -55,12 +55,12 @@ public: bool get_metrics(srsenb::stack_metrics_t* metrics) final; // GW srsue stack_interface_gw dummy interface - bool is_registered() { return true; }; - bool start_service_request() { return true; }; + bool is_registered() override { return true; }; + bool start_service_request() override { return true; }; // PHY->MAC interface - int sf_indication(const uint32_t tti); - int rx_data_indication(rx_data_ind_t& grant); + int sf_indication(const uint32_t tti) override; + int rx_data_indication(rx_data_ind_t& grant) override; // Temporary GW interface void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu); @@ -71,9 +71,11 @@ public: // MAC interface to trigger processing of received PDUs void process_pdus() final; - void toggle_padding() { srsran::console("padding not available for NR\n"); } - int get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res) override; - int get_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res) override; + void toggle_padding() override { srsran::console("padding not available for NR\n"); } + + int slot_indication(const srsran_slot_cfg_t& slot_cfg) override; + int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) override; + int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override; private: void run_thread() final; diff --git a/srsenb/hdr/stack/mac/mac_nr.h b/srsenb/hdr/stack/mac/mac_nr.h index 274efb74b..7290dfcbd 100644 --- a/srsenb/hdr/stack/mac/mac_nr.h +++ b/srsenb/hdr/stack/mac/mac_nr.h @@ -65,8 +65,9 @@ public: int rx_data_indication(stack_interface_phy_nr::rx_data_ind_t& grant); void process_pdus(); - int get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res) override; - int get_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res) override; + int slot_indication(const srsran_slot_cfg_t& slot_cfg) override; + int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) override; + int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override; private: void get_dl_config(const uint32_t tti, diff --git a/srsenb/src/phy/CMakeLists.txt b/srsenb/src/phy/CMakeLists.txt index 60061af9f..66c4db7b2 100644 --- a/srsenb/src/phy/CMakeLists.txt +++ b/srsenb/src/phy/CMakeLists.txt @@ -10,10 +10,8 @@ set(SOURCES lte/cc_worker.cc lte/sf_worker.cc lte/worker_pool.cc - nr/cc_worker.cc - nr/sf_worker.cc + nr/slot_worker.cc nr/worker_pool.cc - nr/phy_nr_state.cc phy.cc phy_common.cc phy_ue_db.cc diff --git a/srsenb/src/phy/nr/cc_worker.cc b/srsenb/src/phy/nr/cc_worker.cc deleted file mode 100644 index cadb736fb..000000000 --- a/srsenb/src/phy/nr/cc_worker.cc +++ /dev/null @@ -1,186 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 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 "srsenb/hdr/phy/nr/cc_worker.h" -#include "srsran/srsran.h" - -namespace srsenb { -namespace nr { -cc_worker::cc_worker(const args_t& args, srslog::basic_logger& log, phy_nr_state& phy_state_) : - cc_idx(args.cc_idx), - phy_state(phy_state_), - logger(log), - nof_tx_antennas(args.dl.nof_tx_antennas) -{ - cf_t* buffer_c[SRSRAN_MAX_PORTS] = {}; - - // Allocate buffers - buffer_sz = SRSRAN_SF_LEN_PRB(args.dl.nof_max_prb); - for (uint32_t i = 0; i < args.dl.nof_tx_antennas; i++) { - tx_buffer[i] = srsran_vec_cf_malloc(buffer_sz); - rx_buffer[i] = srsran_vec_cf_malloc(buffer_sz); - buffer_c[i] = tx_buffer[i]; - } - - if (srsran_enb_dl_nr_init(&gnb_dl, buffer_c, &args.dl)) { - ERROR("Error initiating GNB DL NR"); - return; - } - - if (srsran_enb_dl_nr_set_carrier(&gnb_dl, &args.carrier) < SRSRAN_SUCCESS) { - ERROR("Error setting carrier"); - } -} - -cc_worker::~cc_worker() -{ - srsran_enb_dl_nr_free(&gnb_dl); - for (cf_t* p : rx_buffer) { - if (p != nullptr) { - free(p); - } - } - for (cf_t* p : tx_buffer) { - if (p != nullptr) { - free(p); - } - } -} - -void cc_worker::set_tti(uint32_t tti) -{ - ul_slot_cfg.idx = tti; - dl_slot_cfg.idx = TTI_ADD(tti, FDD_HARQ_DELAY_UL_MS); -} - -cf_t* cc_worker::get_tx_buffer(uint32_t antenna_idx) -{ - if (antenna_idx >= nof_tx_antennas) { - return nullptr; - } - - return tx_buffer.at(antenna_idx); -} - -cf_t* cc_worker::get_rx_buffer(uint32_t antenna_idx) -{ - if (antenna_idx >= nof_tx_antennas) { - return nullptr; - } - - return rx_buffer.at(antenna_idx); -} - -uint32_t cc_worker::get_buffer_len() -{ - return tx_buffer.size(); -} - -int cc_worker::encode_pdcch_dl(stack_interface_phy_nr::dl_sched_grant_t* grants, uint32_t nof_grants) -{ - for (uint32_t i = 0; i < nof_grants; i++) { - uint16_t rnti = grants->dci.ctx.rnti; - - // Get PHY config for UE - srsran::phy_cfg_nr_t cfg = {}; - if (phy_state.get_config(rnti, cfg) < SRSRAN_SUCCESS) { - logger.error("Invalid RNTI 0x%x", rnti); - return SRSRAN_ERROR; - } - - srsran_dci_cfg_nr_t dci_cfg = cfg.get_dci_cfg(); - if (srsran_enb_dl_nr_set_pdcch_config(&gnb_dl, &cfg.pdcch, &dci_cfg) < SRSRAN_SUCCESS) { - logger.error("Invalid CORESET setting"); - return SRSRAN_ERROR; - } - - // Put actual DCI - if (srsran_enb_dl_nr_pdcch_put(&gnb_dl, &dl_slot_cfg, &grants[i].dci) < SRSRAN_SUCCESS) { - ERROR("Error putting PDCCH"); - return SRSRAN_ERROR; - } - - if (logger.info.enabled()) { - std::array str = {}; - srsran_dci_dl_nr_to_str(&gnb_dl.dci, &grants[i].dci, str.data(), (uint32_t)str.size()); - if (logger.info.enabled()) { - logger.info("PDCCH: cc=%d %s tti_tx=%d", cc_idx, str.data(), dl_slot_cfg.idx); - } - } - } - - return SRSRAN_SUCCESS; -} - -int cc_worker::encode_pdsch(stack_interface_phy_nr::dl_sched_grant_t* grants, uint32_t nof_grants) -{ - for (uint32_t i = 0; i < nof_grants; i++) { - // Get PHY config for UE - srsran::phy_cfg_nr_t cfg = {}; - if (phy_state.get_config(grants[i].dci.ctx.rnti, cfg) < SRSRAN_SUCCESS) { - return SRSRAN_ERROR; - } - - // Compute DL grant - srsran_sch_cfg_nr_t pdsch_cfg = {}; - if (srsran_ra_dl_dci_to_grant_nr( - &gnb_dl.carrier, &dl_slot_cfg, &cfg.pdsch, &grants[i].dci, &pdsch_cfg, &pdsch_cfg.grant) < SRSRAN_SUCCESS) { - ERROR("Computing DL grant"); - return SRSRAN_ERROR; - } - - // Set soft buffer - for (uint32_t j = 0; j < SRSRAN_MAX_CODEWORDS; j++) { - pdsch_cfg.grant.tb[j].softbuffer.tx = grants[i].softbuffer_tx[j]; - } - - if (srsran_enb_dl_nr_pdsch_put(&gnb_dl, &dl_slot_cfg, &pdsch_cfg, grants[i].data) < SRSRAN_SUCCESS) { - ERROR("Error putting PDSCH"); - return SRSRAN_ERROR; - } - - // Logging - if (logger.info.enabled()) { - char str[512]; - srsran_enb_dl_nr_pdsch_info(&gnb_dl, &pdsch_cfg, str, sizeof(str)); - logger.info("PDSCH: cc=%d, %s tti_tx=%d", cc_idx, str, dl_slot_cfg.idx); - } - } - - return SRSRAN_SUCCESS; -} - -bool cc_worker::work_ul() -{ - return true; -} - -bool cc_worker::work_dl(stack_interface_phy_nr::dl_sched_t& dl_grants, stack_interface_phy_nr::ul_sched_t& ul_grants) -{ - // Reset resource grid - if (srsran_enb_dl_nr_base_zero(&gnb_dl) < SRSRAN_SUCCESS) { - ERROR("Error setting base to zero"); - return SRSRAN_ERROR; - } - - // Put DL grants to resource grid. PDSCH data will be encoded as well. - encode_pdcch_dl(dl_grants.pdsch, dl_grants.nof_grants); - encode_pdsch(dl_grants.pdsch, dl_grants.nof_grants); - - // Generate signal - srsran_enb_dl_nr_gen_signal(&gnb_dl); - - return true; -} - -} // namespace nr -} // namespace srsenb diff --git a/srsenb/src/phy/nr/phy_nr_state.cc b/srsenb/src/phy/nr/phy_nr_state.cc deleted file mode 100644 index 80c271b28..000000000 --- a/srsenb/src/phy/nr/phy_nr_state.cc +++ /dev/null @@ -1,85 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 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 "srsenb/hdr/phy/nr/phy_nr_state.h" - -namespace srsenb { -namespace nr { - -int phy_nr_state::_add_rnti(uint16_t rnti) -{ - if (ue_db.count(rnti) > 0) { - return SRSRAN_ERROR; - } - - // Access UE to create - // Set defaults - ue_db[rnti] = {}; - - return SRSRAN_SUCCESS; -} - -int phy_nr_state::_assert_rnti(uint16_t rnti) const -{ - return ue_db.count(rnti) > 0 ? SRSRAN_SUCCESS : SRSRAN_ERROR; -} - -int phy_nr_state::_get_rnti_config(uint16_t rnti, srsran::phy_cfg_nr_t& phy_cfg) const -{ - if (_assert_rnti(rnti) < SRSRAN_SUCCESS) { - return SRSRAN_ERROR; - } - - phy_cfg = ue_db.at(rnti).cfg; - - return SRSRAN_SUCCESS; -} - -phy_nr_state::phy_nr_state(const phy_cell_cfg_list_nr_t& cell_cfg_list_, stack_interface_phy_nr& stack_) : - cell_cfg_list(cell_cfg_list_), - stack(stack_) -{} - -void phy_nr_state::addmod_rnti(uint16_t rnti, const srsran::phy_cfg_nr_t& phy_cfg) -{ - std::lock_guard lock(mutex); - - // Create UE if it does not exist - if (_assert_rnti(rnti) < SRSRAN_SUCCESS) { - _add_rnti(rnti); - } - - // Set UE configuration - ue_db[rnti].cfg = phy_cfg; -} -int phy_nr_state::rem_rnti(uint16_t rnti) -{ - std::lock_guard lock(mutex); - - if (_assert_rnti(rnti) < SRSRAN_SUCCESS) { - return SRSRAN_ERROR; - } - - ue_db.erase(rnti); - - return SRSRAN_SUCCESS; -} - -int phy_nr_state::get_config(uint16_t rnti, srsran::phy_cfg_nr_t& phy_cfg) -{ - std::lock_guard lock(mutex); - - return _get_rnti_config(rnti, phy_cfg); -} - -} // namespace nr -} // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/phy/nr/sf_worker.cc b/srsenb/src/phy/nr/sf_worker.cc deleted file mode 100644 index 662b77ca9..000000000 --- a/srsenb/src/phy/nr/sf_worker.cc +++ /dev/null @@ -1,125 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 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 "srsenb/hdr/phy/nr/sf_worker.h" - -namespace srsenb { -namespace nr { -sf_worker::sf_worker(srsran::phy_common_interface& common_, phy_nr_state& phy_state_, srslog::basic_logger& logger_) : - common(common_), - phy_state(phy_state_), - logger(logger_) -{ - // Set subframe length - sf_len = SRSRAN_SF_LEN_PRB_NR(phy_state.get_carrier_list()[0].carrier.nof_prb); - - const phy_cell_cfg_list_nr_t& carrier_list = phy_state.get_carrier_list(); - for (uint32_t i = 0; i < (uint32_t)carrier_list.size(); i++) { - cc_worker::args_t cc_args = {}; - cc_args.cc_idx = i; - cc_args.carrier = carrier_list[i].carrier; - cc_args.dl.nof_tx_antennas = 1; - cc_args.dl.nof_max_prb = cc_args.carrier.nof_prb; - cc_args.dl.pdsch.max_prb = cc_args.carrier.nof_prb; - cc_args.dl.pdsch.max_layers = 1; - - cc_worker* w = new cc_worker(cc_args, logger_, phy_state); - cc_workers.push_back(std::unique_ptr(w)); - } - - if (srsran_softbuffer_tx_init_guru(&softbuffer_tx, SRSRAN_SCH_NR_MAX_NOF_CB_LDPC, SRSRAN_LDPC_MAX_LEN_ENCODED_CB) < - SRSRAN_SUCCESS) { - ERROR("Error init soft-buffer"); - return; - } - data.resize(SRSRAN_SCH_NR_MAX_NOF_CB_LDPC * SRSRAN_LDPC_MAX_LEN_ENCODED_CB / 8); - srsran_vec_u8_zero(data.data(), SRSRAN_SCH_NR_MAX_NOF_CB_LDPC * SRSRAN_LDPC_MAX_LEN_ENCODED_CB / 8); - snprintf((char*)data.data(), SRSRAN_SCH_NR_MAX_NOF_CB_LDPC * SRSRAN_LDPC_MAX_LEN_ENCODED_CB / 8, "hello world!"); -} - -sf_worker::~sf_worker() -{ - srsran_softbuffer_tx_free(&softbuffer_tx); -} - -cf_t* sf_worker::get_buffer_rx(uint32_t cc_idx, uint32_t antenna_idx) -{ - if (cc_idx >= cc_workers.size()) { - return nullptr; - } - - return cc_workers.at(cc_idx)->get_rx_buffer(antenna_idx); -} - -cf_t* sf_worker::get_buffer_tx(uint32_t cc_idx, uint32_t antenna_idx) -{ - if (cc_idx >= cc_workers.size()) { - return nullptr; - } - - return cc_workers.at(cc_idx)->get_tx_buffer(antenna_idx); -} - -uint32_t sf_worker::get_buffer_len() -{ - return cc_workers.at(0)->get_buffer_len(); -} - -void sf_worker::set_time(const uint32_t& tti, const srsran::rf_timestamp_t& timestamp) -{ - logger.set_context(tti); - for (auto& w : cc_workers) { - w->set_tti(tti); - } - ul_slot_cfg.idx = tti; - dl_slot_cfg.idx = TTI_ADD(tti, FDD_HARQ_DELAY_UL_MS); - tx_time.copy(timestamp); -} - -void sf_worker::work_imp() -{ - // Get Transmission buffers - srsran::rf_buffer_t tx_buffer = {}; - for (uint32_t cc = 0; cc < (uint32_t)phy_state.get_carrier_list().size(); cc++) { - tx_buffer.set(cc, 0, 1, cc_workers[cc]->get_tx_buffer(0)); - } - - // Set number of samples - tx_buffer.set_nof_samples(sf_len); - - // Get UL Scheduling - mac_interface_phy_nr::ul_sched_list_t ul_sched_list = {}; - ul_sched_list.resize(1); - if (phy_state.get_stack().get_ul_sched(ul_slot_cfg.idx, ul_sched_list) < SRSRAN_SUCCESS) { - logger.error("DL Scheduling error"); - common.worker_end(this, true, tx_buffer, tx_time, true); - return; - } - - // Get DL scheduling - mac_interface_phy_nr::dl_sched_list_t dl_sched_list = {}; - dl_sched_list.resize(1); - if (phy_state.get_stack().get_dl_sched(ul_slot_cfg.idx, dl_sched_list) < SRSRAN_SUCCESS) { - logger.error("DL Scheduling error"); - common.worker_end(this, true, tx_buffer, tx_time, true); - return; - } - - for (auto& w : cc_workers) { - w->work_dl(dl_sched_list[0], ul_sched_list[0]); - } - - common.worker_end(this, true, tx_buffer, tx_time, true); -} - -} // namespace nr -} // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc new file mode 100644 index 000000000..c47a4572e --- /dev/null +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -0,0 +1,262 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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 "srsenb/hdr/phy/nr/slot_worker.h" +#include + +namespace srsenb { +namespace nr { +slot_worker::slot_worker(srsran::phy_common_interface& common_, + stack_interface_phy_nr& stack_, + srslog::basic_logger& logger_) : + common(common_), stack(stack_), logger(logger_) +{ + // Do nothing +} + +bool slot_worker::init(const args_t& args) +{ + // Calculate subframe length + sf_len = SRSRAN_SF_LEN_PRB_NR(args.carrier.nof_prb); + + // Copy common configurations + cell_index = args.cell_index; + pdcch_cfg = args.pdcch_cfg; + + // Allocate Tx buffers + tx_buffer.resize(args.nof_tx_ports); + for (uint32_t i = 0; i < args.nof_tx_ports; i++) { + tx_buffer[i] = srsran_vec_cf_malloc(sf_len); + if (tx_buffer[i] == nullptr) { + logger.error("Error allocating Tx buffer"); + return false; + } + } + + // Allocate Tx buffers + rx_buffer.resize(args.nof_rx_ports); + for (uint32_t i = 0; i < args.nof_rx_ports; i++) { + rx_buffer[i] = srsran_vec_cf_malloc(sf_len); + if (rx_buffer[i] == nullptr) { + logger.error("Error allocating Rx buffer"); + return false; + } + } + + // Prepare DL arguments + srsran_enb_dl_nr_args_t dl_args = {}; + dl_args.pdsch.measure_time = true; + dl_args.pdsch.max_layers = args.carrier.max_mimo_layers; + dl_args.pdsch.max_prb = args.carrier.nof_prb; + dl_args.nof_tx_antennas = args.nof_tx_ports; + dl_args.nof_max_prb = args.carrier.nof_prb; + + // Initialise DL + if (srsran_enb_dl_nr_init(&gnb_dl, tx_buffer.data(), &dl_args) < SRSRAN_SUCCESS) { + logger.error("Error gNb PHY init"); + return false; + } + + // Set gNb carrier + if (srsran_enb_dl_nr_set_carrier(&gnb_dl, &args.carrier) < SRSRAN_SUCCESS) { + logger.error("Error setting carrier"); + return false; + } + + return true; +} + +slot_worker::~slot_worker() +{ + for (auto& b : tx_buffer) { + if (b) { + free(b); + b = nullptr; + } + } + for (auto& b : rx_buffer) { + if (b) { + free(b); + b = nullptr; + } + } + srsran_enb_dl_nr_free(&gnb_dl); +} + +cf_t* slot_worker::get_buffer_rx(uint32_t antenna_idx) +{ + if (antenna_idx >= (uint32_t)rx_buffer.size()) { + return nullptr; + } + + return rx_buffer[antenna_idx]; +} + +cf_t* slot_worker::get_buffer_tx(uint32_t antenna_idx) +{ + if (antenna_idx >= (uint32_t)tx_buffer.size()) { + return nullptr; + } + + return tx_buffer[antenna_idx]; +} + +uint32_t slot_worker::get_buffer_len() +{ + return sf_len; +} + +void slot_worker::set_time(const uint32_t& tti, const srsran::rf_timestamp_t& timestamp) +{ + logger.set_context(tti); + ul_slot_cfg.idx = tti; + dl_slot_cfg.idx = TTI_ADD(tti, FDD_HARQ_DELAY_UL_MS); + tx_time.copy(timestamp); +} + +bool slot_worker::work_ul() +{ + stack_interface_phy_nr::ul_sched_t ul_sched = {}; + if (stack.get_ul_sched(ul_slot_cfg, ul_sched) < SRSRAN_SUCCESS) { + logger.error("Error retrieving UL scheduling"); + return false; + } + + // Decode PUCCH + for (uint32_t i = 0; i < ul_sched.uci_count; i++) { + const stack_interface_phy_nr::uci_t& uci = ul_sched.uci[i]; + // ... + } + + // Decode PUSCH + for (uint32_t i = 0; i < ul_sched.pusch_count; i++) { + const stack_interface_phy_nr::pusch_t& pusch = ul_sched.pusch[i]; + // ... + } + + return true; +} + +bool slot_worker::work_dl() +{ + stack_interface_phy_nr::dl_sched_t dl_sched = {}; + if (stack.get_dl_sched(ul_slot_cfg, dl_sched) < SRSRAN_SUCCESS) { + logger.error("Error retrieving DL scheduling"); + return false; + } + + // Encode PDCCH for DL transmissions + for (uint32_t i = 0; i < dl_sched.pdcch_dl_count; i++) { + // Select PDCCH from scheduler result + const stack_interface_phy_nr::pdcch_dl_t& pdcch = dl_sched.pdcch_dl[i]; + + // Set PDCCH configuration, including DCI dedicated + if (srsran_enb_dl_nr_set_pdcch_config(&gnb_dl, &pdcch_cfg, &pdcch.dci_cfg) < SRSRAN_SUCCESS) { + logger.error("PDCCH: Error setting DL configuration"); + return false; + } + + // Put PDCCH message + if (srsran_enb_dl_nr_pdcch_put_dl(&gnb_dl, &dl_slot_cfg, &pdcch.dci) < SRSRAN_SUCCESS) { + logger.error("PDCCH: Error putting DL message"); + return false; + } + + // Log PDCCH information + if (logger.info.enabled()) { + std::array str = {}; + srsran_enb_dl_nr_pdcch_dl_info(&gnb_dl, &pdcch.dci, str.data(), (uint32_t)str.size()); + logger.info("PDCCH: cc=%d %s tti_tx=%d", cell_index, str.data(), dl_slot_cfg.idx); + } + } + + // Encode PDCCH for UL transmissions + for (uint32_t i = 0; i < dl_sched.pdcch_ul_count; i++) { + // Select PDCCH from scheduler result + const stack_interface_phy_nr::pdcch_ul_t& pdcch = dl_sched.pdcch_ul[i]; + + // Set PDCCH configuration, including DCI dedicated + if (srsran_enb_dl_nr_set_pdcch_config(&gnb_dl, &pdcch_cfg, &pdcch.dci_cfg) < SRSRAN_SUCCESS) { + logger.error("PDCCH: Error setting DL configuration"); + return false; + } + + // Put PDCCH message + if (srsran_enb_dl_nr_pdcch_put_ul(&gnb_dl, &dl_slot_cfg, &pdcch.dci) < SRSRAN_SUCCESS) { + logger.error("PDCCH: Error putting DL message"); + return false; + } + + // Log PDCCH information + if (logger.info.enabled()) { + std::array str = {}; + srsran_enb_dl_nr_pdcch_ul_info(&gnb_dl, &pdcch.dci, str.data(), (uint32_t)str.size()); + logger.info("PDCCH: cc=%d %s tti_tx=%d", cell_index, str.data(), dl_slot_cfg.idx); + } + } + + // Encode PDSCH + for (uint32_t i = 0; i < dl_sched.pdsch_count; i++) { + // Select PDSCH from scheduler result + stack_interface_phy_nr::pdsch_t& pdsch = dl_sched.pdsch[i]; + + // Put PDSCH message + if (srsran_enb_dl_nr_pdsch_put(&gnb_dl, &dl_slot_cfg, &pdsch.sch, pdsch.data.data()) < SRSRAN_SUCCESS) { + logger.error("PDSCH: Error putting DL message"); + return false; + } + + // Log PDSCH information + if (logger.info.enabled()) { + std::array str = {}; + srsran_enb_dl_nr_pdsch_info(&gnb_dl, &pdsch.sch, str.data(), (uint32_t)str.size()); + logger.info("PDSCH: cc=%d %s tti_tx=%d", cell_index, str.data(), dl_slot_cfg.idx); + } + } + + // Generate baseband signal + srsran_enb_dl_nr_gen_signal(&gnb_dl); + + return true; +} + +void slot_worker::work_imp() +{ + // Inform Scheduler about new slot + stack.sf_indication(dl_slot_cfg.idx); + + // Get Transmission buffers + srsran::rf_buffer_t tx_rf_buffer = {}; + for (uint32_t i = 0; i < (uint32_t)tx_buffer.size(); i++) { + tx_rf_buffer.set(i, tx_buffer[i]); + } + + // Set number of samples + tx_rf_buffer.set_nof_samples(sf_len); + + // Process uplink + if (not work_ul()) { + common.worker_end(this, false, tx_rf_buffer, tx_time, true); + return; + } + + // Process downlink + if (not work_dl()) { + common.worker_end(this, false, tx_rf_buffer, tx_time, true); + return; + } + + common.worker_end(this, true, tx_rf_buffer, tx_time, true); +} + +} // namespace nr +} // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/phy/nr/worker_pool.cc b/srsenb/src/phy/nr/worker_pool.cc index dd8726334..b2a16999f 100644 --- a/srsenb/src/phy/nr/worker_pool.cc +++ b/srsenb/src/phy/nr/worker_pool.cc @@ -14,40 +14,58 @@ namespace srsenb { namespace nr { -worker_pool::worker_pool(const phy_cell_cfg_list_nr_t& cell_list, - const args_t& args, - srsran::phy_common_interface& common, - stack_interface_phy_nr& stack, - srslog::sink& log_sink) : - pool(args.nof_workers), - phy_state(cell_list, stack) +worker_pool::worker_pool(srsran::phy_common_interface& common_, + stack_interface_phy_nr& stack_, + srslog::sink& log_sink_, + uint32_t max_workers) : + pool(max_workers), common(common_), stack(stack_), log_sink(log_sink_) +{ + // Do nothing +} + +bool worker_pool::init(const args_t& args, const phy_cell_cfg_list_nr_t& cell_list) { // Add workers to workers pool and start threads srslog::basic_levels log_level = srslog::str_to_basic_level(args.log_level); - for (uint32_t i = 0; i < args.nof_workers; i++) { + for (uint32_t i = 0; i < args.nof_phy_threads; i++) { auto& log = srslog::fetch_basic_logger(fmt::format("{}PHY{}-NR", args.log_id_preamble, i), log_sink); log.set_level(log_level); log.set_hex_dump_max_size(args.log_hex_limit); - auto w = new sf_worker(common, phy_state, log); + auto w = new slot_worker(common, stack, log); pool.init_worker(i, w, args.prio); - workers.push_back(std::unique_ptr(w)); + workers.push_back(std::unique_ptr(w)); + + slot_worker::args_t w_args = {}; + uint32_t cell_index = 0; + w_args.cell_index = cell_index; + w_args.carrier = cell_list[cell_index].carrier; + w_args.nof_tx_ports = cell_list[cell_index].carrier.max_mimo_layers; + w_args.nof_rx_ports = cell_list[cell_index].carrier.max_mimo_layers; + w_args.pusch_max_nof_iter = args.pusch_max_nof_iter; + w_args.pdcch_cfg = cell_list[cell_index].pdcch; + + if (not w->init(w_args)) { + return false; + } } + + return true; } -void worker_pool::start_worker(sf_worker* w) +void worker_pool::start_worker(slot_worker* w) { pool.start_worker(w); } -sf_worker* worker_pool::wait_worker(uint32_t tti) +slot_worker* worker_pool::wait_worker(uint32_t tti) { - return (sf_worker*)pool.wait_worker(tti); + return (slot_worker*)pool.wait_worker(tti); } -sf_worker* worker_pool::wait_worker_id(uint32_t id) +slot_worker* worker_pool::wait_worker_id(uint32_t id) { - return (sf_worker*)pool.wait_worker_id(id); + return (slot_worker*)pool.wait_worker_id(id); } void worker_pool::stop() @@ -55,12 +73,5 @@ void worker_pool::stop() pool.stop(); } -bool worker_pool::addmod_rnti(uint16_t rnti, const srsran::phy_cfg_nr_t& phy_cfg) -{ - phy_state.addmod_rnti(rnti, phy_cfg); - - return true; -} - } // namespace nr } // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/phy/txrx.cc b/srsenb/src/phy/txrx.cc index 326114faa..c05633c2f 100644 --- a/srsenb/src/phy/txrx.cc +++ b/srsenb/src/phy/txrx.cc @@ -124,7 +124,7 @@ void txrx::run_thread() } } - nr::sf_worker* nr_worker = nullptr; + nr::slot_worker* nr_worker = nullptr; if (worker_com->get_nof_carriers_nr() > 0) { nr_worker = nr_workers->wait_worker(tti); if (nr_worker == nullptr) { @@ -144,12 +144,14 @@ void txrx::run_thread() buffer.set(rf_port, p, worker_com->get_nof_ports(0), lte_worker->get_buffer_rx(cc_lte, p)); } } - for (uint32_t cc_nr = 0; cc_nr < worker_com->get_nof_carriers_lte(); cc_nr++, cc++) { + for (uint32_t cc_nr = 0; cc_nr < worker_com->get_nof_carriers_nr(); cc_nr++, cc++) { uint32_t rf_port = worker_com->get_rf_port(cc); for (uint32_t p = 0; p < worker_com->get_nof_ports(cc); p++) { - // WARNING: The number of ports for all cells must be the same - buffer.set(rf_port, p, worker_com->get_nof_ports(0), nr_worker->get_buffer_rx(cc_nr, p)); + // WARNING: + // - The number of ports for all cells must be the same + // - Only one NR cell is currently supported + buffer.set(rf_port, p, worker_com->get_nof_ports(0), nr_worker->get_buffer_rx(p)); } } } diff --git a/srsenb/src/stack/gnb_stack_nr.cc b/srsenb/src/stack/gnb_stack_nr.cc index cf90c2393..cafe2e7c3 100644 --- a/srsenb/src/stack/gnb_stack_nr.cc +++ b/srsenb/src/stack/gnb_stack_nr.cc @@ -182,13 +182,17 @@ bool gnb_stack_nr::has_active_radio_bearer(uint32_t eps_bearer_id) { return (eps_bearer_id == args.coreless.drb_lcid); } -int gnb_stack_nr::get_dl_sched(uint32_t tti, mac_interface_phy_nr::dl_sched_list_t& dl_sched_res) +int gnb_stack_nr::slot_indication(const srsran_slot_cfg_t& slot_cfg) { - return m_mac->get_dl_sched(tti, dl_sched_res); + return m_mac->slot_indication(slot_cfg); } -int gnb_stack_nr::get_ul_sched(uint32_t tti, mac_interface_phy_nr::ul_sched_list_t& ul_sched_res) +int gnb_stack_nr::get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) { - return m_mac->get_ul_sched(tti, ul_sched_res); + return m_mac->get_dl_sched(slot_cfg, dl_sched); +} +int gnb_stack_nr::get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) +{ + return m_mac->get_ul_sched(slot_cfg, ul_sched); } } // namespace srsenb diff --git a/srsenb/src/stack/mac/nr/mac_nr.cc b/srsenb/src/stack/mac/nr/mac_nr.cc index 4ae51e0e3..66ba30c0f 100644 --- a/srsenb/src/stack/mac/nr/mac_nr.cc +++ b/srsenb/src/stack/mac/nr/mac_nr.cc @@ -267,11 +267,16 @@ int mac_nr::cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg) return SRSRAN_SUCCESS; } -int mac_nr::get_dl_sched(uint32_t tti, mac_interface_phy_nr::dl_sched_list_t& dl_sched_res) +int mac_nr::slot_indication(const srsran_slot_cfg_t& slot_cfg) { return 0; } -int mac_nr::get_ul_sched(uint32_t tti, mac_interface_phy_nr::ul_sched_list_t& ul_sched_res) + +int mac_nr::get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) +{ + return 0; +} +int mac_nr::get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) { return 0; } diff --git a/srsenb/test/phy/enb_phy_test.cc b/srsenb/test/phy/enb_phy_test.cc index f2014e637..016aee059 100644 --- a/srsenb/test/phy/enb_phy_test.cc +++ b/srsenb/test/phy/enb_phy_test.cc @@ -11,9 +11,9 @@ */ #include "srsran/common/threads.h" -#include "srsran/phy/common/phy_common.h" #include "srsran/phy/utils/random.h" #include "srsran/srslog/srslog.h" +#include "srsran/srsran.h" #include #include #include @@ -22,7 +22,6 @@ #include #include #include -#include static inline bool dl_ack_value(uint32_t ue_cc_idx, uint32_t tti) { diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h new file mode 100644 index 000000000..4536ac999 --- /dev/null +++ b/test/phy/dummy_gnb_stack.h @@ -0,0 +1,239 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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. + * + */ + +#ifndef SRSRAN_DUMMY_GNB_STACK_H +#define SRSRAN_DUMMY_GNB_STACK_H + +#include +#include +#include + +class gnb_dummy_stack : public srsenb::stack_interface_phy_nr +{ +private: + srslog::basic_logger& logger = srslog::fetch_basic_logger("GNB STK"); + const uint16_t rnti = 0x1234; + const uint32_t mcs = 1; + srsran::circular_array dci_dl_location; + srsran::circular_array dci_ul_location; + srsran::circular_array dl_data_to_ul_ack; + srsran_search_space_t ss = {}; + srsran_dci_format_nr_t dci_format_ul = SRSRAN_DCI_FORMAT_NR_COUNT; + srsran_dci_format_nr_t dci_format_dl = SRSRAN_DCI_FORMAT_NR_COUNT; + uint32_t dl_freq_res = 0; + uint32_t dl_time_res = 0; + srsran_random_t random_gen = nullptr; + srsran::phy_cfg_nr_t phy_cfg = {}; + bool valid = false; + + struct dummy_harq_proc { + static const uint32_t MAX_TB_SZ = SRSRAN_LDPC_MAX_LEN_CB * SRSRAN_SCH_NR_MAX_NOF_CB_LDPC; + std::vector data; + srsran_softbuffer_tx_t softbuffer = {}; + + dummy_harq_proc() + { + // Allocate data + data.resize(MAX_TB_SZ); + + // Initialise softbuffer + if (srsran_softbuffer_tx_init_guru(&softbuffer, SRSRAN_SCH_NR_MAX_NOF_CB_LDPC, SRSRAN_LDPC_MAX_LEN_ENCODED_CB) < + SRSRAN_SUCCESS) { + ERROR("Error Tx buffer"); + } + } + + ~dummy_harq_proc() { srsran_softbuffer_tx_free(&softbuffer); } + }; + srsran::circular_array tx_harq_proc; + +public: + struct args_t { + srsran::phy_cfg_nr_t phy_cfg; ///< Physical layer configuration + uint16_t rnti = 0x1234; ///< C-RNTI + uint32_t mcs = 10; ///< Modulation code scheme + uint32_t ss_id = 1; ///< Search Space identifier + uint32_t pdcch_aggregation_level = 0; ///< PDCCH aggregation level + uint32_t pdcch_dl_candidate_index = 0; ///< PDCCH DL DCI candidate index + uint32_t pdcch_ul_candidate_index = 0; ///< PDCCH UL DCI candidate index + uint32_t dl_start_rb = 0; ///< Start resource block + uint32_t dl_length_rb = 0l; ///< Number of resource blocks + uint32_t dl_time_res = 0; ///< PDSCH time resource + }; + + gnb_dummy_stack(args_t args) : mcs(args.mcs), rnti(args.rnti), dl_time_res(args.dl_time_res), phy_cfg(args.phy_cfg) + { + random_gen = srsran_random_init(0x1234); + + // Select search space + if (args.ss_id >= SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE) { + logger.error("Search Space Id (%d) is out-of-range (%d)", args.ss_id, SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE); + return; + } + if (not args.phy_cfg.pdcch.search_space_present[args.ss_id]) { + logger.error("Search Space Id (%d) is not present", args.ss_id); + return; + } + ss = args.phy_cfg.pdcch.search_space[args.ss_id]; + + // Select CORESET + if (ss.coreset_id >= SRSRAN_UE_DL_NR_MAX_NOF_CORESET) { + logger.error("CORESET Id (%d) is out-of-range (%d)", ss.coreset_id, SRSRAN_UE_DL_NR_MAX_NOF_CORESET); + return; + } + if (not args.phy_cfg.pdcch.coreset_present[ss.coreset_id]) { + logger.error("CORESET Id (%d) is not present", args.ss_id); + return; + } + const srsran_coreset_t& coreset = args.phy_cfg.pdcch.coreset[ss.coreset_id]; + + // Select DCI locations + for (uint32_t slot = 0; slot < SRSRAN_NOF_SF_X_FRAME; slot++) { + std::array ncce = {}; + int n = srsran_pdcch_nr_locations_coreset(&coreset, &ss, rnti, args.pdcch_aggregation_level, slot++, ncce.data()); + if (n < SRSRAN_SUCCESS) { + logger.error( + "Error generating locations for slot %d and aggregation level %d", slot, args.pdcch_aggregation_level); + return; + } + uint32_t nof_candidates = (uint32_t)n; + + // DCI DL + if (args.pdcch_dl_candidate_index >= nof_candidates or + args.pdcch_dl_candidate_index >= SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR) { + logger.error("Candidate index %d exceeds the number of candidates %d for aggregation level %d", + args.pdcch_dl_candidate_index, + n, + args.pdcch_aggregation_level); + return; + } + dci_dl_location[slot].L = args.pdcch_aggregation_level; + dci_dl_location[slot].ncce = ncce[args.pdcch_dl_candidate_index]; + + // DCI UL + if (args.pdcch_ul_candidate_index >= nof_candidates or + args.pdcch_ul_candidate_index >= SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR) { + logger.error("Candidate index %d exceeds the number of candidates %d for aggregation level %d", + args.pdcch_ul_candidate_index, + n, + args.pdcch_aggregation_level); + return; + } + dci_ul_location[slot].L = args.pdcch_aggregation_level; + dci_ul_location[slot].ncce = ncce[args.pdcch_ul_candidate_index]; + } + + // Select DCI formats + for (uint32_t i = 0; i < ss.nof_formats; i++) { + // Select DL format + if (ss.formats[i] == srsran_dci_format_nr_1_0 or ss.formats[i] == srsran_dci_format_nr_1_1) { + dci_format_dl = ss.formats[i]; + } + + // Select DL format + if (ss.formats[i] == srsran_dci_format_nr_0_0 or ss.formats[i] == srsran_dci_format_nr_0_1) { + dci_format_ul = ss.formats[i]; + } + } + + // Validate that a DCI format is selected + if (dci_format_dl == SRSRAN_DCI_FORMAT_NR_COUNT or dci_format_ul == SRSRAN_DCI_FORMAT_NR_COUNT) { + logger.error("Missing valid DL or UL DCI format in search space"); + return; + } + + // Select DL frequency domain resources + dl_freq_res = srsran_ra_nr_type1_riv(args.phy_cfg.carrier.nof_prb, args.dl_start_rb, args.dl_length_rb); + + // Setup DL Data to ACK timing + for (uint32_t i = 0; i < SRSRAN_NOF_SF_X_FRAME; i++) { + dl_data_to_ul_ack[i] = args.phy_cfg.harq_ack.dl_data_to_ul_ack[i % SRSRAN_MAX_NOF_DL_DATA_TO_UL]; + } + + // If reached this point the configuration is valid + valid = true; + } + + ~gnb_dummy_stack() { srsran_random_free(random_gen); } + bool is_valid() const { return valid; } + + int sf_indication(const uint32_t tti) override { return 0; } + int rx_data_indication(rx_data_ind_t& grant) override { return 0; } + + int slot_indication(const srsran_slot_cfg_t& slot_cfg) override { return 0; } + + int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) override + { + // Check if it is TDD DL slot and PDSCH mask, if no PDSCH shall be scheduled, do not set any grant and skip + if (not srsran_tdd_nr_is_dl(&phy_cfg.tdd, phy_cfg.carrier.scs, slot_cfg.idx)) { + return SRSRAN_SUCCESS; + } + + // Select PDCCH and PDSCH from scheduling results + pdcch_dl_t& pdcch = dl_sched.pdcch_dl[0]; + pdsch_t& pdsch = dl_sched.pdsch[0]; + + // Select grant and set data + pdsch.data[0] = tx_harq_proc[slot_cfg.idx].data.data(); + + // Second TB is not used + pdsch.data[1] = nullptr; + + // Generate random data + srsran_random_byte_vector(random_gen, pdsch.data[0], SRSRAN_LDPC_MAX_LEN_CB * SRSRAN_SCH_NR_MAX_NOF_CB_LDPC / 8); + + // Fill DCI configuration + pdcch.dci_cfg = phy_cfg.get_dci_cfg(); + + // Fill DCI + srsran_dci_dl_nr_t& dci = pdcch.dci; + dci.ctx.location = dci_dl_location[slot_cfg.idx]; + dci.ctx.ss_type = ss.type; + dci.ctx.coreset_id = ss.coreset_id; + dci.ctx.rnti_type = srsran_rnti_type_c; + dci.ctx.format = dci_format_dl; + dci.ctx.rnti = rnti; + dci.freq_domain_assigment = dl_freq_res; + dci.time_domain_assigment = dl_time_res; + dci.mcs = mcs; + dci.rv = 0; + dci.ndi = (slot_cfg.idx / SRSRAN_NOF_SF_X_FRAME) % 2; + dci.pid = slot_cfg.idx % SRSRAN_NOF_SF_X_FRAME; + dci.dai = slot_cfg.idx % SRSRAN_NOF_SF_X_FRAME; + dci.tpc = 1; + dci.pucch_resource = 0; + dci.harq_feedback = dl_data_to_ul_ack[TTI_TX(slot_cfg.idx)]; + + // It currently support only one grant + dl_sched.pdcch_dl_count = 1; + dl_sched.pdsch_count = 1; + + // Create PDSCH configuration + if (srsran_ra_dl_dci_to_grant_nr(&phy_cfg.carrier, &slot_cfg, &phy_cfg.pdsch, &dci, &pdsch.sch, &pdsch.sch.grant) < + SRSRAN_SUCCESS) { + logger.error("Error converting DCI to grant"); + return SRSRAN_ERROR; + } + + // Set softbuffer + pdsch.sch.grant.tb[0].softbuffer.tx = &tx_harq_proc[slot_cfg.idx].softbuffer; + + // Reset Tx softbuffer always + srsran_softbuffer_tx_reset(pdsch.sch.grant.tb[0].softbuffer.tx); + + return SRSRAN_SUCCESS; + } + + int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override { return 0; } +}; + +#endif // SRSRAN_DUMMY_GNB_STACK_H diff --git a/test/phy/dummy_phy_common.h b/test/phy/dummy_phy_common.h index 2f898e90b..bb7d4a992 100644 --- a/test/phy/dummy_phy_common.h +++ b/test/phy/dummy_phy_common.h @@ -23,13 +23,14 @@ class phy_common : public srsran::phy_common_interface { private: const uint32_t RINGBUFFER_TIMEOUT_MS = 10; - bool quit = false; + std::atomic quit = {false}; srslog::basic_logger& logger; double srate_hz; uint64_t write_ts = 0; uint64_t read_ts = 0; std::vector zero_buffer; ///< Zero buffer for Tx std::vector sink_buffer; ///< Dummy buffer for Rx + std::mutex ringbuffers_mutex; std::vector ringbuffers; srsran::tti_semaphore semaphore; @@ -145,9 +146,7 @@ public: uint32_t nof_channels = 1; args_t(double srate_hz_, uint32_t buffer_sz_ms_, uint32_t nof_channels_) : - srate_hz(srate_hz_), - buffer_sz_ms(buffer_sz_ms_), - nof_channels(nof_channels_) + srate_hz(srate_hz_), buffer_sz_ms(buffer_sz_ms_), nof_channels(nof_channels_) {} }; @@ -186,6 +185,9 @@ public: // Synchronize worker semaphore.wait(h); + // Protect internal buffers and states + std::unique_lock lock(ringbuffers_mutex); + uint64_t tx_ts = srsran_timestamp_uint64(&tx_time.get(0), srate_hz); // Check transmit timestamp is not in the past @@ -213,6 +215,9 @@ public: void read(std::vector& buffers, uint32_t nof_samples, srsran::rf_timestamp_t& timestamp) { + // Protect internal buffers and states + std::unique_lock lock(ringbuffers_mutex); + // Detect if zero padding is necessary if (read_ts + nof_samples > write_ts) { uint32_t nof_zero_pading = (uint32_t)((read_ts + nof_samples) - write_ts); diff --git a/test/phy/nr_dl_flood.cc b/test/phy/nr_dl_flood.cc index 2407b3b18..26c5bd04e 100644 --- a/test/phy/nr_dl_flood.cc +++ b/test/phy/nr_dl_flood.cc @@ -10,6 +10,7 @@ * */ +#include "dummy_gnb_stack.h" #include "srsran/common/test_common.h" #include "test_bench.h" @@ -18,18 +19,13 @@ test_bench::args_t::args_t(int argc, char** argv) // Flag configuration as valid valid = true; - cell_list.resize(1); - cell_list[0].carrier.nof_prb = 52; - cell_list[0].carrier.max_mimo_layers = 1; - cell_list[0].carrier.pci = 500; - - phy_cfg.carrier = cell_list[0].carrier; - + phy_cfg.carrier.nof_prb = 52; + phy_cfg.carrier.max_mimo_layers = 1; + phy_cfg.carrier.pci = 500; phy_cfg.carrier.absolute_frequency_point_a = 633928; phy_cfg.carrier.absolute_frequency_ssb = 634176; phy_cfg.carrier.offset_to_carrier = 0; phy_cfg.carrier.scs = srsran_subcarrier_spacing_15kHz; - phy_cfg.carrier.nof_prb = 52; phy_cfg.ssb.periodicity_ms = 5; phy_cfg.ssb.position_in_burst[0] = true; @@ -212,8 +208,15 @@ test_bench::args_t::args_t(int argc, char** argv) phy_cfg.harq_ack.dl_data_to_ul_ack[4] = 4; phy_cfg.harq_ack.dl_data_to_ul_ack[5] = 12; phy_cfg.harq_ack.dl_data_to_ul_ack[6] = 11; + phy_cfg.harq_ack.harq_ack_codebook = srsran_pdsch_harq_ack_codebook_dynamic; phy_cfg.prach.freq_offset = 2; + + cell_list.resize(1); + cell_list[0].carrier = phy_cfg.carrier; + cell_list[0].rf_port = 0; + cell_list[0].cell_id = 0; + cell_list[0].pdcch = phy_cfg.pdcch; } class ue_dummy_stack : public srsue::stack_interface_phy_nr @@ -262,220 +265,6 @@ public: bool is_valid() const { return valid; } }; -class gnb_dummy_stack : public srsenb::stack_interface_phy_nr -{ -private: - srslog::basic_logger& logger = srslog::fetch_basic_logger("GNB STK"); - const uint16_t rnti = 0x1234; - const uint32_t mcs = 1; - const srsran::circular_array pdsch_mask; - srsran::circular_array dci_dl_location; - srsran::circular_array dci_ul_location; - srsran::circular_array dl_data_to_ul_ack; - bool valid = false; - srsran_search_space_t ss = {}; - srsran_dci_format_nr_t dci_format_ul = SRSRAN_DCI_FORMAT_NR_COUNT; - srsran_dci_format_nr_t dci_format_dl = SRSRAN_DCI_FORMAT_NR_COUNT; - uint32_t dl_freq_res = 0; - uint32_t dl_time_res = 0; - srsran_random_t random_gen = nullptr; - - struct dummy_harq_proc { - static const uint32_t MAX_TB_SZ = SRSRAN_LDPC_MAX_LEN_CB * SRSRAN_SCH_NR_MAX_NOF_CB_LDPC; - std::vector data; - srsran_softbuffer_tx_t softbuffer = {}; - - dummy_harq_proc() - { - // Allocate data - data.resize(MAX_TB_SZ); - - // Initialise softbuffer - if (srsran_softbuffer_tx_init_guru(&softbuffer, SRSRAN_SCH_NR_MAX_NOF_CB_LDPC, SRSRAN_LDPC_MAX_LEN_ENCODED_CB) < - SRSRAN_SUCCESS) { - ERROR("Error Tx buffer"); - } - } - - ~dummy_harq_proc() { srsran_softbuffer_tx_free(&softbuffer); } - }; - srsran::circular_array tx_harq_proc; - -public: - struct args_t { - srsran::phy_cfg_nr_t phy_cfg; ///< Physical layer configuration - uint16_t rnti = 0x1234; ///< C-RNTI - uint32_t mcs = 10; ///< Modulation code scheme - srsran::circular_array pdsch_mask = {}; ///< PDSCH scheduling mask - uint32_t ss_id = 1; ///< Search Space identifier - uint32_t pdcch_aggregation_level = 0; ///< PDCCH aggregation level - uint32_t pdcch_dl_candidate_index = 0; ///< PDCCH DL DCI candidate index - uint32_t pdcch_ul_candidate_index = 0; ///< PDCCH UL DCI candidate index - uint32_t dl_start_rb = 0; ///< Start resource block - uint32_t dl_length_rb = 0l; ///< Number of resource blocks - uint32_t dl_time_res = 0; ///< PDSCH time resource - }; - - gnb_dummy_stack(args_t args) : - pdsch_mask(args.pdsch_mask), - mcs(args.mcs), - rnti(args.rnti), - dl_time_res(args.dl_time_res) - { - random_gen = srsran_random_init(0x1234); - - // Select search space - if (args.ss_id >= SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE) { - logger.error("Search Space Id (%d) is out-of-range (%d)", args.ss_id, SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE); - return; - } - if (not args.phy_cfg.pdcch.search_space_present[args.ss_id]) { - logger.error("Search Space Id (%d) is not present", args.ss_id); - return; - } - ss = args.phy_cfg.pdcch.search_space[args.ss_id]; - - // Select CORESET - if (ss.coreset_id >= SRSRAN_UE_DL_NR_MAX_NOF_CORESET) { - logger.error("CORESET Id (%d) is out-of-range (%d)", ss.coreset_id, SRSRAN_UE_DL_NR_MAX_NOF_CORESET); - return; - } - if (not args.phy_cfg.pdcch.coreset_present[ss.coreset_id]) { - logger.error("CORESET Id (%d) is not present", args.ss_id); - return; - } - const srsran_coreset_t& coreset = args.phy_cfg.pdcch.coreset[ss.coreset_id]; - - // Select DCI locations - for (uint32_t slot = 0; slot < SRSRAN_NOF_SF_X_FRAME; slot++) { - std::array ncce = {}; - int n = srsran_pdcch_nr_locations_coreset(&coreset, &ss, rnti, args.pdcch_aggregation_level, slot++, ncce.data()); - if (n < SRSRAN_SUCCESS) { - logger.error( - "Error generating locations for slot %d and aggregation level %d", slot, args.pdcch_aggregation_level); - return; - } - uint32_t nof_candidates = (uint32_t)n; - - // DCI DL - if (args.pdcch_dl_candidate_index >= nof_candidates or - args.pdcch_dl_candidate_index >= SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR) { - logger.error("Candidate index %d exceeds the number of candidates %d for aggregation level %d", - args.pdcch_dl_candidate_index, - n, - args.pdcch_aggregation_level); - return; - } - dci_dl_location[slot].L = args.pdcch_aggregation_level; - dci_dl_location[slot].ncce = ncce[args.pdcch_dl_candidate_index]; - - // DCI UL - if (args.pdcch_ul_candidate_index >= nof_candidates or - args.pdcch_ul_candidate_index >= SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR) { - logger.error("Candidate index %d exceeds the number of candidates %d for aggregation level %d", - args.pdcch_ul_candidate_index, - n, - args.pdcch_aggregation_level); - return; - } - dci_ul_location[slot].L = args.pdcch_aggregation_level; - dci_ul_location[slot].ncce = ncce[args.pdcch_ul_candidate_index]; - } - - // Select DCI formats - for (uint32_t i = 0; i < ss.nof_formats; i++) { - // Select DL format - if (ss.formats[i] == srsran_dci_format_nr_1_0 or ss.formats[i] == srsran_dci_format_nr_1_1) { - dci_format_dl = ss.formats[i]; - } - - // Select DL format - if (ss.formats[i] == srsran_dci_format_nr_0_0 or ss.formats[i] == srsran_dci_format_nr_0_1) { - dci_format_ul = ss.formats[i]; - } - } - - // Validate that a DCI format is selected - if (dci_format_dl == SRSRAN_DCI_FORMAT_NR_COUNT or dci_format_ul == SRSRAN_DCI_FORMAT_NR_COUNT) { - logger.error("Missing valid DL or UL DCI format in search space"); - return; - } - - // Select DL frequency domain resources - dl_freq_res = srsran_ra_nr_type1_riv(args.phy_cfg.carrier.nof_prb, args.dl_start_rb, args.dl_length_rb); - - // Setup DL Data to ACK timing - for (uint32_t i = 0; i < SRSRAN_NOF_SF_X_FRAME; i++) { - dl_data_to_ul_ack[i] = args.phy_cfg.harq_ack.dl_data_to_ul_ack[i % SRSRAN_MAX_NOF_DL_DATA_TO_UL]; - } - - // If reached this point the configuration is valid - valid = true; - } - - ~gnb_dummy_stack() { srsran_random_free(random_gen); } - - bool is_valid() const { return valid; } - - int sf_indication(const uint32_t tti) override { return 0; } - int rx_data_indication(rx_data_ind_t& grant) override { return 0; } - - int get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res) override - { - // Check input - if (dl_sched_res.size() == 0) { - return SRSRAN_ERROR; - } - - // Check PDSCH mask, if no PDSCH shall be scheduled, do not set any grant and skip - if (not pdsch_mask[tti]) { - dl_sched_res[0].nof_grants = 0; - return SRSRAN_SUCCESS; - } - - // Select grant and set data - dl_sched_grant_t& grant = dl_sched_res[0].pdsch[0]; - grant.data[0] = tx_harq_proc[tti].data.data(); - grant.softbuffer_tx[0] = &tx_harq_proc[tti].softbuffer; - - // Second TB is not used - grant.data[1] = nullptr; - grant.softbuffer_tx[1] = nullptr; - - // Reset Tx softbuffer always - srsran_softbuffer_tx_reset(grant.softbuffer_tx[0]); - - // Generate random data - srsran_random_byte_vector(random_gen, grant.data[0], SRSRAN_LDPC_MAX_LEN_CB * SRSRAN_SCH_NR_MAX_NOF_CB_LDPC / 8); - - // It currently support only one grant - dl_sched_res[0].nof_grants = 1; - - // Fill DCI - srsran_dci_dl_nr_t& dci = grant.dci; - dci.ctx.location = dci_dl_location[tti]; - dci.ctx.ss_type = ss.type; - dci.ctx.coreset_id = ss.coreset_id; - dci.ctx.rnti_type = srsran_rnti_type_c; - dci.ctx.format = dci_format_dl; - dci.ctx.rnti = rnti; - dci.freq_domain_assigment = dl_freq_res; - dci.time_domain_assigment = dl_time_res; - dci.mcs = mcs; - dci.rv = 0; - dci.ndi = (tti / SRSRAN_NOF_SF_X_FRAME) % 2; - dci.pid = tti % SRSRAN_NOF_SF_X_FRAME; - dci.dai = tti % SRSRAN_NOF_SF_X_FRAME; - dci.tpc = 1; - dci.pucch_resource = 0; - dci.harq_feedback = dl_data_to_ul_ack[tti]; - - return SRSRAN_SUCCESS; - } - - int get_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res) override { return 0; } -}; - int main(int argc, char** argv) { srslog::init(); @@ -484,7 +273,7 @@ int main(int argc, char** argv) test_bench::args_t args(argc, argv); args.gnb_args.log_id_preamble = "GNB/"; args.gnb_args.log_level = "warning"; - args.gnb_args.nof_workers = 1; + args.gnb_args.nof_phy_threads = 1; args.ue_args.log.id_preamble = " UE/"; args.ue_args.log.phy_level = "warning"; args.ue_args.log.phy_hex_limit = 0; @@ -505,12 +294,9 @@ int main(int argc, char** argv) gnb_dummy_stack::args_t gnb_stack_args = {}; gnb_stack_args.rnti = 0x1234; gnb_stack_args.mcs = 10; - for (bool& mask : gnb_stack_args.pdsch_mask) { - mask = true; - } - gnb_stack_args.phy_cfg = args.phy_cfg; - gnb_stack_args.dl_start_rb = 0; - gnb_stack_args.dl_length_rb = args.phy_cfg.carrier.nof_prb; + gnb_stack_args.phy_cfg = args.phy_cfg; + gnb_stack_args.dl_start_rb = 0; + gnb_stack_args.dl_length_rb = args.phy_cfg.carrier.nof_prb; // Create GNB stack gnb_dummy_stack gnb_stack(gnb_stack_args); diff --git a/test/phy/test_bench.h b/test/phy/test_bench.h index b878cb355..11425de6f 100644 --- a/test/phy/test_bench.h +++ b/test/phy/test_bench.h @@ -33,7 +33,6 @@ private: public: struct args_t { double srate_hz = 11.52e6; - uint32_t nof_threads = 6; uint32_t nof_channels = 1; uint32_t buffer_sz_ms = 10; bool valid = false; @@ -48,18 +47,20 @@ public: }; test_bench(const args_t& args, srsenb::stack_interface_phy_nr& gnb_stack, srsue::stack_interface_phy_nr& ue_stack) : - ue_phy(args.nof_threads), - gnb_phy(args.cell_list, args.gnb_args, gnb_phy_com, gnb_stack, srslog::get_default_sink()), + ue_phy(args.ue_args.nof_phy_threads), + gnb_phy(gnb_phy_com, gnb_stack, srslog::get_default_sink(), args.gnb_args.nof_phy_threads), ue_phy_com(phy_common::args_t(args.srate_hz, args.buffer_sz_ms, args.nof_channels), srslog::fetch_basic_logger(UE_PHY_COM_LOG_NAME, srslog::get_default_sink(), false)), gnb_phy_com(phy_common::args_t(args.srate_hz, args.buffer_sz_ms, args.nof_channels), - srslog::fetch_basic_logger(GNB_PHY_COM_LOG_NAME, srslog::get_default_sink(), false)) + srslog::fetch_basic_logger(GNB_PHY_COM_LOG_NAME, srslog::get_default_sink(), false)), + sf_sz((uint32_t)std::round(args.srate_hz * 1e-3)) { srslog::fetch_basic_logger(UE_PHY_COM_LOG_NAME).set_level(srslog::str_to_basic_level(args.phy_com_log_level)); srslog::fetch_basic_logger(GNB_PHY_COM_LOG_NAME).set_level(srslog::str_to_basic_level(args.phy_com_log_level)); - // Calculate subframe length - sf_sz = (uint32_t)std::round(args.srate_hz * 1e-3); + if (not gnb_phy.init(args.gnb_args, args.cell_list)) { + return; + } // Initialise UE PHY if (not ue_phy.init(args.ue_args, ue_phy_com, &ue_stack, 31)) { @@ -71,11 +72,6 @@ public: return; } - // Set UE configuration in gNb - if (not gnb_phy.addmod_rnti(args.rnti, args.phy_cfg)) { - return; - } - initialised = true; } @@ -92,7 +88,7 @@ public: bool run_tti() { // Get gNb worker - srsenb::nr::sf_worker* gnb_worker = gnb_phy.wait_worker(tti); + srsenb::nr::slot_worker* gnb_worker = gnb_phy.wait_worker(tti); if (gnb_worker == nullptr) { return false; } @@ -100,7 +96,7 @@ public: // Feed gNb the UE transmitted signal srsran::rf_timestamp_t gnb_time = {}; std::vector gnb_rx_buffers(1); - gnb_rx_buffers[0] = gnb_worker->get_buffer_rx(0, 0); + gnb_rx_buffers[0] = gnb_worker->get_buffer_rx(0); ue_phy_com.read(gnb_rx_buffers, sf_sz, gnb_time); // Set gNb time From 6f5614a0cce50c1394a11da1397cd9e293f62114 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 23 Jun 2021 15:14:36 +0200 Subject: [PATCH 29/43] Suggested modifications on gNb MAC/PHY interface --- .../srsran/interfaces/gnb_interfaces.h | 31 ++++++++------- lib/src/common/basic_vnf.cc | 4 +- srsenb/hdr/stack/gnb_stack_nr.h | 5 +-- srsenb/src/phy/nr/slot_worker.cc | 39 +++++++++++-------- srsenb/src/stack/gnb_stack_nr.cc | 5 --- srsenb/src/stack/mac/nr/mac_nr.cc | 10 ++--- test/phy/dummy_gnb_stack.h | 21 +++++----- 7 files changed, 57 insertions(+), 58 deletions(-) diff --git a/lib/include/srsran/interfaces/gnb_interfaces.h b/lib/include/srsran/interfaces/gnb_interfaces.h index c061c58cc..d0c9fd902 100644 --- a/lib/include/srsran/interfaces/gnb_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_interfaces.h @@ -210,7 +210,9 @@ public: class mac_interface_phy_nr { public: - const static int MAX_GRANTS = 64; + const static int MAX_SSB = 4; + const static int MAX_GRANTS = 64; + const static int MAX_NZP_CSI_RS = 4; struct pdcch_dl_t { srsran_dci_cfg_nr_t dci_cfg = {}; @@ -227,13 +229,16 @@ public: std::array data = {}; ///< Data pointer }; + struct ssb_t { + srsran_pbch_msg_nr_t pbch_msg = {}; + }; + struct dl_sched_t { - std::array pdcch_dl; - uint32_t pdcch_dl_count = 0; - std::array pdcch_ul; - uint32_t pdcch_ul_count = 0; - std::array pdsch; - uint32_t pdsch_count = 0; + srsran::bounded_vector ssb; + srsran::bounded_vector pdcch_dl; + srsran::bounded_vector pdcch_ul; + srsran::bounded_vector pdsch; + srsran::bounded_vector nzp_csi_rs; }; struct pusch_t { @@ -242,15 +247,14 @@ public: std::array softbuffer_tx = {}; ///< Tx Softbuffer }; - struct uci_t { - srsran_uci_cfg_nr_t cfg; + struct pucch_t { + srsran_uci_cfg_nr_t uci_cfg; + srsran_pucch_nr_resource_t resource; }; struct ul_sched_t { - std::array pusch; - uint32_t pusch_count = 0; - std::array uci; - uint32_t uci_count; + srsran::bounded_vector pusch; + srsran::bounded_vector pucch; }; virtual int slot_indication(const srsran_slot_cfg_t& slot_cfg) = 0; @@ -267,7 +271,6 @@ public: srsran::unique_byte_buffer_t tb; }; - virtual int sf_indication(const uint32_t tti) = 0; virtual int rx_data_indication(rx_data_ind_t& grant) = 0; }; diff --git a/lib/src/common/basic_vnf.cc b/lib/src/common/basic_vnf.cc index 223d9a9dc..be8a609e9 100644 --- a/lib/src/common/basic_vnf.cc +++ b/lib/src/common/basic_vnf.cc @@ -155,7 +155,9 @@ int srsran_basic_vnf::handle_sf_ind(basic_vnf_api::sf_ind_msg_t* msg) last_sf_indication_time = msg->t1; if (m_gnb_stack != nullptr) { - m_gnb_stack->sf_indication(msg->tti); + srsran_slot_cfg_t slot_cfg = {}; + slot_cfg.idx = msg->tti; + m_gnb_stack->slot_indication(slot_cfg); } else if (m_ue_stack != nullptr) { m_ue_stack->sf_indication(msg->tti); } else { diff --git a/srsenb/hdr/stack/gnb_stack_nr.h b/srsenb/hdr/stack/gnb_stack_nr.h index 549791e32..328348e4c 100644 --- a/srsenb/hdr/stack/gnb_stack_nr.h +++ b/srsenb/hdr/stack/gnb_stack_nr.h @@ -59,12 +59,11 @@ public: bool start_service_request() override { return true; }; // PHY->MAC interface - int sf_indication(const uint32_t tti) override; int rx_data_indication(rx_data_ind_t& grant) override; // Temporary GW interface - void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu); - bool has_active_radio_bearer(uint32_t eps_bearer_id); + void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) override; + bool has_active_radio_bearer(uint32_t eps_bearer_id) override; bool switch_on(); void run_tti(uint32_t tti); diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index c47a4572e..9bb1fa0bf 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -132,14 +132,12 @@ bool slot_worker::work_ul() } // Decode PUCCH - for (uint32_t i = 0; i < ul_sched.uci_count; i++) { - const stack_interface_phy_nr::uci_t& uci = ul_sched.uci[i]; + for (stack_interface_phy_nr::pucch_t& pucch : ul_sched.pucch) { // ... } // Decode PUSCH - for (uint32_t i = 0; i < ul_sched.pusch_count; i++) { - const stack_interface_phy_nr::pusch_t& pusch = ul_sched.pusch[i]; + for (stack_interface_phy_nr::pusch_t& pusch : ul_sched.pusch) { // ... } @@ -148,17 +146,20 @@ bool slot_worker::work_ul() bool slot_worker::work_dl() { + // Retrieve Scheduling for the current processing DL slot stack_interface_phy_nr::dl_sched_t dl_sched = {}; if (stack.get_dl_sched(ul_slot_cfg, dl_sched) < SRSRAN_SUCCESS) { logger.error("Error retrieving DL scheduling"); return false; } - // Encode PDCCH for DL transmissions - for (uint32_t i = 0; i < dl_sched.pdcch_dl_count; i++) { - // Select PDCCH from scheduler result - const stack_interface_phy_nr::pdcch_dl_t& pdcch = dl_sched.pdcch_dl[i]; + if (srsran_enb_dl_nr_base_zero(&gnb_dl) < SRSRAN_SUCCESS) { + logger.error("Error zeroeing RE grid"); + return false; + } + // Encode PDCCH for DL transmissions + for (const stack_interface_phy_nr::pdcch_dl_t& pdcch : dl_sched.pdcch_dl) { // Set PDCCH configuration, including DCI dedicated if (srsran_enb_dl_nr_set_pdcch_config(&gnb_dl, &pdcch_cfg, &pdcch.dci_cfg) < SRSRAN_SUCCESS) { logger.error("PDCCH: Error setting DL configuration"); @@ -180,10 +181,7 @@ bool slot_worker::work_dl() } // Encode PDCCH for UL transmissions - for (uint32_t i = 0; i < dl_sched.pdcch_ul_count; i++) { - // Select PDCCH from scheduler result - const stack_interface_phy_nr::pdcch_ul_t& pdcch = dl_sched.pdcch_ul[i]; - + for (const stack_interface_phy_nr::pdcch_ul_t& pdcch : dl_sched.pdcch_ul) { // Set PDCCH configuration, including DCI dedicated if (srsran_enb_dl_nr_set_pdcch_config(&gnb_dl, &pdcch_cfg, &pdcch.dci_cfg) < SRSRAN_SUCCESS) { logger.error("PDCCH: Error setting DL configuration"); @@ -205,10 +203,7 @@ bool slot_worker::work_dl() } // Encode PDSCH - for (uint32_t i = 0; i < dl_sched.pdsch_count; i++) { - // Select PDSCH from scheduler result - stack_interface_phy_nr::pdsch_t& pdsch = dl_sched.pdsch[i]; - + for (stack_interface_phy_nr::pdsch_t& pdsch : dl_sched.pdsch) { // Put PDSCH message if (srsran_enb_dl_nr_pdsch_put(&gnb_dl, &dl_slot_cfg, &pdsch.sch, pdsch.data.data()) < SRSRAN_SUCCESS) { logger.error("PDSCH: Error putting DL message"); @@ -223,16 +218,26 @@ bool slot_worker::work_dl() } } + // Put NZP-CSI-RS + for (srsran_csi_rs_nzp_resource_t& pdsch : dl_sched.nzp_csi_rs) { + // ... + } + // Generate baseband signal srsran_enb_dl_nr_gen_signal(&gnb_dl); + // Add SSB to the baseband signal + for (const stack_interface_phy_nr::ssb_t& ssb : dl_sched.ssb) { + // ... + } + return true; } void slot_worker::work_imp() { // Inform Scheduler about new slot - stack.sf_indication(dl_slot_cfg.idx); + stack.slot_indication(dl_slot_cfg); // Get Transmission buffers srsran::rf_buffer_t tx_rf_buffer = {}; diff --git a/srsenb/src/stack/gnb_stack_nr.cc b/srsenb/src/stack/gnb_stack_nr.cc index cafe2e7c3..54a25b4bc 100644 --- a/srsenb/src/stack/gnb_stack_nr.cc +++ b/srsenb/src/stack/gnb_stack_nr.cc @@ -162,11 +162,6 @@ bool gnb_stack_nr::get_metrics(srsenb::stack_metrics_t* metrics) return true; } -int gnb_stack_nr::sf_indication(const uint32_t tti) -{ - return m_mac->sf_indication(tti); -} - int gnb_stack_nr::rx_data_indication(rx_data_ind_t& grant) { return m_mac->rx_data_indication(grant); diff --git a/srsenb/src/stack/mac/nr/mac_nr.cc b/srsenb/src/stack/mac/nr/mac_nr.cc index 66ba30c0f..f03dec542 100644 --- a/srsenb/src/stack/mac/nr/mac_nr.cc +++ b/srsenb/src/stack/mac/nr/mac_nr.cc @@ -176,15 +176,15 @@ void mac_nr::get_dl_config(const uint32_t tti, tx_request.tti = tti; } -int mac_nr::sf_indication(const uint32_t tti) +int mac_nr::slot_indication(const srsran_slot_cfg_t& slot_cfg) { phy_interface_stack_nr::dl_config_request_t config_request = {}; phy_interface_stack_nr::tx_request_t tx_request = {}; // step MAC TTI - logger.set_context(tti); + logger.set_context(slot_cfg.idx); - get_dl_config(tti, config_request, tx_request); + get_dl_config(slot_cfg.idx, config_request, tx_request); // send DL_CONFIG.request phy_h->dl_config_request(config_request); @@ -267,10 +267,6 @@ int mac_nr::cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg) return SRSRAN_SUCCESS; } -int mac_nr::slot_indication(const srsran_slot_cfg_t& slot_cfg) -{ - return 0; -} int mac_nr::get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) { diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 4536ac999..8162dcac4 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -166,7 +166,6 @@ public: ~gnb_dummy_stack() { srsran_random_free(random_gen); } bool is_valid() const { return valid; } - int sf_indication(const uint32_t tti) override { return 0; } int rx_data_indication(rx_data_ind_t& grant) override { return 0; } int slot_indication(const srsran_slot_cfg_t& slot_cfg) override { return 0; } @@ -178,9 +177,9 @@ public: return SRSRAN_SUCCESS; } - // Select PDCCH and PDSCH from scheduling results - pdcch_dl_t& pdcch = dl_sched.pdcch_dl[0]; - pdsch_t& pdsch = dl_sched.pdsch[0]; + // Instantiate PDCCH and PDSCH + pdcch_dl_t pdcch = {}; + pdsch_t pdsch = {}; // Select grant and set data pdsch.data[0] = tx_harq_proc[slot_cfg.idx].data.data(); @@ -188,9 +187,6 @@ public: // Second TB is not used pdsch.data[1] = nullptr; - // Generate random data - srsran_random_byte_vector(random_gen, pdsch.data[0], SRSRAN_LDPC_MAX_LEN_CB * SRSRAN_SCH_NR_MAX_NOF_CB_LDPC / 8); - // Fill DCI configuration pdcch.dci_cfg = phy_cfg.get_dci_cfg(); @@ -213,10 +209,6 @@ public: dci.pucch_resource = 0; dci.harq_feedback = dl_data_to_ul_ack[TTI_TX(slot_cfg.idx)]; - // It currently support only one grant - dl_sched.pdcch_dl_count = 1; - dl_sched.pdsch_count = 1; - // Create PDSCH configuration if (srsran_ra_dl_dci_to_grant_nr(&phy_cfg.carrier, &slot_cfg, &phy_cfg.pdsch, &dci, &pdsch.sch, &pdsch.sch.grant) < SRSRAN_SUCCESS) { @@ -224,12 +216,19 @@ public: return SRSRAN_ERROR; } + // Generate random data + srsran_random_byte_vector(random_gen, pdsch.data[0], pdsch.sch.grant.tb[0].tbs / 8); + // Set softbuffer pdsch.sch.grant.tb[0].softbuffer.tx = &tx_harq_proc[slot_cfg.idx].softbuffer; // Reset Tx softbuffer always srsran_softbuffer_tx_reset(pdsch.sch.grant.tb[0].softbuffer.tx); + // Push scheduling results + dl_sched.pdcch_dl.push_back(pdcch); + dl_sched.pdsch.push_back(pdsch); + return SRSRAN_SUCCESS; } From e20934583e8471159b4cd763ee070cb43cabc6b9 Mon Sep 17 00:00:00 2001 From: faluco Date: Fri, 25 Jun 2021 10:21:31 +0200 Subject: [PATCH 30/43] Remove an unsafe assert in the log backend that could be triggered under very certain circumstances. RFCI has detected this assert failing in the log_backend_test. I have not been able to reproduce this locally but my theory is the following one: one of the unit tests does the following: backend.start(); backend.stop(); the internal running_flag member could be set to true and then to false by the main thread before the worker thread calls do_work(). If this happens the assert will be triggered, which is wrong and too conservative, so remove the assert. --- lib/src/srslog/backend_worker.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/src/srslog/backend_worker.cpp b/lib/src/srslog/backend_worker.cpp index 8c1040599..87c043842 100644 --- a/lib/src/srslog/backend_worker.cpp +++ b/lib/src/srslog/backend_worker.cpp @@ -85,8 +85,6 @@ void backend_worker::start(backend_priority priority) void backend_worker::do_work() { - assert(running_flag && "Thread entry function called without running thread"); - /// This period defines the time the worker will sleep while waiting for new entries. This is required to check the /// termination variable periodically. constexpr std::chrono::microseconds sleep_period{100}; From 368c7b9e4ff81690996952380818559ff273905e Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 25 Jun 2021 11:06:45 +0200 Subject: [PATCH 31/43] ue,stack: clear all EPS bearers when going RRC idle the EPS bearer manager was only informed when a single DRB was removed but not when entering idle which requires to remove all bearers. This cause the service request to fail. --- lib/include/srsran/interfaces/ue_interfaces.h | 1 + srsue/hdr/stack/bearer_manager.h | 5 ++++- srsue/hdr/stack/ue_stack_lte.h | 1 + srsue/hdr/stack/ue_stack_nr.h | 7 ++++--- srsue/src/stack/bearer_manager.cc | 8 +++++++- srsue/src/stack/rrc/rrc.cc | 1 + srsue/src/stack/ue_stack_lte.cc | 5 +++++ 7 files changed, 23 insertions(+), 5 deletions(-) diff --git a/lib/include/srsran/interfaces/ue_interfaces.h b/lib/include/srsran/interfaces/ue_interfaces.h index b55a5266b..f267c5b9e 100644 --- a/lib/include/srsran/interfaces/ue_interfaces.h +++ b/lib/include/srsran/interfaces/ue_interfaces.h @@ -31,6 +31,7 @@ public: virtual srsran::tti_point get_current_tti() = 0; virtual void add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) = 0; virtual void remove_eps_bearer(uint8_t eps_bearer_id) = 0; + virtual void reset_eps_bearers() = 0; }; // Combined interface for PHY to access stack (MAC and RRC) diff --git a/srsue/hdr/stack/bearer_manager.h b/srsue/hdr/stack/bearer_manager.h index b954bd6e8..7e2d3d779 100644 --- a/srsue/hdr/stack/bearer_manager.h +++ b/srsue/hdr/stack/bearer_manager.h @@ -45,9 +45,12 @@ public: /// Registers EPS bearer with PDCP RAT type and LCID void add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid); - /// EPS bearer is removed from map when the associated DRB is deleted (e.g. after connection release) + /// Single EPS bearer is removed from map when the associated DRB is deleted void remove_eps_bearer(uint8_t eps_bearer_id); + /// All registered bearer are removed (e.g. after connection release) + void reset(); + // GW interface bool has_active_radio_bearer(uint32_t eps_bearer_id); diff --git a/srsue/hdr/stack/ue_stack_lte.h b/srsue/hdr/stack/ue_stack_lte.h index 2c81c017b..4f9d5f1b2 100644 --- a/srsue/hdr/stack/ue_stack_lte.h +++ b/srsue/hdr/stack/ue_stack_lte.h @@ -167,6 +167,7 @@ public: tti_point get_current_tti() final { return current_tti; } void add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) final; void remove_eps_bearer(uint8_t eps_bearer_id) final; + void reset_eps_bearers() final; srsran::ext_task_sched_handle get_task_sched() { return {&task_sched}; } diff --git a/srsue/hdr/stack/ue_stack_nr.h b/srsue/hdr/stack/ue_stack_nr.h index dbb4cf0cb..6e5189c81 100644 --- a/srsue/hdr/stack/ue_stack_nr.h +++ b/srsue/hdr/stack/ue_stack_nr.h @@ -106,9 +106,10 @@ public: bool has_active_radio_bearer(uint32_t eps_bearer_id) final { return true; /* TODO: add EPS to LCID mapping */ } // Interface for RRC - srsran::tti_point get_current_tti() { return srsran::tti_point{0}; }; - void add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) final{}; - void remove_eps_bearer(uint8_t eps_bearer_id) final{}; + srsran::tti_point get_current_tti() { return srsran::tti_point{0}; } + void add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) final {} + void remove_eps_bearer(uint8_t eps_bearer_id) final {} + void reset_eps_bearers() final {} private: void run_thread() final; diff --git a/srsue/src/stack/bearer_manager.cc b/srsue/src/stack/bearer_manager.cc index 9b2d4c87e..862fd1ba5 100644 --- a/srsue/src/stack/bearer_manager.cc +++ b/srsue/src/stack/bearer_manager.cc @@ -36,7 +36,6 @@ void bearer_manager::add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t logger.info("Registered EPS bearer ID %d for lcid=%d over %s-PDCP", eps_bearer_id, lcid, to_string(rat).c_str()); } -/// EPS bearer is removed from map when the associated DRB is deleted (e.g. after connection release) void bearer_manager::remove_eps_bearer(uint8_t eps_bearer_id) { srsran::rwlock_write_guard rw_lock(rwlock); @@ -49,6 +48,13 @@ void bearer_manager::remove_eps_bearer(uint8_t eps_bearer_id) logger.info("Removed mapping for EPS bearer ID %d", eps_bearer_id); } +void bearer_manager::reset() +{ + srsran::rwlock_write_guard rw_lock(rwlock); + eps_rb_map.clear(); + logger.info("Reset EPS bearer manager"); +} + // GW interface bool bearer_manager::has_active_radio_bearer(uint32_t eps_bearer_id) { diff --git a/srsue/src/stack/rrc/rrc.cc b/srsue/src/stack/rrc/rrc.cc index b97956247..eb6ea061a 100644 --- a/srsue/src/stack/rrc/rrc.cc +++ b/srsue/src/stack/rrc/rrc.cc @@ -1120,6 +1120,7 @@ void rrc::leave_connected() rlc->reset(); pdcp->reset(); set_mac_default(); + stack->reset_eps_bearers(); // 1> indicate the release of the RRC connection to upper layers together with the release cause; nas->left_rrc_connected(); diff --git a/srsue/src/stack/ue_stack_lte.cc b/srsue/src/stack/ue_stack_lte.cc index 40f0eb0a9..94adee7dd 100644 --- a/srsue/src/stack/ue_stack_lte.cc +++ b/srsue/src/stack/ue_stack_lte.cc @@ -391,6 +391,11 @@ bool ue_stack_lte::has_active_radio_bearer(uint32_t eps_bearer_id) return bearers.has_active_radio_bearer(eps_bearer_id); } +void ue_stack_lte::reset_eps_bearers() +{ + bearers.reset(); +} + /** * Check whether nas is attached * @return bool wether NAS is in EMM_REGISTERED From 4d11e5552a9e6bfe2055f566acc1cbb93e19bb7e Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 25 Jun 2021 11:08:25 +0200 Subject: [PATCH 32/43] rrc,ue: for RRC conn release, delay transition to RRC idle by 60ms as per TS 36.331 when receiving RRC connection release all actions shall be delayed by 60ms as per the standard --- lib/include/srsran/test/ue_test_interfaces.h | 1 + srsue/src/stack/rrc/rrc.cc | 4 +++- srsue/src/stack/rrc/test/ue_rrc_nr_test.cc | 7 ++++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/include/srsran/test/ue_test_interfaces.h b/lib/include/srsran/test/ue_test_interfaces.h index 3df9d9605..196a39e45 100644 --- a/lib/include/srsran/test/ue_test_interfaces.h +++ b/lib/include/srsran/test/ue_test_interfaces.h @@ -29,6 +29,7 @@ public: srsran::tti_point get_current_tti() override { return srsran::tti_point{tti % 10240}; } void add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) final{}; void remove_eps_bearer(uint8_t eps_bearer_id) final{}; + void reset_eps_bearers() final{}; // Testing utility functions void run_tti() diff --git a/srsue/src/stack/rrc/rrc.cc b/srsue/src/stack/rrc/rrc.cc index eb6ea061a..28935ef8d 100644 --- a/srsue/src/stack/rrc/rrc.cc +++ b/srsue/src/stack/rrc/rrc.cc @@ -1098,7 +1098,9 @@ void rrc::rrc_connection_release(const std::string& cause) { // Save idleModeMobilityControlInfo, etc. srsran::console("Received RRC Connection Release (releaseCause: %s)\n", cause.c_str()); - start_go_idle(); + + // delay actions by 60ms as per 5.3.8.3 + task_sched.defer_callback(60, [this]() { start_go_idle(); }); } /// TS 36.331, 5.3.12 - UE actions upon leaving RRC_CONNECTED diff --git a/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc b/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc index 185386a01..1f382e78c 100644 --- a/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc +++ b/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc @@ -100,9 +100,10 @@ class dummy_sim : public usim_interface_rrc_nr class dummy_stack : public stack_interface_rrc { - srsran::tti_point get_current_tti() { return srsran::tti_point(); }; - void add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid){}; - void remove_eps_bearer(uint8_t eps_bearer_id){}; + srsran::tti_point get_current_tti() final { return srsran::tti_point(); }; + void add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) final{}; + void remove_eps_bearer(uint8_t eps_bearer_id) final{}; + void reset_eps_bearers() final{}; }; int rrc_nr_cap_request_test() From 0a16f48869283534bd44d3986fa96d5ccf1ecfc5 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 28 Jun 2021 10:01:44 +0200 Subject: [PATCH 33/43] gw: fix race condition GW thread was checking the default_eps_bearer variable without protection. RRC could update it when deleting DRB or receiving RRC connection release. --- srsue/hdr/stack/upper/gw.h | 2 + srsue/src/stack/upper/gw.cc | 142 ++++++++++++++++++------------------ 2 files changed, 72 insertions(+), 72 deletions(-) diff --git a/srsue/hdr/stack/upper/gw.h b/srsue/hdr/stack/upper/gw.h index f4bf13ab2..dc36f38ea 100644 --- a/srsue/hdr/stack/upper/gw.h +++ b/srsue/hdr/stack/upper/gw.h @@ -22,6 +22,7 @@ #include "srsran/srslog/srslog.h" #include "tft_packet_filter.h" #include +#include #include #include @@ -84,6 +85,7 @@ private: static const int NOT_ASSIGNED = -1; int32_t default_eps_bearer_id = NOT_ASSIGNED; + std::mutex gw_mutex; srslog::basic_logger& logger; diff --git a/srsue/src/stack/upper/gw.cc b/srsue/src/stack/upper/gw.cc index 90afe24ad..4ae579421 100644 --- a/srsue/src/stack/upper/gw.cc +++ b/srsue/src/stack/upper/gw.cc @@ -165,11 +165,7 @@ void gw::write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) /******************************************************************************* NAS interface *******************************************************************************/ -int gw::setup_if_addr(uint32_t eps_bearer_id, - uint8_t pdn_type, - uint32_t ip_addr, - uint8_t* ipv6_if_addr, - char* err_str) +int gw::setup_if_addr(uint32_t eps_bearer_id, uint8_t pdn_type, uint32_t ip_addr, uint8_t* ipv6_if_addr, char* err_str) { int err; if (pdn_type == LIBLTE_MME_PDN_TYPE_IPV4 || pdn_type == LIBLTE_MME_PDN_TYPE_IPV4V6) { @@ -212,8 +208,7 @@ bool gw::is_running() return running; } -int gw::apply_traffic_flow_template(const uint8_t& erab_id, - const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft) +int gw::apply_traffic_flow_template(const uint8_t& erab_id, const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft) { return tft_matcher.apply_traffic_flow_template(erab_id, tft); } @@ -270,86 +265,89 @@ void gw::run_thread() break; } - // Check if IP version makes sense and get packtet length - struct iphdr* ip_pkt = (struct iphdr*)pdu->msg; - struct ipv6hdr* ip6_pkt = (struct ipv6hdr*)pdu->msg; - uint16_t pkt_len = 0; - pdu->N_bytes = idx + N_bytes; - if (ip_pkt->version == 4) { - pkt_len = ntohs(ip_pkt->tot_len); - } else if (ip_pkt->version == 6) { - pkt_len = ntohs(ip6_pkt->payload_len) + 40; - } else { - logger.error(pdu->msg, pdu->N_bytes, "Unsupported IP version. Dropping packet."); - continue; - } - logger.debug("IPv%d packet total length: %d Bytes", int(ip_pkt->version), pkt_len); - - // Check if entire packet was received - if (pkt_len == pdu->N_bytes) { - logger.info(pdu->msg, pdu->N_bytes, "TX PDU"); - - // Make sure UE is attached and has default EPS bearer activated - while (run_enable && default_eps_bearer_id == NOT_ASSIGNED && register_wait < REGISTER_WAIT_TOUT) { - if (!register_wait) { - logger.info("UE is not attached, waiting for NAS attach (%d/%d)", register_wait, REGISTER_WAIT_TOUT); - } - usleep(100000); - register_wait++; - } - register_wait = 0; - - // If we are still not attached by this stage, drop packet - if (run_enable && default_eps_bearer_id == NOT_ASSIGNED) { + { + std::unique_lock lock(gw_mutex); + // Check if IP version makes sense and get packtet length + struct iphdr* ip_pkt = (struct iphdr*)pdu->msg; + struct ipv6hdr* ip6_pkt = (struct ipv6hdr*)pdu->msg; + uint16_t pkt_len = 0; + pdu->N_bytes = idx + N_bytes; + if (ip_pkt->version == 4) { + pkt_len = ntohs(ip_pkt->tot_len); + } else if (ip_pkt->version == 6) { + pkt_len = ntohs(ip6_pkt->payload_len) + 40; + } else { + logger.error(pdu->msg, pdu->N_bytes, "Unsupported IP version. Dropping packet."); continue; } + logger.debug("IPv%d packet total length: %d Bytes", int(ip_pkt->version), pkt_len); - // Beyond this point we should have a activated default EPS bearer - srsran_assert(default_eps_bearer_id != NOT_ASSIGNED, "Default EPS bearer not activated"); + // Check if entire packet was received + if (pkt_len == pdu->N_bytes) { + logger.info(pdu->msg, pdu->N_bytes, "TX PDU"); - uint8_t eps_bearer_id = default_eps_bearer_id; - tft_matcher.check_tft_filter_match(pdu, eps_bearer_id); + // Make sure UE is attached and has default EPS bearer activated + while (run_enable && default_eps_bearer_id == NOT_ASSIGNED && register_wait < REGISTER_WAIT_TOUT) { + if (!register_wait) { + logger.info("UE is not attached, waiting for NAS attach (%d/%d)", register_wait, REGISTER_WAIT_TOUT); + } + lock.unlock(); + std::this_thread::sleep_for(std::chrono::microseconds(100)); + lock.lock(); + register_wait++; + } + register_wait = 0; - // Wait for service request if necessary - while (run_enable && !stack->has_active_radio_bearer(eps_bearer_id) && service_wait < SERVICE_WAIT_TOUT) { - if (!service_wait) { - logger.info( - "UE does not have service, waiting for NAS service request (%d/%d)", service_wait, SERVICE_WAIT_TOUT); - stack->start_service_request(); + // If we are still not attached by this stage, drop packet + if (run_enable && default_eps_bearer_id == NOT_ASSIGNED) { + continue; } - usleep(100000); - service_wait++; - } - service_wait = 0; - // Quit before writing packet if necessary - if (!run_enable) { - break; - } + // Beyond this point we should have a activated default EPS bearer + srsran_assert(default_eps_bearer_id != NOT_ASSIGNED, "Default EPS bearer not activated"); - // Send PDU directly to PDCP - pdu->set_timestamp(); - ul_tput_bytes += pdu->N_bytes; - stack->write_sdu(eps_bearer_id, std::move(pdu)); - do { - pdu = srsran::make_byte_buffer(); - if (!pdu) { - logger.error("Fatal Error: Couldn't allocate PDU in run_thread()."); + uint8_t eps_bearer_id = default_eps_bearer_id; + tft_matcher.check_tft_filter_match(pdu, eps_bearer_id); + + // Wait for service request if necessary + while (run_enable && !stack->has_active_radio_bearer(eps_bearer_id) && service_wait < SERVICE_WAIT_TOUT) { + if (!service_wait) { + logger.info( + "UE does not have service, waiting for NAS service request (%d/%d)", service_wait, SERVICE_WAIT_TOUT); + stack->start_service_request(); + } usleep(100000); + service_wait++; } - } while (!pdu); - idx = 0; - } else { - idx += N_bytes; - logger.debug("Entire packet not read from socket. Total Length %d, N_Bytes %d.", ip_pkt->tot_len, pdu->N_bytes); - } + service_wait = 0; + + // Quit before writing packet if necessary + if (!run_enable) { + break; + } + + // Send PDU directly to PDCP + pdu->set_timestamp(); + ul_tput_bytes += pdu->N_bytes; + stack->write_sdu(eps_bearer_id, std::move(pdu)); + do { + pdu = srsran::make_byte_buffer(); + if (!pdu) { + logger.error("Fatal Error: Couldn't allocate PDU in run_thread()."); + usleep(100000); + } + } while (!pdu); + idx = 0; + } else { + idx += N_bytes; + logger.debug("Entire packet not read from socket. Total Length %d, N_Bytes %d.", ip_pkt->tot_len, pdu->N_bytes); + } + } // end of holdering gw_mutex } running = false; logger.info("GW IP receiver thread exiting."); } - - /**************************/ /* TUN Interface Helpers */ /**************************/ From 8087bb01e402321185e2005caecaf3e591104b17 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 28 Jun 2021 10:03:00 +0200 Subject: [PATCH 34/43] nas: log message when airplane mode timer expires --- srsue/src/stack/upper/nas.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/srsue/src/stack/upper/nas.cc b/srsue/src/stack/upper/nas.cc index 7606e1343..1003da37a 100644 --- a/srsue/src/stack/upper/nas.cc +++ b/srsue/src/stack/upper/nas.cc @@ -229,6 +229,9 @@ void nas::timer_expired(uint32_t timeout_id) logger.warning("Reattach timer expired: trying to attach again"); start_attach_request(srsran::establishment_cause_t::mo_sig); } else if (timeout_id == airplane_mode_sim_timer.id()) { + logger.debug("Airplane mode simulation timer expired after %dms, airplane mode is currently %s.", + airplane_mode_sim_timer.time_elapsed(), + airplane_mode_state == DISABLED ? "disabled" : "enabled"); if (airplane_mode_state == DISABLED) { // Enabling air-plane mode send_detach_request(true); From a70ad58440a6839be81f59a2fb761bebd85863ff Mon Sep 17 00:00:00 2001 From: faluco Date: Mon, 28 Jun 2021 12:03:41 +0200 Subject: [PATCH 35/43] Fix a data race in the UHD class wrapper where the last error member was being set concurrently causing random crashes. Introduce a new macro to catch UHD exceptions and log them directly instead of storing an error string, similar to what errno does. Remove usrp logging helpers that depend on the now removed member since all calls potentially log the error directly. --- lib/src/phy/rf/rf_uhd_generic.h | 85 ++++++++++--------- lib/src/phy/rf/rf_uhd_imp.cc | 65 ++------------- lib/src/phy/rf/rf_uhd_rfnoc.h | 141 +++++++++++++------------------- lib/src/phy/rf/rf_uhd_safe.h | 52 ++++++++---- lib/src/phy/rf/rfnoc_test.cc | 5 -- 5 files changed, 139 insertions(+), 209 deletions(-) diff --git a/lib/src/phy/rf/rf_uhd_generic.h b/lib/src/phy/rf/rf_uhd_generic.h index b9d73a810..490bf947e 100644 --- a/lib/src/phy/rf/rf_uhd_generic.h +++ b/lib/src/phy/rf/rf_uhd_generic.h @@ -33,18 +33,18 @@ private: Debug("Making USRP object with args '" << dev_addr.to_string() << "'"); - UHD_SAFE_C_SAVE_ERROR(this, usrp = uhd::usrp::multi_usrp::make(dev_addr);) + SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp = uhd::usrp::multi_usrp::make(dev_addr);) } uhd_error set_tx_subdev(const std::string& string) { Info("Setting tx_subdev_spec to '" << string << "'"); - UHD_SAFE_C_SAVE_ERROR(this, usrp->set_tx_subdev_spec(string);) + SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp->set_tx_subdev_spec(string);) } uhd_error set_rx_subdev(const std::string& string) { Info("Setting rx_subdev_spec to '" << string << "'"); - UHD_SAFE_C_SAVE_ERROR(this, usrp->set_rx_subdev_spec(string);) + SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp->set_rx_subdev_spec(string);) } uhd_error test_ad936x_device(uint32_t nof_channels) @@ -92,7 +92,7 @@ private: } if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT) { - last_error = md.strerror(); + Error(md.strerror()); return UHD_ERROR_IO; } @@ -236,9 +236,8 @@ public: // Otherwise, close USRP and open again usrp = nullptr; - Warning("Failed to open Rx stream '" << last_error << "', trying to open device again. " << ntrials - << " trials left. Waiting for " << FE_RX_RESET_SLEEP_TIME_MS.count() - << " ms"); + Warning("Failed to open Rx stream, trying to open device again. " + << ntrials << " trials left. Waiting for " << FE_RX_RESET_SLEEP_TIME_MS.count() << " ms"); // Sleep std::this_thread::sleep_for(FE_RX_RESET_SLEEP_TIME_MS); @@ -254,103 +253,101 @@ public: uhd_error get_mboard_name(std::string& mboard_name) override { - UHD_SAFE_C_SAVE_ERROR(this, mboard_name = usrp->get_mboard_name();) + SRSRAN_UHD_SAFE_C_LOG_ERROR(mboard_name = usrp->get_mboard_name();) } uhd_error get_mboard_sensor_names(std::vector& sensors) override { - UHD_SAFE_C_SAVE_ERROR(this, sensors = usrp->get_mboard_sensor_names();) + SRSRAN_UHD_SAFE_C_LOG_ERROR(sensors = usrp->get_mboard_sensor_names();) } uhd_error get_rx_sensor_names(std::vector& sensors) override { - UHD_SAFE_C_SAVE_ERROR(this, sensors = usrp->get_rx_sensor_names();) + SRSRAN_UHD_SAFE_C_LOG_ERROR(sensors = usrp->get_rx_sensor_names();) } uhd_error get_sensor(const std::string& sensor_name, double& sensor_value) override { - UHD_SAFE_C_SAVE_ERROR(this, sensor_value = usrp->get_mboard_sensor(sensor_name).to_real();) + SRSRAN_UHD_SAFE_C_LOG_ERROR(sensor_value = usrp->get_mboard_sensor(sensor_name).to_real();) } uhd_error get_sensor(const std::string& sensor_name, bool& sensor_value) override { - UHD_SAFE_C_SAVE_ERROR(this, sensor_value = usrp->get_mboard_sensor(sensor_name).to_bool();) + SRSRAN_UHD_SAFE_C_LOG_ERROR(sensor_value = usrp->get_mboard_sensor(sensor_name).to_bool();) } uhd_error get_rx_sensor(const std::string& sensor_name, bool& sensor_value) override { - UHD_SAFE_C_SAVE_ERROR(this, sensor_value = usrp->get_rx_sensor(sensor_name).to_bool();) + SRSRAN_UHD_SAFE_C_LOG_ERROR(sensor_value = usrp->get_rx_sensor(sensor_name).to_bool();) } uhd_error set_time_unknown_pps(const uhd::time_spec_t& timespec) override { Debug("Setting Time at next PPS..."); - UHD_SAFE_C_SAVE_ERROR(this, usrp->set_time_unknown_pps(timespec);) + SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp->set_time_unknown_pps(timespec);) } uhd_error get_time_now(uhd::time_spec_t& timespec) override { - UHD_SAFE_C_SAVE_ERROR(this, timespec = usrp->get_time_now();) + SRSRAN_UHD_SAFE_C_LOG_ERROR(timespec = usrp->get_time_now();) } uhd_error set_sync_source(const std::string& sync_source, const std::string& clock_source) override { Debug("Setting PPS source to '" << sync_source << "' and clock source to '" << clock_source << "'"); #if UHD_VERSION < 3140099 - UHD_SAFE_C_SAVE_ERROR(this, usrp->set_clock_source(clock_source); usrp->set_time_source(sync_source);) + SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp->set_clock_source(clock_source); usrp->set_time_source(sync_source);) #else - UHD_SAFE_C_SAVE_ERROR(this, usrp->set_sync_source(clock_source, sync_source);) + SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp->set_sync_source(clock_source, sync_source);) #endif } uhd_error get_gain_range(uhd::gain_range_t& tx_gain_range, uhd::gain_range_t& rx_gain_range) override { - UHD_SAFE_C_SAVE_ERROR(this, tx_gain_range = usrp->get_tx_gain_range(); rx_gain_range = usrp->get_rx_gain_range();) + SRSRAN_UHD_SAFE_C_LOG_ERROR(tx_gain_range = usrp->get_tx_gain_range(); rx_gain_range = usrp->get_rx_gain_range();) } uhd_error set_master_clock_rate(double rate) override { Debug("Setting master clock rate to " << rate / 1e6 << " MHz"); - UHD_SAFE_C_SAVE_ERROR(this, usrp->set_master_clock_rate(rate);) + SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp->set_master_clock_rate(rate);) } uhd_error set_rx_rate(double rate) override { Debug("Setting Rx Rate to " << rate / 1e6 << "MHz"); - UHD_SAFE_C_SAVE_ERROR(this, usrp->set_rx_rate(rate);) + SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp->set_rx_rate(rate);) } uhd_error set_tx_rate(double rate) override { Debug("Setting Tx Rate to " << rate / 1e6 << "MHz"); - UHD_SAFE_C_SAVE_ERROR(this, usrp->set_tx_rate(rate);) + SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp->set_tx_rate(rate);) } uhd_error set_command_time(const uhd::time_spec_t& timespec) override { - UHD_SAFE_C_SAVE_ERROR(this, usrp->set_command_time(timespec);) + SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp->set_command_time(timespec);) } uhd_error get_rx_stream(size_t& max_num_samps) override { Debug("Creating Rx stream"); - UHD_SAFE_C_SAVE_ERROR( - this, rx_stream = nullptr; rx_stream = usrp->get_rx_stream(stream_args); - max_num_samps = rx_stream->get_max_num_samps(); - if (max_num_samps == 0UL) { - last_error = "The maximum number of receive samples is zero."; - return UHD_ERROR_VALUE; - }) + SRSRAN_UHD_SAFE_C_LOG_ERROR(rx_stream = nullptr; rx_stream = usrp->get_rx_stream(stream_args); + max_num_samps = rx_stream->get_max_num_samps(); + if (max_num_samps == 0UL) { + Error("The maximum number of receive samples is zero."); + return UHD_ERROR_VALUE; + }) } uhd_error get_tx_stream(size_t& max_num_samps) override { Debug("Creating Tx stream"); - UHD_SAFE_C_SAVE_ERROR( - this, tx_stream = nullptr; tx_stream = usrp->get_tx_stream(stream_args); - max_num_samps = tx_stream->get_max_num_samps(); - if (max_num_samps == 0UL) { - last_error = "The maximum number of transmit samples is zero."; - return UHD_ERROR_VALUE; - }) + SRSRAN_UHD_SAFE_C_LOG_ERROR(tx_stream = nullptr; tx_stream = usrp->get_tx_stream(stream_args); + max_num_samps = tx_stream->get_max_num_samps(); + if (max_num_samps == 0UL) { + Error("The maximum number of transmit samples is zero."); + return UHD_ERROR_VALUE; + }) } uhd_error set_tx_gain(size_t ch, double gain) override { Debug("Setting channel " << ch << " Tx gain to " << gain << " dB"); - UHD_SAFE_C_SAVE_ERROR(this, usrp->set_tx_gain(gain, ch);) + SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp->set_tx_gain(gain, ch);) } uhd_error set_rx_gain(size_t ch, double gain) override { Debug("Setting channel " << ch << " Rx gain to " << gain << " dB"); - UHD_SAFE_C_SAVE_ERROR(this, usrp->set_rx_gain(gain, ch);) + SRSRAN_UHD_SAFE_C_LOG_ERROR(usrp->set_rx_gain(gain, ch);) } - uhd_error get_rx_gain(double& gain) override { UHD_SAFE_C_SAVE_ERROR(this, gain = usrp->get_rx_gain();) } - uhd_error get_tx_gain(double& gain) override { UHD_SAFE_C_SAVE_ERROR(this, gain = usrp->get_tx_gain();) } + uhd_error get_rx_gain(double& gain) override { SRSRAN_UHD_SAFE_C_LOG_ERROR(gain = usrp->get_rx_gain();) } + uhd_error get_tx_gain(double& gain) override { SRSRAN_UHD_SAFE_C_LOG_ERROR(gain = usrp->get_tx_gain();) } uhd_error set_tx_freq(uint32_t ch, double target_freq, double& actual_freq) override { Debug("Setting channel " << ch << " Tx frequency to " << target_freq / 1e6 << " MHz"); @@ -369,8 +366,8 @@ public: tune_request.dsp_freq_policy = uhd::tune_request_t::POLICY_AUTO; } - UHD_SAFE_C_SAVE_ERROR(this, uhd::tune_result_t tune_result = usrp->set_tx_freq(tune_request, ch); - actual_freq = tune_result.target_rf_freq;) + SRSRAN_UHD_SAFE_C_LOG_ERROR(uhd::tune_result_t tune_result = usrp->set_tx_freq(tune_request, ch); + actual_freq = tune_result.target_rf_freq;) } uhd_error set_rx_freq(uint32_t ch, double target_freq, double& actual_freq) override { @@ -390,8 +387,8 @@ public: tune_request.dsp_freq_policy = uhd::tune_request_t::POLICY_AUTO; } - UHD_SAFE_C_SAVE_ERROR(this, uhd::tune_result_t tune_result = usrp->set_rx_freq(tune_request, ch); - actual_freq = tune_result.target_rf_freq;) + SRSRAN_UHD_SAFE_C_LOG_ERROR(uhd::tune_result_t tune_result = usrp->set_rx_freq(tune_request, ch); + actual_freq = tune_result.target_rf_freq;) } }; diff --git a/lib/src/phy/rf/rf_uhd_imp.cc b/lib/src/phy/rf/rf_uhd_imp.cc index 32ca0e25a..b9447f415 100644 --- a/lib/src/phy/rf/rf_uhd_imp.cc +++ b/lib/src/phy/rf/rf_uhd_imp.cc @@ -190,11 +190,6 @@ void suppress_handler(const char* x) static cf_t zero_mem[64 * 1024] = {}; -#define print_usrp_error(h) \ - do { \ - ERROR("USRP reported the following error: %s", h->uhd->last_error.c_str()); \ - } while (false) - static void log_overflow(rf_uhd_handler_t* h) { if (h->tx_state == RF_UHD_IMP_TX_STATE_BURST) { @@ -243,8 +238,6 @@ static void log_underflow(rf_uhd_handler_t* h) static void log_rx_error(rf_uhd_handler_t* h) { if (h->uhd_error_handler) { - ERROR("USRP reported the following error: %s", h->uhd->last_error.c_str()); - srsran_rf_error_t error; bzero(&error, sizeof(srsran_rf_error_t)); error.type = srsran_rf_error_t::SRSRAN_RF_ERROR_RX; @@ -272,7 +265,6 @@ static void* async_thread(void* h) if (handler->uhd->is_tx_ready()) { lock.unlock(); if (handler->uhd->recv_async_msg(md, RF_UHD_IMP_ASYNCH_MSG_TIMEOUT_S, valid) != UHD_ERROR_NONE) { - print_usrp_error(handler); return nullptr; } @@ -369,7 +361,6 @@ static int set_time_to_gps_time(rf_uhd_handler_t* handler) std::vector sensors; if (handler->uhd->get_mboard_sensor_names(sensors) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } @@ -395,14 +386,12 @@ static int set_time_to_gps_time(rf_uhd_handler_t* handler) // Get actual sensor value double frac_secs = 0.0; if (handler->uhd->get_sensor(sensor_name, frac_secs) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } // Get time and set printf("Setting USRP time to %fs\n", frac_secs); if (handler->uhd->set_time_unknown_pps(uhd::time_spec_t(frac_secs)) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } @@ -423,13 +412,11 @@ static int wait_sensor_locked(rf_uhd_handler_t* handler, if (is_mboard) { // motherboard sensor if (handler->uhd->get_mboard_sensor_names(sensors) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } } else { // daughterboard sensor if (handler->uhd->get_rx_sensor_names(sensors) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } } @@ -457,12 +444,10 @@ static int wait_sensor_locked(rf_uhd_handler_t* handler, // Get actual sensor value if (is_mboard) { if (handler->uhd->get_sensor(sensor_name, is_locked) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } } else { if (handler->uhd->get_rx_sensor(sensor_name, is_locked) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } } @@ -510,7 +495,6 @@ static inline int rf_uhd_start_rx_stream_unsafe(rf_uhd_handler_t* handler) // Issue stream command if (handler->uhd->start_rx_stream(RF_UHD_IMP_STREAM_DELAY_S) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } @@ -537,7 +521,6 @@ static inline int rf_uhd_stop_rx_stream_unsafe(rf_uhd_handler_t* handler) // Issue stream command if (handler->uhd->stop_rx_stream() != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } @@ -579,7 +562,6 @@ void rf_uhd_flush_buffer(void* h) do { if (handler->uhd->receive(data, handler->rx_nof_samples, md, 0.0, false, rxd_samples) != UHD_ERROR_NONE) { log_rx_error(handler); - print_usrp_error(handler); return; } } while (rxd_samples > 0 and md.error_code == uhd::rx_metadata_t::ERROR_CODE_NONE); @@ -764,7 +746,6 @@ static int uhd_init(rf_uhd_handler_t* handler, char* args, uint32_t nof_channels // Make USRP if (handler->uhd->usrp_make(device_addr, nof_channels) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } @@ -785,7 +766,6 @@ static int uhd_init(rf_uhd_handler_t* handler, char* args, uint32_t nof_channels if (handler->devname.empty()) { std::string mboard_name; if (handler->uhd->get_mboard_name(mboard_name) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } @@ -810,7 +790,6 @@ static int uhd_init(rf_uhd_handler_t* handler, char* args, uint32_t nof_channels // Set sync source if (handler->uhd->set_sync_source(sync_src, clock_src) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } @@ -837,11 +816,9 @@ static int uhd_init(rf_uhd_handler_t* handler, char* args, uint32_t nof_channels // Set default Tx/Rx rates if (handler->uhd->set_rx_rate(handler->rx_rate) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } if (handler->uhd->set_tx_rate(handler->tx_rate) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } @@ -851,12 +828,10 @@ static int uhd_init(rf_uhd_handler_t* handler, char* args, uint32_t nof_channels } if (handler->uhd->get_rx_stream(handler->rx_nof_samples) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } if (handler->uhd->get_tx_stream(handler->tx_nof_samples) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } @@ -865,7 +840,6 @@ static int uhd_init(rf_uhd_handler_t* handler, char* args, uint32_t nof_channels for (uint32_t i = 0; i < nof_channels; i++) { if (std::isnormal(handler->rx_freq[i])) { if (handler->uhd->set_rx_freq(i, handler->rx_freq[i], handler->rx_freq[i]) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } rf_uhd_rx_wait_lo_locked(handler); @@ -875,7 +849,6 @@ static int uhd_init(rf_uhd_handler_t* handler, char* args, uint32_t nof_channels for (uint32_t i = 0; i < nof_channels; i++) { if (std::isnormal(handler->tx_freq[i])) { if (handler->uhd->set_tx_freq(i, handler->tx_freq[i], handler->tx_freq[i]) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } } @@ -885,7 +858,6 @@ static int uhd_init(rf_uhd_handler_t* handler, char* args, uint32_t nof_channels uhd::gain_range_t tx_gain_range; uhd::gain_range_t rx_gain_range; if (handler->uhd->get_gain_range(tx_gain_range, rx_gain_range) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } handler->info.min_tx_gain = tx_gain_range.start(); @@ -906,7 +878,6 @@ static int uhd_init(rf_uhd_handler_t* handler, char* args, uint32_t nof_channels // Restore priorities if (uhd_set_thread_priority(0, false) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } @@ -965,9 +936,7 @@ static inline void rf_uhd_set_master_clock_rate_unsafe(rf_uhd_handler_t* handler { // Set master clock rate if it is allowed and change is required if (handler->dynamic_master_rate and handler->current_master_clock != rate) { - if (handler->uhd->set_master_clock_rate(rate) != UHD_ERROR_NONE) { - print_usrp_error(handler); - } + handler->uhd->set_master_clock_rate(rate); handler->current_master_clock = rate; } } @@ -990,7 +959,6 @@ static inline int rf_uhd_imp_end_burst(rf_uhd_handler_t* handler) // Actual base-band transmission if (handler->uhd->send(buffs_ptr, 0, md, RF_UHD_IMP_TRX_TIMEOUT_S, txd_samples) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } @@ -1025,7 +993,6 @@ double rf_uhd_set_rx_srate(void* h, double freq) if (handler->nof_rx_channels > 1) { uhd::time_spec_t timespec; if (handler->uhd->get_time_now(timespec) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } timespec += RF_UHD_IMP_TIMED_COMMAND_DELAY_S; @@ -1034,13 +1001,11 @@ double rf_uhd_set_rx_srate(void* h, double freq) // Set RX rate if (handler->uhd->set_rx_rate(freq) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } if (RF_UHD_IMP_PROHIBITED_STREAM_REMAKE.count(handler->devname) == 0) { if (handler->uhd->get_rx_stream(handler->rx_nof_samples) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } } @@ -1079,7 +1044,6 @@ double rf_uhd_set_tx_srate(void* h, double freq) if (handler->nof_tx_channels > 1) { uhd::time_spec_t timespec; if (handler->uhd->get_time_now(timespec) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } timespec += RF_UHD_IMP_TIMED_COMMAND_DELAY_S; @@ -1088,13 +1052,11 @@ double rf_uhd_set_tx_srate(void* h, double freq) // Set TX rate if (handler->uhd->set_tx_rate(freq) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } if (RF_UHD_IMP_PROHIBITED_STREAM_REMAKE.count(handler->devname) == 0) { if (handler->uhd->get_tx_stream(handler->tx_nof_samples) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } } @@ -1114,7 +1076,6 @@ int rf_uhd_set_rx_gain(void* h, double gain) rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; for (size_t i = 0; i < handler->nof_rx_channels; i++) { if (rf_uhd_set_rx_gain_ch(h, i, gain)) { - print_usrp_error(handler); return SRSRAN_ERROR; } } @@ -1125,7 +1086,6 @@ int rf_uhd_set_rx_gain_ch(void* h, uint32_t ch, double gain) { rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; if (handler->uhd->set_rx_gain(ch, gain) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } return SRSRAN_SUCCESS; @@ -1136,7 +1096,6 @@ int rf_uhd_set_tx_gain(void* h, double gain) rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; for (size_t i = 0; i < handler->nof_tx_channels; i++) { if (rf_uhd_set_tx_gain_ch(h, i, gain)) { - print_usrp_error(handler); return SRSRAN_ERROR; } } @@ -1147,7 +1106,6 @@ int rf_uhd_set_tx_gain_ch(void* h, uint32_t ch, double gain) { rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; if (handler->uhd->set_tx_gain(ch, gain) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } return SRSRAN_SUCCESS; @@ -1159,7 +1117,6 @@ double rf_uhd_get_rx_gain(void* h) double gain = 0.0; if (handler->uhd->get_rx_gain(gain) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } @@ -1172,7 +1129,6 @@ double rf_uhd_get_tx_gain(void* h) double gain = 0.0; if (handler->uhd->get_tx_gain(gain) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } @@ -1201,13 +1157,9 @@ static bool rf_uhd_set_freq_ch(rf_uhd_handler_t* handler, uint32_t ch, double& f // Set frequency if (is_tx) { - if (handler->uhd->set_tx_freq(ch, freq, curr_freq) != UHD_ERROR_NONE) { - print_usrp_error(handler); - } + handler->uhd->set_tx_freq(ch, freq, curr_freq); } else { - if (handler->uhd->set_rx_freq(ch, freq, curr_freq) != UHD_ERROR_NONE) { - print_usrp_error(handler); - } + handler->uhd->set_rx_freq(ch, freq, curr_freq); } return true; } @@ -1251,9 +1203,7 @@ void rf_uhd_get_time(void* h, time_t* secs, double* frac_secs) { rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; uhd::time_spec_t timespec; - if (handler->uhd->get_time_now(timespec) != UHD_ERROR_NONE) { - print_usrp_error(handler); - } + handler->uhd->get_time_now(timespec); if (secs != nullptr) { *secs = timespec.get_full_secs(); } @@ -1271,9 +1221,7 @@ void rf_uhd_sync_pps(void* h) rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; uhd::time_spec_t timespec(0.0); - if (handler->uhd->set_time_unknown_pps(timespec) != UHD_ERROR_NONE) { - print_usrp_error(handler); - } + handler->uhd->set_time_unknown_pps(timespec); } int rf_uhd_recv_with_time(void* h, void* data, uint32_t nsamples, bool blocking, time_t* secs, double* frac_secs) @@ -1323,7 +1271,6 @@ int rf_uhd_recv_with_time_multi(void* h, if (handler->uhd->receive(buffs_ptr, num_rx_samples, md, 1.0, false, rxd_samples) != UHD_ERROR_NONE) { log_rx_error(handler); - print_usrp_error(handler); return SRSRAN_ERROR; } @@ -1417,7 +1364,6 @@ int rf_uhd_send_timed_multi(void* h, if (is_start_of_burst) { // It gets the USRP time for transmissions without time if (handler->uhd->get_time_now(md.time_spec) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } @@ -1499,7 +1445,6 @@ int rf_uhd_send_timed_multi(void* h, if (handler->tx_state != RF_UHD_IMP_TX_STATE_WAIT_EOB_ACK) { // Actual transmission if (handler->uhd->send(buffs_ptr, tx_samples, md, RF_UHD_IMP_TRX_TIMEOUT_S, txd_samples) != UHD_ERROR_NONE) { - print_usrp_error(handler); return SRSRAN_ERROR; } diff --git a/lib/src/phy/rf/rf_uhd_rfnoc.h b/lib/src/phy/rf/rf_uhd_rfnoc.h index 84b19b26b..c19ba9481 100644 --- a/lib/src/phy/rf/rf_uhd_rfnoc.h +++ b/lib/src/phy/rf/rf_uhd_rfnoc.h @@ -99,17 +99,16 @@ private: // Destroy any previous USRP instance device3 = nullptr; - UHD_SAFE_C_SAVE_ERROR(this, device3 = uhd::device3::make(dev_addr);) + SRSRAN_UHD_SAFE_C_LOG_ERROR(device3 = uhd::device3::make(dev_addr);) } template uhd_error parse_param(uhd::device_addr_t& args, const std::string& param, T& value, bool pop = true) { - UHD_SAFE_C_SAVE_ERROR( - this, + SRSRAN_UHD_SAFE_C_LOG_ERROR( // Check if parameter exists if (not args.has_key(param)) { - last_error = "RF-NOC requires " + param + " parameter"; + Error("RF-NOC requires " + param + " parameter"); return UHD_ERROR_KEY; } @@ -135,14 +134,14 @@ private: // Parse number of radios parse_param(args, "rfnoc_nof_radios", nof_radios); if (nof_radios == 0) { - last_error = "RF-NOC Number of radios cannot be zero"; + Error("RF-NOC Number of radios cannot be zero"); return UHD_ERROR_KEY; } // Parse number of channels per radio parse_param(args, "rfnoc_nof_channels", nof_channels); if (nof_channels == 0) { - last_error = "RF-NOC Number of channels cannot be zero"; + Error("RF-NOC Number of channels cannot be zero"); return UHD_ERROR_KEY; } @@ -158,8 +157,7 @@ private: uhd_error create_control_interfaces() { - UHD_SAFE_C_SAVE_ERROR( - this, + SRSRAN_UHD_SAFE_C_LOG_ERROR( // Create Radio control if (not loopback) { radio_ctrl.resize(nof_radios); @@ -316,9 +314,7 @@ private: nof_samples_per_packet = spp * 4 + 2 * sizeof(uint64_t); } - UHD_SAFE_C_SAVE_ERROR( - this, - + SRSRAN_UHD_SAFE_C_LOG_ERROR( // Get Tx and Rx Graph graph = device3->create_graph("graph"); @@ -358,9 +354,7 @@ private: nof_samples_per_packet = spp * 4 + 2 * sizeof(uint64_t); } - UHD_SAFE_C_SAVE_ERROR( - this, - + SRSRAN_UHD_SAFE_C_LOG_ERROR( // Get Tx and Rx Graph graph = device3->create_graph("graph"); @@ -416,10 +410,10 @@ public: // Check number of channels if (nof_channels_ % nof_channels != 0 or nof_channels_ / nof_channels > nof_radios) { - last_error = "Number of requested channels (" + std::to_string(nof_channels_) + - ") is different than the RFNOC " - "available channels (" + - std::to_string(nof_radios * nof_channels) + ")"; + Error("Number of requested channels (" + std::to_string(nof_channels_) + + ") is different than the RFNOC " + "available channels (" + + std::to_string(nof_radios * nof_channels) + ")"); return UHD_ERROR_VALUE; } @@ -461,49 +455,41 @@ public: }; uhd_error get_mboard_sensor_names(std::vector& sensors) override { - UHD_SAFE_C_SAVE_ERROR( - this, if (device3->get_tree()->exists(TREE_MBOARD_SENSORS)) { - sensors = device3->get_tree()->list(TREE_MBOARD_SENSORS); - }) + SRSRAN_UHD_SAFE_C_LOG_ERROR(if (device3->get_tree()->exists(TREE_MBOARD_SENSORS)) { + sensors = device3->get_tree()->list(TREE_MBOARD_SENSORS); + }) } uhd_error get_rx_sensor_names(std::vector& sensors) override { - UHD_SAFE_C_SAVE_ERROR( - this, + SRSRAN_UHD_SAFE_C_LOG_ERROR( if (device3->get_tree()->exists(TREE_RX_SENSORS)) { sensors = device3->get_tree()->list(TREE_RX_SENSORS); }) } uhd_error get_sensor(const std::string& sensor_name, double& sensor_value) override { - UHD_SAFE_C_SAVE_ERROR( - this, + SRSRAN_UHD_SAFE_C_LOG_ERROR( sensor_value = device3->get_tree()->access(TREE_MBOARD_SENSORS / sensor_name).get().to_real();) } uhd_error get_sensor(const std::string& sensor_name, bool& sensor_value) override { - UHD_SAFE_C_SAVE_ERROR( - this, + SRSRAN_UHD_SAFE_C_LOG_ERROR( sensor_value = device3->get_tree()->access(TREE_MBOARD_SENSORS / sensor_name).get().to_bool();) } uhd_error get_rx_sensor(const std::string& sensor_name, bool& sensor_value) override { - UHD_SAFE_C_SAVE_ERROR( - this, + SRSRAN_UHD_SAFE_C_LOG_ERROR( sensor_value = device3->get_tree()->access(TREE_RX_SENSORS / sensor_name).get().to_bool();) } uhd_error set_time_unknown_pps(const uhd::time_spec_t& timespec) override { Info("Setting time " << timespec.get_real_secs() << " at next PPS..."); - UHD_SAFE_C_SAVE_ERROR( - this, - for (auto& r - : radio_ctrl) { r->set_time_next_pps(timespec); }); + SRSRAN_UHD_SAFE_C_LOG_ERROR(for (auto& r : radio_ctrl) { r->set_time_next_pps(timespec); }); } uhd_error get_time_now(uhd::time_spec_t& timespec) override { - UHD_SAFE_C_SAVE_ERROR(this, timespec = device3->get_tree()->access(TREE_TIME_NOW).get(); - Info("-- " << timespec.get_real_secs());) + SRSRAN_UHD_SAFE_C_LOG_ERROR(timespec = device3->get_tree()->access(TREE_TIME_NOW).get(); + Info("-- " << timespec.get_real_secs());) } uhd_error set_sync_source(const std::string& sync_source, const std::string& clock_source) override { @@ -511,13 +497,12 @@ public: return UHD_ERROR_NONE; } - UHD_SAFE_C_SAVE_ERROR( - this, for (size_t radio_idx = 0; radio_idx < nof_radios; radio_idx++) { - UHD_LOG_DEBUG(radio_id[radio_idx], - "Setting PPS source to '" << sync_source << "' and clock source to '" << clock_source << "'"); - radio_ctrl[radio_idx]->set_clock_source(clock_source); - radio_ctrl[radio_idx]->set_time_source(sync_source); - }) + SRSRAN_UHD_SAFE_C_LOG_ERROR(for (size_t radio_idx = 0; radio_idx < nof_radios; radio_idx++) { + UHD_LOG_DEBUG(radio_id[radio_idx], + "Setting PPS source to '" << sync_source << "' and clock source to '" << clock_source << "'"); + radio_ctrl[radio_idx]->set_clock_source(clock_source); + radio_ctrl[radio_idx]->set_time_source(sync_source); + }) } uhd_error get_gain_range(uhd::gain_range_t& tx_gain_range, uhd::gain_range_t& rx_gain_range) override { @@ -529,29 +514,27 @@ public: uhd_error set_master_clock_rate(double rate) override { return UHD_ERROR_NONE; } uhd_error set_rx_rate(double rate) override { - UHD_SAFE_C_SAVE_ERROR( - this, for (size_t i = 0; i < nof_radios; i++) { - for (size_t j = 0; j < nof_channels; j++) { - UHD_LOG_DEBUG(ddc_id[i], "Setting channel " << j << " output rate to " << rate / 1e6 << " MHz"); - ddc_ctrl[i]->set_arg("output_rate", std::to_string(rate), j); - } - }) + SRSRAN_UHD_SAFE_C_LOG_ERROR(for (size_t i = 0; i < nof_radios; i++) { + for (size_t j = 0; j < nof_channels; j++) { + UHD_LOG_DEBUG(ddc_id[i], "Setting channel " << j << " output rate to " << rate / 1e6 << " MHz"); + ddc_ctrl[i]->set_arg("output_rate", std::to_string(rate), j); + } + }) } uhd_error set_tx_rate(double rate) override { - UHD_SAFE_C_SAVE_ERROR( - this, for (size_t i = 0; i < nof_radios; i++) { - for (size_t j = 0; j < nof_channels; j++) { - UHD_LOG_DEBUG(duc_id[i], "Setting channel " << j << " input rate to " << rate / 1e6 << " MHz"); - duc_ctrl[i]->set_arg("input_rate", std::to_string(rate), j); - } - }) + SRSRAN_UHD_SAFE_C_LOG_ERROR(for (size_t i = 0; i < nof_radios; i++) { + for (size_t j = 0; j < nof_channels; j++) { + UHD_LOG_DEBUG(duc_id[i], "Setting channel " << j << " input rate to " << rate / 1e6 << " MHz"); + duc_ctrl[i]->set_arg("input_rate", std::to_string(rate), j); + } + }) } uhd_error set_command_time(const uhd::time_spec_t& timespec) override { return UHD_ERROR_NONE; } uhd_error get_rx_stream(size_t& max_num_samps) override { - UHD_SAFE_C_SAVE_ERROR( - this, uhd::stream_args_t stream_args("fc32", "sc16"); + SRSRAN_UHD_SAFE_C_LOG_ERROR( + uhd::stream_args_t stream_args("fc32", "sc16"); stream_args.channels.resize(nof_radios * nof_channels); @@ -575,8 +558,8 @@ public: } uhd_error get_tx_stream(size_t& max_num_samps) override { - UHD_SAFE_C_SAVE_ERROR( - this, uhd::stream_args_t stream_args("fc32", "sc16"); + SRSRAN_UHD_SAFE_C_LOG_ERROR( + uhd::stream_args_t stream_args("fc32", "sc16"); stream_args.channels.resize(nof_radios * nof_channels); if (spp != 0) { stream_args.args["spp"] = std::to_string(spp); } @@ -605,7 +588,7 @@ public: uhd_error set_tx_gain(size_t ch, double gain) override { if (ch >= nof_channels * nof_radios) { - last_error = "Invalid channel index " + std::to_string(ch); + Error("Invalid channel index " + std::to_string(ch)); return UHD_ERROR_INDEX; } @@ -618,12 +601,11 @@ public: // Set the gain for the channel zero only if (channel_idx != 0) { - last_error = "None"; return UHD_ERROR_NONE; } - UHD_SAFE_C_SAVE_ERROR( - this, UHD_LOG_DEBUG(radio_id[radio_idx], "Setting TX Gain: " << gain << " dB..."); + SRSRAN_UHD_SAFE_C_LOG_ERROR( + UHD_LOG_DEBUG(radio_id[radio_idx], "Setting TX Gain: " << gain << " dB..."); radio_ctrl[radio_idx]->set_tx_gain(gain, 0); UHD_LOG_DEBUG(radio_id[radio_idx], "Actual TX Gain: " << radio_ctrl[radio_idx]->get_rx_gain(0) << " dB...");) } @@ -631,7 +613,7 @@ public: uhd_error set_rx_gain(size_t ch, double gain) override { if (ch >= nof_channels * nof_radios) { - last_error = "Invalid channel index " + std::to_string(ch); + Error("Invalid channel index " + std::to_string(ch)); return UHD_ERROR_INDEX; } @@ -644,12 +626,11 @@ public: // Set the gain for the channel zero only if (channel_idx != 0) { - last_error = "None"; return UHD_ERROR_NONE; } - UHD_SAFE_C_SAVE_ERROR( - this, UHD_LOG_DEBUG(radio_id[radio_idx], "Setting RX Gain: " << gain << " dB..."); + SRSRAN_UHD_SAFE_C_LOG_ERROR( + UHD_LOG_DEBUG(radio_id[radio_idx], "Setting RX Gain: " << gain << " dB..."); radio_ctrl[radio_idx]->set_rx_gain(gain, 0); UHD_LOG_DEBUG(radio_id[radio_idx], "Actual RX Gain: " << radio_ctrl[radio_idx]->get_rx_gain(0) << " dB...");) } @@ -659,7 +640,7 @@ public: return UHD_ERROR_NONE; } - UHD_SAFE_C_SAVE_ERROR(this, gain = radio_ctrl[0]->get_tx_gain(0);) + SRSRAN_UHD_SAFE_C_LOG_ERROR(gain = radio_ctrl[0]->get_tx_gain(0);) } uhd_error get_rx_gain(double& gain) override { @@ -667,23 +648,22 @@ public: return UHD_ERROR_NONE; } - UHD_SAFE_C_SAVE_ERROR(this, gain = radio_ctrl[0]->get_rx_gain(0);) + SRSRAN_UHD_SAFE_C_LOG_ERROR(gain = radio_ctrl[0]->get_rx_gain(0);) } uhd_error set_tx_freq(uint32_t ch, double target_freq, double& actual_freq) override { if (ch >= tx_freq_hz.size()) { - last_error = "Invalid channel index " + std::to_string(ch); + Error("Invalid channel index " + std::to_string(ch)); return UHD_ERROR_INDEX; } if (not std::isnormal(target_freq)) { - last_error = "Invalid TX frequency value " + std::to_string(target_freq) + " for channel " + std::to_string(ch); + Error("Invalid TX frequency value " + std::to_string(target_freq) + " for channel " + std::to_string(ch)); return UHD_ERROR_VALUE; } // Nothing to update if (std::round(tx_freq_hz[ch]) == std::round(target_freq)) { - last_error = "None"; return UHD_ERROR_NONE; } @@ -695,9 +675,7 @@ public: size_t i = ch / nof_channels; size_t j = ch % nof_channels; - UHD_SAFE_C_SAVE_ERROR( - this, - + SRSRAN_UHD_SAFE_C_LOG_ERROR( // Set Radio Tx freq if (not std::isnormal(tx_center_freq_hz[i]) and not loopback) { UHD_LOG_DEBUG(radio_id[i], @@ -722,18 +700,17 @@ public: uhd_error set_rx_freq(uint32_t ch, double target_freq, double& actual_freq) override { if (ch >= rx_freq_hz.size()) { - last_error = "Invalid channel index " + std::to_string(ch); + Error("Invalid channel index " + std::to_string(ch)); return UHD_ERROR_INDEX; } if (not std::isnormal(target_freq)) { - last_error = "Invalid TX frequency value " + std::to_string(target_freq) + " for channel " + std::to_string(ch); + Error("Invalid TX frequency value " + std::to_string(target_freq) + " for channel " + std::to_string(ch)); return UHD_ERROR_VALUE; } // Nothing to update if (std::round(rx_freq_hz[ch]) == std::round(target_freq)) { - last_error = "None"; return UHD_ERROR_NONE; } @@ -745,9 +722,7 @@ public: size_t i = ch / nof_channels; size_t j = ch % nof_channels; - UHD_SAFE_C_SAVE_ERROR( - this, - + SRSRAN_UHD_SAFE_C_LOG_ERROR( // Set Radio Tx freq if (not std::isnormal(rx_center_freq_hz[i]) and not loopback) { UHD_LOG_DEBUG(radio_id[i], "Setting RX Freq: " << target_freq / 1e6 << " MHz..."); diff --git a/lib/src/phy/rf/rf_uhd_safe.h b/lib/src/phy/rf/rf_uhd_safe.h index d9e7f862e..f2aa3b722 100644 --- a/lib/src/phy/rf/rf_uhd_safe.h +++ b/lib/src/phy/rf/rf_uhd_safe.h @@ -16,17 +16,37 @@ #include #ifdef UHD_LOG_INFO +#define Error(message) UHD_LOG_ERROR("UHD RF", message) #define Warning(message) UHD_LOG_WARNING("UHD RF", message) #define Info(message) UHD_LOG_INFO("UHD RF", message) #define Debug(message) UHD_LOG_DEBUG("UHD RF", message) #define Trace(message) UHD_LOG_TRACE("UHD RF", message) #else +#define Error(message) UHD_LOG << message << std::endl #define Warning(message) UHD_LOG << message << std::endl #define Info(message) UHD_LOG << message << std::endl #define Debug(message) UHD_LOG << message << std::endl #define Trace(message) UHD_LOG << message << std::endl #endif +#define SRSRAN_UHD_SAFE_C_LOG_ERROR(...) \ + try { \ + __VA_ARGS__ \ + } catch (const uhd::exception& e) { \ + Error(e.what()); \ + return error_from_uhd_exception(&e); \ + } catch (const boost::exception& e) { \ + Error(boost::diagnostic_information(e)); \ + return UHD_ERROR_BOOSTEXCEPT; \ + } catch (const std::exception& e) { \ + Error(e.what()); \ + return UHD_ERROR_STDEXCEPT; \ + } catch (...) { \ + Error("Unrecognized exception caught."); \ + return UHD_ERROR_UNKNOWN; \ + } \ + return UHD_ERROR_NONE; + #ifdef ENABLE_UHD_X300_FW_RESET #include @@ -45,8 +65,7 @@ private: #ifdef ENABLE_UHD_X300_FW_RESET uhd_error try_usrp_x300_reset(const uhd::device_addr_t& dev_addr) { - UHD_SAFE_C_SAVE_ERROR( - this, + SRSRAN_UHD_SAFE_C_LOG_ERROR( // It is not possible to reset device if IP address is not provided if (not dev_addr.has_key("addr")) { return UHD_ERROR_NONE; } @@ -109,8 +128,6 @@ protected: } public: - std::string last_error; - virtual uhd_error usrp_make(const uhd::device_addr_t& dev_addr, uint32_t nof_channels) = 0; virtual uhd_error get_mboard_name(std::string& mboard_name) = 0; virtual uhd_error get_mboard_sensor_names(std::vector& sensors) = 0; @@ -129,19 +146,19 @@ public: return err; } - UHD_SAFE_C_SAVE_ERROR(this, uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); - stream_cmd.time_spec = time_spec; - stream_cmd.time_spec += delay; - stream_cmd.stream_now = not std::isnormal(delay); + SRSRAN_UHD_SAFE_C_LOG_ERROR(uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); + stream_cmd.time_spec = time_spec; + stream_cmd.time_spec += delay; + stream_cmd.stream_now = not std::isnormal(delay); - rx_stream->issue_stream_cmd(stream_cmd);) + rx_stream->issue_stream_cmd(stream_cmd);) } uhd_error stop_rx_stream() { Debug("Stopping Rx stream"); - UHD_SAFE_C_SAVE_ERROR(this, uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); - stream_cmd.stream_now = true; - rx_stream->issue_stream_cmd(stream_cmd);) + SRSRAN_UHD_SAFE_C_LOG_ERROR(uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); + stream_cmd.stream_now = true; + rx_stream->issue_stream_cmd(stream_cmd);) } virtual uhd_error set_sync_source(const std::string& sync_source, const std::string& clock_source) = 0; virtual uhd_error get_gain_range(uhd::gain_range_t& tx_gain_range, uhd::gain_range_t& rx_gain_range) = 0; @@ -164,12 +181,13 @@ public: const bool one_packet, size_t& nof_rxd_samples) { - UHD_SAFE_C_SAVE_ERROR(this, uhd::rx_streamer::buffs_type buffs_cpp(buffs, rx_stream->get_num_channels()); - nof_rxd_samples = rx_stream->recv(buffs_cpp, nsamps_per_buff, metadata, timeout, one_packet);) + SRSRAN_UHD_SAFE_C_LOG_ERROR(uhd::rx_streamer::buffs_type buffs_cpp(buffs, rx_stream->get_num_channels()); + nof_rxd_samples = + rx_stream->recv(buffs_cpp, nsamps_per_buff, metadata, timeout, one_packet);) } virtual uhd_error recv_async_msg(uhd::async_metadata_t& async_metadata, double timeout, bool& valid) { - UHD_SAFE_C_SAVE_ERROR(this, valid = tx_stream->recv_async_msg(async_metadata, timeout);) + SRSRAN_UHD_SAFE_C_LOG_ERROR(valid = tx_stream->recv_async_msg(async_metadata, timeout);) } uhd_error send(void** buffs, const size_t nsamps_per_buff, @@ -177,8 +195,8 @@ public: const double timeout, size_t& nof_txd_samples) { - UHD_SAFE_C_SAVE_ERROR(this, uhd::tx_streamer::buffs_type buffs_cpp(buffs, tx_stream->get_num_channels()); - nof_txd_samples = tx_stream->send(buffs_cpp, nsamps_per_buff, metadata, timeout);) + SRSRAN_UHD_SAFE_C_LOG_ERROR(uhd::tx_streamer::buffs_type buffs_cpp(buffs, tx_stream->get_num_channels()); + nof_txd_samples = tx_stream->send(buffs_cpp, nsamps_per_buff, metadata, timeout);) } virtual bool is_rx_ready() { return rx_stream != nullptr; } virtual bool is_tx_ready() { return tx_stream != nullptr; } diff --git a/lib/src/phy/rf/rfnoc_test.cc b/lib/src/phy/rf/rfnoc_test.cc index 1b3a3a59d..1854f1fd7 100644 --- a/lib/src/phy/rf/rfnoc_test.cc +++ b/lib/src/phy/rf/rfnoc_test.cc @@ -88,7 +88,6 @@ private: if (valid) { switch (async_metadata.event_code) { - case uhd::async_metadata_t::EVENT_CODE_BURST_ACK: Warning("BURST ACK") break; case uhd::async_metadata_t::EVENT_CODE_UNDERFLOW: @@ -223,16 +222,13 @@ public: uhd::log::set_console_level(uhd::log::severity_level::trace); if (rfnoc->usrp_make(hint, config.nof_channels * config.nof_radios) != UHD_ERROR_NONE) { - Warning(rfnoc->last_error); return SRSRAN_ERROR; } if (rfnoc->set_tx_rate(config.srate_hz) != UHD_ERROR_NONE) { - Warning(rfnoc->last_error); return SRSRAN_ERROR; } if (rfnoc->set_rx_rate(config.srate_hz) != UHD_ERROR_NONE) { - Warning(rfnoc->last_error); return SRSRAN_ERROR; } @@ -248,7 +244,6 @@ public: } if (rfnoc->start_rx_stream(config.init_tx_time) != UHD_ERROR_NONE) { - Warning(rfnoc->last_error); return SRSRAN_ERROR; } From 5b3c5ded638693c37dcee6eb6681859239f262e8 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 25 Jun 2021 19:58:10 +0100 Subject: [PATCH 36/43] sched,nr: implement NR PDCCH allocation algorithm --- srsenb/hdr/stack/mac/nr/sched_nr_common.h | 14 +- srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 27 ++- srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h | 103 +++++++++++ srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h | 98 ++++------ srsenb/hdr/stack/mac/nr/sched_nr_ue.h | 41 ++++- srsenb/hdr/stack/mac/nr/sched_nr_worker.h | 10 +- srsenb/hdr/stack/mac/sched_common.h | 106 ++++------- srsenb/hdr/stack/mac/sched_grid.h | 15 +- srsenb/hdr/stack/mac/sched_helpers.h | 2 +- srsenb/hdr/stack/mac/sched_lte_common.h | 93 ++++++++++ srsenb/hdr/stack/mac/sched_phy_ch/sched_dci.h | 2 +- .../hdr/stack/mac/sched_phy_ch/sched_result.h | 2 +- .../stack/mac/sched_phy_ch/sf_cch_allocator.h | 2 +- srsenb/hdr/stack/mac/sched_ue.h | 2 +- .../stack/mac/sched_ue_ctrl/sched_dl_cqi.h | 2 +- .../stack/mac/sched_ue_ctrl/sched_ue_cell.h | 2 +- srsenb/src/stack/mac/nr/CMakeLists.txt | 2 +- srsenb/src/stack/mac/nr/sched_nr.cc | 15 ++ srsenb/src/stack/mac/nr/sched_nr_common.cc | 43 +++++ srsenb/src/stack/mac/nr/sched_nr_pdcch.cc | 167 ++++++++++++++++++ srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 60 +++++-- srsenb/src/stack/mac/nr/sched_nr_ue.cc | 55 ++++-- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 20 +-- srsenb/src/stack/mac/sched_grid.cc | 27 --- .../src/stack/mac/sched_phy_ch/sched_dci.cc | 2 +- srsenb/test/mac/nr/sched_nr_sim_ue.cc | 2 +- srsenb/test/mac/nr/sched_nr_test.cc | 44 +++-- srsenb/test/mac/sched_common_test_suite.h | 2 +- srsenb/test/mac/sched_dci_test.cc | 2 +- 29 files changed, 696 insertions(+), 266 deletions(-) create mode 100644 srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h create mode 100644 srsenb/hdr/stack/mac/sched_lte_common.h create mode 100644 srsenb/src/stack/mac/nr/sched_nr_common.cc create mode 100644 srsenb/src/stack/mac/nr/sched_nr_pdcch.cc diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_common.h b/srsenb/hdr/stack/mac/nr/sched_nr_common.h index 583e47dd3..51d82c58b 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_common.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_common.h @@ -21,6 +21,7 @@ namespace srsenb { const static size_t SCHED_NR_MAX_USERS = 4; const static size_t SCHED_NR_NOF_SUBFRAMES = 10; const static size_t SCHED_NR_NOF_HARQS = 16; +static const size_t MAX_NOF_AGGR_LEVELS = 5; namespace sched_nr_impl { @@ -32,16 +33,14 @@ struct sched_cell_params { const cell_cfg_t cell_cfg; const sched_cfg_t& sched_cfg; - sched_cell_params(uint32_t cc_, const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_) : - cc(cc_), cell_cfg(cell), sched_cfg(sched_cfg_) - {} + sched_cell_params(uint32_t cc_, const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_); }; struct sched_params { const sched_cfg_t sched_cfg; std::vector cells; - explicit sched_params(const sched_cfg_t& sched_cfg_) : sched_cfg(sched_cfg_) {} + explicit sched_params(const sched_cfg_t& sched_cfg_); }; using pdcchmask_t = srsran::bounded_bitset; @@ -87,6 +86,13 @@ private: bool flag = false; }; +using pdcch_cce_pos_list = srsran::bounded_vector; +using bwp_cce_pos_list = std::array, SRSRAN_NOF_SF_X_FRAME>; +void get_dci_locs(const srsran_coreset_t& coreset, + const srsran_search_space_t& search_space, + uint16_t rnti, + bwp_cce_pos_list& cce_locs); + } // namespace sched_nr_impl } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index 73e4b5412..f69a1200c 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -17,17 +17,19 @@ #include "srsran/adt/bounded_vector.h" #include "srsran/adt/span.h" #include "srsran/common/tti_point.h" +#include "srsran/interfaces/rrc_nr_interface_types.h" #include "srsran/phy/phch/dci_nr.h" namespace srsenb { -const static size_t SCHED_NR_MAX_CARRIERS = 4; -const static uint16_t SCHED_NR_INVALID_RNTI = 0; -const static size_t SCHED_NR_MAX_PDSCH_DATA = 16; -const static size_t SCHED_NR_MAX_NOF_RBGS = 25; -const static size_t SCHED_NR_MAX_UL_ALLOCS = 16; -const static size_t SCHED_NR_MAX_TB = 1; -const static size_t SCHED_NR_MAX_HARQ = 16; +const static size_t SCHED_NR_MAX_CARRIERS = 4; +const static uint16_t SCHED_NR_INVALID_RNTI = 0; +const static size_t SCHED_NR_MAX_PDSCH_DATA = 16; +const static size_t SCHED_NR_MAX_NOF_RBGS = 25; +const static size_t SCHED_NR_MAX_UL_ALLOCS = 16; +const static size_t SCHED_NR_MAX_TB = 1; +const static size_t SCHED_NR_MAX_HARQ = 16; +const static size_t SCHED_NR_MAX_BWP_PER_CELL = 1; class sched_nr_interface { @@ -47,9 +49,15 @@ public: }; using pusch_td_res_alloc_list = srsran::bounded_vector; + struct bwp_cfg_t { + uint32_t start_rb = 0; + uint32_t rb_width = 100; + }; + struct cell_cfg_t { - uint32_t nof_prb = 100; - uint32_t nof_rbg = 25; + uint32_t nof_prb = 100; + uint32_t nof_rbg = 25; + srsran::bounded_vector bwps{1}; }; struct sched_cfg_t { @@ -65,6 +73,7 @@ public: struct ue_cfg_t { uint32_t maxharq_tx = 4; srsran::bounded_vector carriers; + srsran::phy_cfg_nr_t phy_cfg = {}; }; ///// Sched Result ///// diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h new file mode 100644 index 000000000..78741d5c1 --- /dev/null +++ b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h @@ -0,0 +1,103 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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. + * + */ + +#ifndef SRSRAN_SCHED_NR_PDCCH_H +#define SRSRAN_SCHED_NR_PDCCH_H + +#include "srsenb/hdr/stack/mac/nr/sched_nr_common.h" +#include "srsran/adt/bounded_bitset.h" +#include "srsran/adt/bounded_vector.h" +#include "srsran/phy/common/phy_common_nr.h" +#include "srsran/phy/phch/dci.h" + +namespace srsenb { + +namespace sched_nr_impl { + +using coreset_bitmap = srsran::bounded_bitset; + +enum class pdcch_grant_type_t { sib, dl_data, ul_data }; + +class slot_ue; + +struct pdcch_dl_t { + srsran_dci_cfg_nr_t dci_cfg = {}; + srsran_dci_dl_nr_t dci = {}; +}; +static const size_t MAX_NOF_PDCCH_DL_GRANTS = 16; +using pdcch_dl_list_t = srsran::bounded_vector; + +class coreset_region +{ +public: + coreset_region(uint32_t bwp_id_, + uint32_t slot_idx, + uint32_t nof_td_symbols, + uint32_t nof_freq_resources, + pdcch_dl_list_t& pdcch_list); + void reset(); + + /** + * Allocates DCI space in PDCCH, avoiding in the process collisions with other users + * @param pdcch_grant_type_t allocation type (e.g. DL data, UL data, SIB) + * @param aggr_idx Aggregation level index (0..4) + * @param user UE object or null in case of broadcast/RAR/paging allocation + * @return if the allocation was successful + */ + bool alloc_dci(pdcch_grant_type_t alloc_type, uint32_t aggr_idx, uint32_t coreset_id, slot_ue* user = nullptr); + + void rem_last_dci(); + + uint32_t get_td_symbols() const { return nof_symbols; } + uint32_t get_freq_resources() const { return nof_freq_res; } + uint32_t nof_cces() const { return nof_freq_res * nof_symbols; } + size_t nof_allocs() const { return dfs_tree.size(); } + +private: + uint32_t bwp_id; + uint32_t slot_idx; + uint32_t nof_symbols; + uint32_t nof_freq_res; + + // List of PDCCH grants + struct alloc_record { + uint32_t coreset_id; + uint32_t aggr_idx; + uint32_t idx; + pdcch_grant_type_t alloc_type; + slot_ue* ue; + }; + srsran::bounded_vector dci_list; + pdcch_dl_list_t& pdcch_dl_list; + + // DFS decision tree of PDCCH grants + struct tree_node { + uint16_t rnti = SRSRAN_INVALID_RNTI; + uint32_t record_idx = 0; + uint32_t dci_pos_idx = 0; + srsran_dci_location_t dci_pos = {0, 0}; + /// Accumulation of all PDCCH masks for the current solution (DFS path) + coreset_bitmap total_mask, current_mask; + }; + using alloc_tree_dfs_t = srsran::bounded_vector; + alloc_tree_dfs_t dfs_tree, saved_dfs_tree; + + srsran::span get_cce_loc_table(const alloc_record& record) const; + bool alloc_dfs_node(const alloc_record& record, uint32_t dci_idx); + bool get_next_dfs(); +}; + +} // namespace sched_nr_impl + +} // namespace srsenb + +#endif // SRSRAN_SCHED_NR_PDCCH_H diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h index 0619a184a..2f2d6c408 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h @@ -13,104 +13,72 @@ #ifndef SRSRAN_SCHED_NR_RB_GRID_H #define SRSRAN_SCHED_NR_RB_GRID_H +#include "../sched_common.h" #include "lib/include/srsran/adt/circular_array.h" #include "sched_nr_interface.h" +#include "sched_nr_pdcch.h" #include "sched_nr_ue.h" namespace srsenb { namespace sched_nr_impl { +using pdsch_bitmap = srsran::bounded_bitset<25, true>; +using pusch_bitmap = srsran::bounded_bitset<25, true>; + using pdsch_list = sched_nr_interface::pdsch_list; using pusch_list = sched_nr_interface::pusch_list; -struct pdcch_t {}; -struct pdsch_t {}; -struct pusch_t {}; struct pucch_t {}; -struct phy_slot_grid { - const sched_cell_params* cell_cfg = nullptr; - pdcchmask_t pdcch_tot_mask; - rbgmask_t pdsch_tot_mask; - rbgmask_t ul_tot_mask; +const static size_t MAX_CORESET_PER_BWP = 3; +using slot_coreset_list = srsran::bounded_vector; + +struct bwp_slot_grid { + pdcch_dl_list_t pdcch_dl_list; + slot_coreset_list coresets; + pdsch_bitmap dl_rbgs; pdsch_list pdsch_grants; + pusch_bitmap ul_rbgs; pusch_list pusch_grants; srsran::bounded_vector pucch_grants; - phy_slot_grid() = default; - explicit phy_slot_grid(const sched_cell_params& cell_cfg_) : - cell_cfg(&cell_cfg_), - pdcch_tot_mask(cell_cfg->cell_cfg.nof_rbg), - pdsch_tot_mask(cell_cfg->cell_cfg.nof_rbg), - ul_tot_mask(cell_cfg->cell_cfg.nof_rbg) - {} - void reset() - { - pdcch_tot_mask.reset(); - pdsch_tot_mask.reset(); - ul_tot_mask.reset(); - pdsch_grants.clear(); - pusch_grants.clear(); - pucch_grants.clear(); - } -}; -using phy_cell_rb_grid = srsran::circular_array; - -struct slot_ue_grid { - phy_slot_grid* pdcch_slot; - phy_slot_grid* pdsch_slot; - phy_slot_grid* pusch_slot; - phy_slot_grid* pucch_slot; - pdcch_t* pdcch_alloc = nullptr; - pdsch_t* pdsch_alloc = nullptr; - pusch_t* pusch_alloc = nullptr; - pucch_t* pucch_alloc = nullptr; - - slot_ue_grid(phy_slot_grid& pdcch_sl, phy_slot_grid& pdsch_sl, phy_slot_grid& pusch_sl, phy_slot_grid& pucch_sl) : - pdcch_slot(&pdcch_sl), pdsch_slot(&pdsch_sl), pusch_slot(&pusch_sl), pucch_slot(&pucch_sl) - {} + bwp_slot_grid() = default; + explicit bwp_slot_grid(const sched_cell_params& cell_params, uint32_t bwp_id_, uint32_t slot_idx_); + void reset(); }; -class rb_alloc_grid -{ -public: - slot_ue_grid get_slot_ue_grid(tti_point pdcch_tti, uint8_t K0, uint8_t K1, uint8_t K2) - { - phy_slot_grid& pdcch_slot = phy_grid[pdcch_tti.to_uint()]; - phy_slot_grid& pdsch_slot = phy_grid[(pdcch_tti + K0).to_uint()]; - phy_slot_grid& pucch_slot = phy_grid[(pdcch_tti + K0 + K1).to_uint()]; - phy_slot_grid& pusch_slot = phy_grid[(pdcch_tti + K2).to_uint()]; - return slot_ue_grid{pdcch_slot, pdsch_slot, pusch_slot, pucch_slot}; - } +struct bwp_res_grid { + bwp_res_grid(const sched_cell_params& cell_cfg_, uint32_t bwp_id_); + + bwp_slot_grid& operator[](tti_point tti) { return slots[tti.sf_idx()]; }; + const bwp_slot_grid& operator[](tti_point tti) const { return slots[tti.sf_idx()]; }; + uint32_t id() const { return bwp_id; } private: - phy_cell_rb_grid phy_grid; + uint32_t bwp_id; + srsran::bounded_vector slots; }; -/// Error code of alloc attempt -enum class alloc_result { success, sch_collision, no_grant_space, no_rnti_opportunity }; -inline const char* to_string(alloc_result res) -{ - return ""; -} +struct cell_res_grid { + const sched_cell_params* cell_cfg = nullptr; + srsran::bounded_vector bwps; + + explicit cell_res_grid(const sched_cell_params& cell_cfg); +}; -class slot_sched +class slot_bwp_sched { public: - explicit slot_sched(const sched_cell_params& cfg_, phy_cell_rb_grid& phy_grid_); - void new_tti(tti_point tti_rx_); - void reset(); + explicit slot_bwp_sched(uint32_t bwp_id, cell_res_grid& phy_grid_); alloc_result alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask); alloc_result alloc_pusch(slot_ue& ue, const rbgmask_t& dl_mask); - void generate_dcis(); - const sched_cell_params& cfg; private: srslog::basic_logger& logger; - phy_cell_rb_grid& phy_grid; + bwp_res_grid& bwp_grid; tti_point tti_rx; }; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h index f15a516d0..d1c2c5c66 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h @@ -27,6 +27,32 @@ namespace sched_nr_impl { using ue_cfg_t = sched_nr_interface::ue_cfg_t; using ue_cc_cfg_t = sched_nr_interface::ue_cc_cfg_t; +class ue_cfg_extended : public ue_cfg_t +{ +public: + struct search_space_params { + srsran_search_space_t* cfg = nullptr; + }; + struct coreset_params { + srsran_coreset_t* cfg = nullptr; + std::vector ss_list; + bwp_cce_pos_list cce_positions; + }; + struct bwp_params { + std::vector search_spaces; + std::vector coresets; + }; + struct cc_params { + srsran::bounded_vector bwps; + }; + + uint16_t rnti; + std::vector cc_params; + + ue_cfg_extended() = default; + explicit ue_cfg_extended(uint16_t rnti, const ue_cfg_t& uecfg); +}; + class ue_carrier; class slot_ue @@ -44,11 +70,13 @@ public: uint32_t cc = SCHED_NR_MAX_CARRIERS; // UE parameters common to all sectors - const ue_cfg_t* cfg = nullptr; - bool pending_sr; + const ue_cfg_extended* cfg = nullptr; + bool pending_sr; // UE parameters that are sector specific const ue_cc_cfg_t* cc_cfg = nullptr; + uint32_t bwp_id; + tti_point pdcch_tti; tti_point pdsch_tti; tti_point pusch_tti; tti_point uci_tti; @@ -65,9 +93,8 @@ class ue_carrier { public: ue_carrier(uint16_t rnti, uint32_t cc, const ue_cfg_t& cfg); - slot_ue try_reserve(tti_point pdcch_tti, const ue_cfg_t& cfg); + slot_ue try_reserve(tti_point pdcch_tti, const ue_cfg_extended& cfg); void push_feedback(srsran::move_callback callback); - void set_cfg(const ue_cfg_t& uecfg); const uint16_t rnti; const uint32_t cc; @@ -101,10 +128,12 @@ public: std::array, SCHED_NR_MAX_CARRIERS> carriers; private: + const uint16_t rnti; + bool pending_sr = false; - int current_idx = 0; - std::array ue_cfgs; + int current_idx = 0; + std::array ue_cfgs; }; using ue_map_t = srsran::static_circular_map, SCHED_NR_MAX_USERS>; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h index 30122c5a9..23632a9d5 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h @@ -32,8 +32,8 @@ using slot_res_t = sched_nr_interface::tti_request_t; class slot_cc_worker { public: - explicit slot_cc_worker(const sched_cell_params& cell_params, phy_cell_rb_grid& phy_grid) : - cfg(cell_params), res_grid(cfg, phy_grid) + explicit slot_cc_worker(const sched_cell_params& cell_params, cell_res_grid& phy_grid) : + cfg(cell_params), res_grid(0, phy_grid) {} void start(tti_point tti_rx_, ue_map_t& ue_db_); @@ -47,8 +47,8 @@ private: const sched_cell_params& cfg; - tti_point tti_rx; - slot_sched res_grid; + tti_point tti_rx; + slot_bwp_sched res_grid; srsran::static_circular_map slot_ues; }; @@ -78,7 +78,7 @@ private: }; std::vector > slot_ctxts; - std::array phy_grid; + srsran::bounded_vector cell_grid_list; slot_worker_ctxt& get_sf(tti_point tti_rx); }; diff --git a/srsenb/hdr/stack/mac/sched_common.h b/srsenb/hdr/stack/mac/sched_common.h index 25ecb78d5..8a2e2978f 100644 --- a/srsenb/hdr/stack/mac/sched_common.h +++ b/srsenb/hdr/stack/mac/sched_common.h @@ -13,79 +13,49 @@ #ifndef SRSRAN_SCHED_COMMON_H #define SRSRAN_SCHED_COMMON_H -#include "srsran/adt/bounded_bitset.h" -#include "srsran/common/tti_point.h" -#include "srsran/interfaces/sched_interface.h" +/** + * File used for all functions and types common to the LTE and NR schedulers + */ namespace srsenb { -/*********************** - * Constants - **********************/ - -constexpr float tti_duration_ms = 1; -constexpr uint32_t NOF_AGGR_LEVEL = 4; - -/*********************** - * Helper Types - **********************/ - -/// List of CCE start positions in PDCCH -using cce_position_list = srsran::bounded_vector; - -/// Map {L} -> list of CCE positions -using cce_cfi_position_table = std::array; - -/// Map {cfi, L} -> list of CCE positions -using cce_sf_position_table = std::array, SRSRAN_NOF_CFI>; - -/// Map {sf, cfi, L} -> list of CCE positions -using cce_frame_position_table = std::array; - -/// structs to bundle together all the sched arguments, and share them with all the sched sub-components -class sched_cell_params_t -{ - struct regs_deleter { - void operator()(srsran_regs_t* p); - }; - -public: - bool set_cfg(uint32_t enb_cc_idx_, - const sched_interface::cell_cfg_t& cfg_, - const sched_interface::sched_args_t& sched_args); - // convenience getters - uint32_t nof_prbs_to_rbgs(uint32_t nof_prbs) const { return srsran::ceil_div(nof_prbs, P); } - uint32_t nof_prb() const { return cfg.cell.nof_prb; } - uint32_t get_dl_lb_nof_re(tti_point tti_tx_dl, uint32_t nof_prbs_alloc) const; - uint32_t get_dl_nof_res(srsran::tti_point tti_tx_dl, const srsran_dci_dl_t& dci, uint32_t cfi) const; - - uint32_t enb_cc_idx = 0; - sched_interface::cell_cfg_t cfg = {}; - srsran_pucch_cfg_t pucch_cfg_common = {}; - const sched_interface::sched_args_t* sched_cfg = nullptr; - std::unique_ptr regs; - cce_sf_position_table common_locations = {}; - cce_frame_position_table rar_locations = {}; - std::array nof_cce_table = {}; ///< map cfix -> nof cces in PDCCH - uint32_t P = 0; - uint32_t nof_rbgs = 0; - - using dl_nof_re_table = srsran::bounded_vector< - std::array, SRSRAN_NOF_SLOTS_PER_SF>, SRSRAN_NOF_SF_X_FRAME>, - SRSRAN_MAX_PRB>; - using dl_lb_nof_re_table = std::array, SRSRAN_NOF_SF_X_FRAME>; - - /// Table of nof REs - dl_nof_re_table nof_re_table; - /// Cached computation of Lower bound of nof REs - dl_lb_nof_re_table nof_re_lb_table; +/// Error code of alloc attempt +enum class alloc_result { + success, + sch_collision, + no_cch_space, + no_sch_space, + no_rnti_opportunity, + invalid_grant_params, + invalid_coderate, + no_grant_space, + other_cause }; - -/// Type of Allocation stored in PDSCH/PUSCH -enum class alloc_type_t { DL_BC, DL_PCCH, DL_RAR, DL_DATA, UL_DATA }; -inline bool is_dl_ctrl_alloc(alloc_type_t a) +inline const char* to_string(alloc_result result) { - return a == alloc_type_t::DL_BC or a == alloc_type_t::DL_PCCH or a == alloc_type_t::DL_RAR; + switch (result) { + case alloc_result::success: + return "success"; + case alloc_result::sch_collision: + return "Collision with existing SCH allocations"; + case alloc_result::other_cause: + return "error"; + case alloc_result::no_cch_space: + return "No space available in PUCCH or PDCCH"; + case alloc_result::no_sch_space: + return "Requested number of PRBs not available"; + case alloc_result::no_rnti_opportunity: + return "rnti cannot be allocated (e.g. already allocated, no data, meas gap collision, carrier inactive, etc.)"; + case alloc_result::invalid_grant_params: + return "invalid grant arguments (e.g. invalid prb mask)"; + case alloc_result::invalid_coderate: + return "Effective coderate exceeds threshold"; + case alloc_result::no_grant_space: + return "Max number of allocations reached"; + default: + break; + } + return "unknown error"; } } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/sched_grid.h b/srsenb/hdr/stack/mac/sched_grid.h index a7b3e9434..f7d7ce183 100644 --- a/srsenb/hdr/stack/mac/sched_grid.h +++ b/srsenb/hdr/stack/mac/sched_grid.h @@ -14,6 +14,7 @@ #define SRSRAN_SCHED_GRID_H #include "lib/include/srsran/interfaces/sched_interface.h" +#include "sched_common.h" #include "sched_phy_ch/sched_result.h" #include "sched_phy_ch/sf_cch_allocator.h" #include "sched_ue.h" @@ -24,20 +25,6 @@ namespace srsenb { -/// Error code of alloc attempt -enum class alloc_result { - success, - sch_collision, - no_cch_space, - no_sch_space, - no_rnti_opportunity, - invalid_grant_params, - invalid_coderate, - no_grant_space, - other_cause -}; -const char* to_string(alloc_result res); - struct sf_sched_result { tti_point tti_rx; std::vector enb_cc_list; diff --git a/srsenb/hdr/stack/mac/sched_helpers.h b/srsenb/hdr/stack/mac/sched_helpers.h index 83962c6ff..651dae6b8 100644 --- a/srsenb/hdr/stack/mac/sched_helpers.h +++ b/srsenb/hdr/stack/mac/sched_helpers.h @@ -13,7 +13,7 @@ #ifndef SRSRAN_SCHED_HELPERS_H #define SRSRAN_SCHED_HELPERS_H -#include "srsenb/hdr/stack/mac/sched_common.h" +#include "srsenb/hdr/stack/mac/sched_lte_common.h" #include "srsran/interfaces/sched_interface.h" #include "srsran/srslog/srslog.h" diff --git a/srsenb/hdr/stack/mac/sched_lte_common.h b/srsenb/hdr/stack/mac/sched_lte_common.h new file mode 100644 index 000000000..39bd4bf9e --- /dev/null +++ b/srsenb/hdr/stack/mac/sched_lte_common.h @@ -0,0 +1,93 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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. + * + */ + +#ifndef SRSRAN_SCHED_LTE_COMMON_H +#define SRSRAN_SCHED_LTE_COMMON_H + +#include "srsran/adt/bounded_bitset.h" +#include "srsran/common/tti_point.h" +#include "srsran/interfaces/sched_interface.h" + +namespace srsenb { + +/*********************** + * Constants + **********************/ + +constexpr float tti_duration_ms = 1; +constexpr uint32_t NOF_AGGR_LEVEL = 4; + +/*********************** + * Helper Types + **********************/ + +/// List of CCE start positions in PDCCH +using cce_position_list = srsran::bounded_vector; + +/// Map {L} -> list of CCE positions +using cce_cfi_position_table = std::array; + +/// Map {cfi, L} -> list of CCE positions +using cce_sf_position_table = std::array, SRSRAN_NOF_CFI>; + +/// Map {sf, cfi, L} -> list of CCE positions +using cce_frame_position_table = std::array; + +/// structs to bundle together all the sched arguments, and share them with all the sched sub-components +class sched_cell_params_t +{ + struct regs_deleter { + void operator()(srsran_regs_t* p); + }; + +public: + bool set_cfg(uint32_t enb_cc_idx_, + const sched_interface::cell_cfg_t& cfg_, + const sched_interface::sched_args_t& sched_args); + // convenience getters + uint32_t nof_prbs_to_rbgs(uint32_t nof_prbs) const { return srsran::ceil_div(nof_prbs, P); } + uint32_t nof_prb() const { return cfg.cell.nof_prb; } + uint32_t get_dl_lb_nof_re(tti_point tti_tx_dl, uint32_t nof_prbs_alloc) const; + uint32_t get_dl_nof_res(srsran::tti_point tti_tx_dl, const srsran_dci_dl_t& dci, uint32_t cfi) const; + + uint32_t enb_cc_idx = 0; + sched_interface::cell_cfg_t cfg = {}; + srsran_pucch_cfg_t pucch_cfg_common = {}; + const sched_interface::sched_args_t* sched_cfg = nullptr; + std::unique_ptr regs; + cce_sf_position_table common_locations = {}; + cce_frame_position_table rar_locations = {}; + std::array nof_cce_table = {}; ///< map cfix -> nof cces in PDCCH + uint32_t P = 0; + uint32_t nof_rbgs = 0; + + using dl_nof_re_table = srsran::bounded_vector< + std::array, SRSRAN_NOF_SLOTS_PER_SF>, SRSRAN_NOF_SF_X_FRAME>, + SRSRAN_MAX_PRB>; + using dl_lb_nof_re_table = std::array, SRSRAN_NOF_SF_X_FRAME>; + + /// Table of nof REs + dl_nof_re_table nof_re_table; + /// Cached computation of Lower bound of nof REs + dl_lb_nof_re_table nof_re_lb_table; +}; + +/// Type of Allocation stored in PDSCH/PUSCH +enum class alloc_type_t { DL_BC, DL_PCCH, DL_RAR, DL_DATA, UL_DATA }; +inline bool is_dl_ctrl_alloc(alloc_type_t a) +{ + return a == alloc_type_t::DL_BC or a == alloc_type_t::DL_PCCH or a == alloc_type_t::DL_RAR; +} + +} // namespace srsenb + +#endif // SRSRAN_SCHED_LTE_COMMON_H diff --git a/srsenb/hdr/stack/mac/sched_phy_ch/sched_dci.h b/srsenb/hdr/stack/mac/sched_phy_ch/sched_dci.h index 97eb9b44b..d6ec586ba 100644 --- a/srsenb/hdr/stack/mac/sched_phy_ch/sched_dci.h +++ b/srsenb/hdr/stack/mac/sched_phy_ch/sched_dci.h @@ -13,7 +13,7 @@ #ifndef SRSRAN_SCHED_DCI_H #define SRSRAN_SCHED_DCI_H -#include "../sched_common.h" +#include "../sched_lte_common.h" #include "srsenb/hdr/stack/mac/sched_phy_ch/sched_phy_resource.h" #include "srsran/adt/bounded_vector.h" diff --git a/srsenb/hdr/stack/mac/sched_phy_ch/sched_result.h b/srsenb/hdr/stack/mac/sched_phy_ch/sched_result.h index 1443ea090..88624d4d0 100644 --- a/srsenb/hdr/stack/mac/sched_phy_ch/sched_result.h +++ b/srsenb/hdr/stack/mac/sched_phy_ch/sched_result.h @@ -13,7 +13,7 @@ #ifndef SRSRAN_SCHED_RESULT_H #define SRSRAN_SCHED_RESULT_H -#include "../sched_common.h" +#include "../sched_lte_common.h" #include "srsenb/hdr/stack/mac/sched_phy_ch/sched_phy_resource.h" namespace srsenb { diff --git a/srsenb/hdr/stack/mac/sched_phy_ch/sf_cch_allocator.h b/srsenb/hdr/stack/mac/sched_phy_ch/sf_cch_allocator.h index 7ae640923..4b6f1b68b 100644 --- a/srsenb/hdr/stack/mac/sched_phy_ch/sf_cch_allocator.h +++ b/srsenb/hdr/stack/mac/sched_phy_ch/sf_cch_allocator.h @@ -10,7 +10,7 @@ * */ -#include "../sched_common.h" +#include "../sched_lte_common.h" #include "sched_result.h" #ifndef SRSRAN_PDCCH_SCHED_H diff --git a/srsenb/hdr/stack/mac/sched_ue.h b/srsenb/hdr/stack/mac/sched_ue.h index 5f831ca13..dadbff6fa 100644 --- a/srsenb/hdr/stack/mac/sched_ue.h +++ b/srsenb/hdr/stack/mac/sched_ue.h @@ -13,7 +13,7 @@ #ifndef SRSENB_SCHEDULER_UE_H #define SRSENB_SCHEDULER_UE_H -#include "sched_common.h" +#include "sched_lte_common.h" #include "sched_ue_ctrl/sched_lch.h" #include "sched_ue_ctrl/sched_ue_cell.h" #include "sched_ue_ctrl/tpc.h" diff --git a/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_dl_cqi.h b/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_dl_cqi.h index 0479f89a9..604cabf61 100644 --- a/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_dl_cqi.h +++ b/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_dl_cqi.h @@ -13,8 +13,8 @@ #ifndef SRSRAN_SCHED_DL_CQI_H #define SRSRAN_SCHED_DL_CQI_H -#include "srsenb/hdr/stack/mac/sched_common.h" #include "srsenb/hdr/stack/mac/sched_helpers.h" +#include "srsenb/hdr/stack/mac/sched_lte_common.h" #include "srsenb/hdr/stack/mac/sched_phy_ch/sched_phy_resource.h" #include "srsran/adt/accumulators.h" #include "srsran/common/common_lte.h" diff --git a/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_ue_cell.h b/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_ue_cell.h index 4e0020b41..4c6585ad7 100644 --- a/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_ue_cell.h +++ b/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_ue_cell.h @@ -13,7 +13,7 @@ #ifndef SRSRAN_SCHED_UE_CELL_H #define SRSRAN_SCHED_UE_CELL_H -#include "../sched_common.h" +#include "../sched_lte_common.h" #include "sched_dl_cqi.h" #include "sched_harq.h" #include "srsenb/hdr/stack/mac/sched_phy_ch/sched_dci.h" diff --git a/srsenb/src/stack/mac/nr/CMakeLists.txt b/srsenb/src/stack/mac/nr/CMakeLists.txt index 480fb0d24..76499a48f 100644 --- a/srsenb/src/stack/mac/nr/CMakeLists.txt +++ b/srsenb/src/stack/mac/nr/CMakeLists.txt @@ -6,6 +6,6 @@ # the distribution. # -set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc sched_nr_rb_grid.cc sched_nr_harq.cc) +set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc sched_nr_rb_grid.cc sched_nr_harq.cc sched_nr_pdcch.cc sched_nr_common.cc) add_library(srsgnb_mac STATIC ${SOURCES}) diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsenb/src/stack/mac/nr/sched_nr.cc index 193a54e1e..4ab1f74ee 100644 --- a/srsenb/src/stack/mac/nr/sched_nr.cc +++ b/srsenb/src/stack/mac/nr/sched_nr.cc @@ -21,6 +21,8 @@ using sched_nr_impl::ue; using sched_nr_impl::ue_carrier; using sched_nr_impl::ue_map_t; +static int assert_ue_cfg_valid(uint16_t rnti, const sched_nr_interface::ue_cfg_t& uecfg); + class ue_event_manager { using callback_t = srsran::move_callback; @@ -96,6 +98,7 @@ int sched_nr::cell_cfg(srsran::const_span cell_list) void sched_nr::ue_cfg(uint16_t rnti, const ue_cfg_t& uecfg) { + srsran_assert(assert_ue_cfg_valid(rnti, uecfg) == SRSRAN_SUCCESS, "Invalid UE configuration"); pending_events->push_event([this, rnti, uecfg]() { ue_cfg_impl(rnti, uecfg); }); } @@ -153,4 +156,16 @@ void sched_nr::ul_sr_info(tti_point tti_rx, uint16_t rnti) }); } +int assert_ue_cfg_valid(uint16_t rnti, const sched_nr_interface::ue_cfg_t& uecfg) +{ + const srslog::basic_logger& logger = srslog::fetch_basic_logger("MAC"); + if (std::count(&uecfg.phy_cfg.pdcch.coreset_present[0], + &uecfg.phy_cfg.pdcch.coreset_present[SRSRAN_UE_DL_NR_MAX_NOF_CORESET], + true) == 0) { + logger.warning("Provided rnti=0x%x configuration does not contain any coreset", rnti); + return SRSRAN_ERROR; + } + return SRSRAN_SUCCESS; +} + } // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/stack/mac/nr/sched_nr_common.cc b/srsenb/src/stack/mac/nr/sched_nr_common.cc new file mode 100644 index 000000000..3a239475a --- /dev/null +++ b/srsenb/src/stack/mac/nr/sched_nr_common.cc @@ -0,0 +1,43 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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 "srsenb/hdr/stack/mac/nr/sched_nr_common.h" + +namespace srsenb { +namespace sched_nr_impl { + +sched_cell_params::sched_cell_params(uint32_t cc_, const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_) : + cc(cc_), cell_cfg(cell), sched_cfg(sched_cfg_) +{} + +sched_params::sched_params(const sched_cfg_t& sched_cfg_) : sched_cfg(sched_cfg_) {} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void get_dci_locs(const srsran_coreset_t& coreset, + const srsran_search_space_t& search_space, + uint16_t rnti, + bwp_cce_pos_list& cce_locs) +{ + for (uint32_t sl = 0; sl < SRSRAN_NOF_SF_X_FRAME; ++sl) { + for (uint32_t agg_idx = 0; agg_idx < MAX_NOF_AGGR_LEVELS; ++agg_idx) { + pdcch_cce_pos_list pdcch_locs; + cce_locs[sl][agg_idx].resize(pdcch_locs.capacity()); + uint32_t n = + srsran_pdcch_nr_locations_coreset(&coreset, &search_space, rnti, agg_idx, sl, cce_locs[sl][agg_idx].data()); + cce_locs[sl][agg_idx].resize(n); + } + } +} + +} // namespace sched_nr_impl +} // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc b/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc new file mode 100644 index 000000000..49e7d7c90 --- /dev/null +++ b/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc @@ -0,0 +1,167 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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 "srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_ue.h" + +namespace srsenb { +namespace sched_nr_impl { + +coreset_region::coreset_region(uint32_t bwp_id_, + uint32_t slot_idx_, + uint32_t nof_td_symbols, + uint32_t nof_freq_resources, + pdcch_dl_list_t& pdcch_list_) : + bwp_id(bwp_id_), + slot_idx(slot_idx_), + nof_symbols(nof_td_symbols), + nof_freq_res(nof_freq_resources), + pdcch_dl_list(pdcch_list_) +{ + srsran_assert(nof_td_symbols <= SRSRAN_CORESET_DURATION_MAX, + "Possible number of time-domain OFDM symbols in CORESET must be within {1,2,3}"); + srsran_assert(nof_freq_resources <= SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE, + "Provided number of CORESET freq domain resources=%d is too high", + nof_freq_resources); +} + +void coreset_region::reset() +{ + dfs_tree.clear(); + saved_dfs_tree.clear(); + dci_list.clear(); + pdcch_dl_list.clear(); +} + +bool coreset_region::alloc_dci(pdcch_grant_type_t alloc_type, uint32_t aggr_idx, uint32_t coreset_id, slot_ue* user) +{ + srsran_assert(aggr_idx <= 4, "Invalid DCI aggregation level=%d", 1U << aggr_idx); + srsran_assert((user == nullptr) xor + (alloc_type == pdcch_grant_type_t::dl_data or alloc_type == pdcch_grant_type_t::ul_data), + "UE should be only provided for DL or UL data allocations"); + saved_dfs_tree.clear(); + + alloc_record record; + record.ue = user; + record.aggr_idx = aggr_idx; + record.alloc_type = alloc_type; + record.idx = pdcch_dl_list.size(); + record.coreset_id = coreset_id; + pdcch_dl_list.emplace_back(); + + // Try to allocate grant. If it fails, attempt the same grant, but using a different permutation of past grant DCI + // positions + do { + bool success = alloc_dfs_node(record, 0); + if (success) { + // DCI record allocation successful + dci_list.push_back(record); + return true; + } + if (dfs_tree.empty()) { + saved_dfs_tree = dfs_tree; + } + } while (get_next_dfs()); + + // Revert steps to initial state, before dci record allocation was attempted + dfs_tree = saved_dfs_tree; + pdcch_dl_list.pop_back(); + return false; +} + +void coreset_region::rem_last_dci() +{ + srsran_assert(not dci_list.empty(), "%s called when no PDCCH have yet been allocated", __FUNCTION__); + + // Remove DCI record + dfs_tree.pop_back(); + dci_list.pop_back(); + pdcch_dl_list.pop_back(); +} + +bool coreset_region::get_next_dfs() +{ + do { + if (dfs_tree.empty()) { + // If we reach root, the allocation failed + return false; + } + // Attempt to re-add last tree node, but with a higher node child index + uint32_t start_child_idx = dfs_tree.back().dci_pos_idx + 1; + dfs_tree.pop_back(); + while (dfs_tree.size() < dci_list.size() and alloc_dfs_node(dci_list[dfs_tree.size()], start_child_idx)) { + start_child_idx = 0; + } + } while (dfs_tree.size() < dci_list.size()); + + // Finished computation of next DFS node + return true; +} + +bool coreset_region::alloc_dfs_node(const alloc_record& record, uint32_t start_dci_idx) +{ + alloc_tree_dfs_t& alloc_dfs = dfs_tree; + // Get DCI Location Table + auto cce_locs = get_cce_loc_table(record); + if (start_dci_idx >= cce_locs.size()) { + return false; + } + + tree_node node; + node.dci_pos_idx = start_dci_idx; + node.dci_pos.L = record.aggr_idx; + node.rnti = record.ue != nullptr ? record.ue->rnti : SRSRAN_INVALID_RNTI; + node.current_mask.resize(nof_cces()); + // get cumulative pdcch bitmap + if (not alloc_dfs.empty()) { + node.total_mask = alloc_dfs.back().total_mask; + } else { + node.total_mask.resize(nof_cces()); + } + + for (; node.dci_pos_idx < cce_locs.size(); ++node.dci_pos_idx) { + node.dci_pos.ncce = cce_locs[node.dci_pos_idx]; + + node.current_mask.reset(); + node.current_mask.fill(node.dci_pos.ncce, node.dci_pos.ncce + (1U << record.aggr_idx)); + if ((node.total_mask & node.current_mask).any()) { + // there is a PDCCH collision. Try another CCE position + continue; + } + + // Allocation successful + node.total_mask |= node.current_mask; + alloc_dfs.push_back(node); + pdcch_dl_t& pdcch_dl = pdcch_dl_list[record.idx]; + pdcch_dl.dci.ctx.location = node.dci_pos; + return true; + } + + return false; +} + +srsran::span coreset_region::get_cce_loc_table(const alloc_record& record) const +{ + switch (record.alloc_type) { + case pdcch_grant_type_t::dl_data: + return record.ue->cfg->cc_params[record.ue->cc] + .bwps[bwp_id] + .coresets[record.coreset_id] + .cce_positions[slot_idx][record.aggr_idx]; + default: + break; + } + return {}; +} + +} // namespace sched_nr_impl +} // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc index b36a2d129..3245388fe 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -18,30 +18,66 @@ namespace sched_nr_impl { using pdsch_grant = sched_nr_interface::pdsch_grant; using pusch_grant = sched_nr_interface::pusch_grant; -slot_sched::slot_sched(const sched_cell_params& cfg_, phy_cell_rb_grid& phy_grid_) : - logger(srslog::fetch_basic_logger("MAC")), cfg(cfg_), phy_grid(phy_grid_) -{} +bwp_slot_grid::bwp_slot_grid(const sched_cell_params& cell_params, uint32_t bwp_id_, uint32_t slot_idx_) : + dl_rbgs(cell_params.cell_cfg.nof_rbg), ul_rbgs(cell_params.cell_cfg.nof_rbg) +{ + coresets.emplace_back(bwp_id_, slot_idx_, 1, cell_params.cell_cfg.bwps[bwp_id_].rb_width / 6, pdcch_dl_list); +} -void slot_sched::new_tti(tti_point tti_rx_) +void bwp_slot_grid::reset() { - tti_rx = tti_rx_; + for (auto& coreset : coresets) { + coreset.reset(); + } + dl_rbgs.reset(); + ul_rbgs.reset(); + pdsch_grants.clear(); + pdcch_dl_list.clear(); + pusch_grants.clear(); + pucch_grants.clear(); } -alloc_result slot_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) +bwp_res_grid::bwp_res_grid(const sched_cell_params& cell_cfg_, uint32_t bwp_id_) : bwp_id(bwp_id_) +{ + for (uint32_t sl = 0; sl < SCHED_NR_NOF_SUBFRAMES; ++sl) { + slots.emplace_back(cell_cfg_, bwp_id, sl); + } +} + +cell_res_grid::cell_res_grid(const sched_cell_params& cell_cfg_) : cell_cfg(&cell_cfg_) +{ + for (uint32_t bwp_id = 0; bwp_id < cell_cfg->cell_cfg.bwps.size(); ++bwp_id) { + bwps.emplace_back(cell_cfg_, bwp_id); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +slot_bwp_sched::slot_bwp_sched(uint32_t bwp_id, cell_res_grid& phy_grid_) : + logger(srslog::fetch_basic_logger("MAC")), cfg(*phy_grid_.cell_cfg), bwp_grid(phy_grid_.bwps[bwp_id]) +{} + +alloc_result slot_bwp_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) { if (ue.h_dl == nullptr) { logger.warning("SCHED: Trying to allocate PDSCH for rnti=0x%x with no available HARQs", ue.rnti); return alloc_result::no_rnti_opportunity; } - pdsch_list& pdsch_grants = phy_grid[ue.pdsch_tti.to_uint()].pdsch_grants; + pdsch_list& pdsch_grants = bwp_grid[ue.pdsch_tti].pdsch_grants; if (pdsch_grants.full()) { logger.warning("SCHED: Maximum number of DL allocations reached"); return alloc_result::no_grant_space; } - rbgmask_t& pdsch_mask = phy_grid[ue.pdsch_tti.to_uint()].pdsch_tot_mask; + rbgmask_t& pdsch_mask = bwp_grid[ue.pdsch_tti].dl_rbgs; if ((pdsch_mask & dl_mask).any()) { return alloc_result::sch_collision; } + const uint32_t aggr_idx = 3, coreset_id = 0; + if (not bwp_grid[ue.pdcch_tti].coresets[coreset_id].alloc_dci( + pdcch_grant_type_t::dl_data, aggr_idx, coreset_id, &ue)) { + // Could not find space in PDCCH + return alloc_result::no_cch_space; + } int mcs = -1, tbs = -1; if (ue.h_dl->empty()) { @@ -65,18 +101,18 @@ alloc_result slot_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) return alloc_result::success; } -alloc_result slot_sched::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) +alloc_result slot_bwp_sched::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) { if (ue.h_ul == nullptr) { logger.warning("SCHED: Trying to allocate PUSCH for rnti=0x%x with no available HARQs", ue.rnti); return alloc_result::no_rnti_opportunity; } - pusch_list& pusch_grants = phy_grid[ue.pusch_tti.to_uint()].pusch_grants; + pusch_list& pusch_grants = bwp_grid[ue.pusch_tti].pusch_grants; if (pusch_grants.full()) { logger.warning("SCHED: Maximum number of UL allocations reached"); return alloc_result::no_grant_space; } - rbgmask_t& pusch_mask = phy_grid[ue.pusch_tti.to_uint()].ul_tot_mask; + rbgmask_t& pusch_mask = bwp_grid[ue.pusch_tti].ul_rbgs; if ((pusch_mask & ul_mask).any()) { return alloc_result::sch_collision; } @@ -104,7 +140,5 @@ alloc_result slot_sched::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) return alloc_result::success; } -void slot_sched::generate_dcis() {} - } // namespace sched_nr_impl } // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue.cc b/srsenb/src/stack/mac/nr/sched_nr_ue.cc index 5b255135d..9e7a38107 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_ue.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_ue.cc @@ -11,10 +11,41 @@ */ #include "srsenb/hdr/stack/mac/nr/sched_nr_ue.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h" namespace srsenb { namespace sched_nr_impl { +ue_cfg_extended::ue_cfg_extended(uint16_t rnti_, const ue_cfg_t& uecfg) : ue_cfg_t(uecfg), rnti(rnti_) +{ + cc_params.resize(carriers.size()); + for (uint32_t cc = 0; cc < cc_params.size(); ++cc) { + cc_params[cc].bwps.resize(1); + auto& bwp = cc_params[cc].bwps[0]; + for (uint32_t ssid = 0; ssid < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE; ++ssid) { + if (phy_cfg.pdcch.search_space_present[ssid]) { + bwp.search_spaces.emplace_back(); + bwp.search_spaces.back().cfg = &phy_cfg.pdcch.search_space[ssid]; + } + } + for (uint32_t csid = 0; csid < SRSRAN_UE_DL_NR_MAX_NOF_CORESET; ++csid) { + if (phy_cfg.pdcch.coreset_present[csid]) { + bwp.coresets.emplace_back(); + auto& coreset = bwp.coresets.back(); + coreset.cfg = &phy_cfg.pdcch.coreset[csid]; + for (auto& ss : bwp.search_spaces) { + if (ss.cfg->coreset_id == csid) { + coreset.ss_list.push_back(&ss); + get_dci_locs(*coreset.cfg, *coreset.ss_list.back()->cfg, rnti, coreset.cce_positions); + } + } + } + } + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + slot_ue::slot_ue(resource_guard::token ue_token_, uint16_t rnti_, tti_point tti_rx_, uint32_t cc_) : ue_token(std::move(ue_token_)), rnti(rnti_), tti_rx(tti_rx_), cc(cc_) {} @@ -23,26 +54,19 @@ slot_ue::slot_ue(resource_guard::token ue_token_, uint16_t rnti_, tti_point tti_ ue_carrier::ue_carrier(uint16_t rnti_, uint32_t cc_, const ue_cfg_t& uecfg_) : rnti(rnti_), cc(cc_), cfg(&uecfg_) {} -void ue_carrier::set_cfg(const ue_cfg_t& uecfg) -{ - cfg = &uecfg; -} - void ue_carrier::push_feedback(srsran::move_callback callback) { pending_feedback.push_back(std::move(callback)); } -slot_ue ue_carrier::try_reserve(tti_point tti_rx, const ue_cfg_t& uecfg_) +slot_ue ue_carrier::try_reserve(tti_point tti_rx, const ue_cfg_extended& uecfg_) { slot_ue sfu(busy, rnti, tti_rx, cc); if (sfu.empty()) { return sfu; } // successfully acquired. Process any CC-specific pending feedback - if (cfg != &uecfg_) { - set_cfg(uecfg_); - } + cfg = &uecfg_; while (not pending_feedback.empty()) { pending_feedback.front()(*this); pending_feedback.pop_front(); @@ -61,8 +85,9 @@ slot_ue ue_carrier::try_reserve(tti_point tti_rx, const ue_cfg_t& uecfg_) // copy cc-specific parameters and find available HARQs sfu.cc_cfg = &uecfg_.carriers[cc]; - sfu.pdsch_tti = tti_rx + TX_ENB_DELAY + sfu.cc_cfg->pdsch_res_list[0].k0; - sfu.pusch_tti = tti_rx + TX_ENB_DELAY + sfu.cc_cfg->pusch_res_list[0].k2; + sfu.pdcch_tti = tti_rx + TX_ENB_DELAY; + sfu.pdsch_tti = sfu.pdcch_tti + sfu.cc_cfg->pdsch_res_list[0].k0; + sfu.pusch_tti = sfu.pdcch_tti + sfu.cc_cfg->pusch_res_list[0].k2; sfu.uci_tti = sfu.pdsch_tti + sfu.cc_cfg->pdsch_res_list[0].k1; sfu.dl_cqi = dl_cqi; sfu.ul_cqi = ul_cqi; @@ -85,9 +110,9 @@ slot_ue ue_carrier::try_reserve(tti_point tti_rx, const ue_cfg_t& uecfg_) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -ue::ue(uint16_t rnti, const ue_cfg_t& cfg) +ue::ue(uint16_t rnti_, const ue_cfg_t& cfg) : rnti(rnti_) { - ue_cfgs[0] = cfg; + ue_cfgs[0] = ue_cfg_extended(rnti, cfg); for (uint32_t cc = 0; cc < cfg.carriers.size(); ++cc) { if (cfg.carriers[cc].active) { carriers[cc].reset(new ue_carrier(rnti, cc, cfg)); @@ -97,8 +122,8 @@ ue::ue(uint16_t rnti, const ue_cfg_t& cfg) void ue::set_cfg(const ue_cfg_t& cfg) { - current_idx = (current_idx + 1) % ue_cfgs.size(); - ue_cfgs[current_idx] = cfg; + current_idx = (current_idx + 1U) % ue_cfgs.size(); + ue_cfgs[current_idx] = ue_cfg_extended(rnti, cfg); } slot_ue ue::try_reserve(tti_point tti_rx, uint32_t cc) diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index bf04032c0..a8e77eb3e 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -35,7 +35,6 @@ void slot_cc_worker::start(tti_point tti_rx_, ue_map_t& ue_db) // UE acquired successfully for scheduling in this {tti, cc} } - res_grid.new_tti(tti_rx_); tti_rx = tti_rx_; } @@ -51,9 +50,6 @@ void slot_cc_worker::run() alloc_ul_ues(); alloc_dl_ues(); } - - // Select the winner PDCCH allocation combination, store all the scheduling results - res_grid.generate_dcis(); } void slot_cc_worker::end_tti() @@ -100,9 +96,7 @@ void slot_cc_worker::alloc_ul_ues() sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, const sched_params& cfg_) : cfg(cfg_), ue_db(ue_db_) { for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { - for (auto& slot_grid : phy_grid[cc]) { - slot_grid = phy_slot_grid(cfg.cells[cc]); - } + cell_grid_list.emplace_back(cfg.cells[cc]); } // Note: For now, we only allow parallelism at the sector level @@ -112,7 +106,7 @@ sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, const sched_params& sem_init(&slot_ctxts[i]->sf_sem, 0, 1); slot_ctxts[i]->workers.reserve(cfg.cells.size()); for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { - slot_ctxts[i]->workers.emplace_back(cfg.cells[cc], phy_grid[cc]); + slot_ctxts[i]->workers.emplace_back(cfg.cells[cc], cell_grid_list[cc]); } } } @@ -164,18 +158,16 @@ bool sched_worker_manager::run_tti(tti_point tti_rx_, uint32_t cc, slot_res_t& t // Copy requested TTI DL and UL sched result tti_req.dl_res.pdsch_tti = tti_rx_ + TX_ENB_DELAY; - tti_req.dl_res.pdsch = phy_grid[cc][tti_req.dl_res.pdsch_tti.to_uint()].pdsch_grants; + tti_req.dl_res.pdsch = cell_grid_list[cc].bwps[0][tti_req.dl_res.pdsch_tti].pdsch_grants; + cell_grid_list[cc].bwps[0][tti_req.dl_res.pdsch_tti].reset(); tti_req.ul_res.pusch_tti = tti_rx_ + TX_ENB_DELAY; - tti_req.ul_res.pusch = phy_grid[cc][tti_req.ul_res.pusch_tti.to_uint()].pusch_grants; + tti_req.ul_res.pusch = cell_grid_list[cc].bwps[0][tti_req.ul_res.pusch_tti].pusch_grants; + cell_grid_list[cc].bwps[0][tti_req.ul_res.pusch_tti].reset(); // decrement the number of active workers int rem_workers = sf_worker_ctxt.worker_count.fetch_sub(1, std::memory_order_release) - 1; srsran_assert(rem_workers >= 0, "invalid number of calls to run_tti(tti, cc)"); - if (rem_workers == 0) { - // Clear one slot of PHY grid, so it can be reused in the next TTIs - phy_grid[cc][sf_worker_ctxt.tti_rx.to_uint()].reset(); - } return rem_workers == 0; } diff --git a/srsenb/src/stack/mac/sched_grid.cc b/srsenb/src/stack/mac/sched_grid.cc index 3a79b462d..4b3813195 100644 --- a/srsenb/src/stack/mac/sched_grid.cc +++ b/srsenb/src/stack/mac/sched_grid.cc @@ -16,33 +16,6 @@ namespace srsenb { -const char* to_string(alloc_result result) -{ - switch (result) { - case alloc_result::success: - return "success"; - case alloc_result::sch_collision: - return "Collision with existing SCH allocations"; - case alloc_result::other_cause: - return "error"; - case alloc_result::no_cch_space: - return "No space available in PUCCH or PDCCH"; - case alloc_result::no_sch_space: - return "Requested number of PRBs not available"; - case alloc_result::no_rnti_opportunity: - return "rnti cannot be allocated (e.g. already allocated, no data, meas gap collision, carrier inactive, etc.)"; - case alloc_result::invalid_grant_params: - return "invalid grant arguments (e.g. invalid prb mask)"; - case alloc_result::invalid_coderate: - return "Effective coderate exceeds threshold"; - case alloc_result::no_grant_space: - return "Max number of allocations reached"; - default: - break; - } - return "unknown error"; -} - void sf_sched_result::new_tti(tti_point tti_rx_) { assert(tti_rx != tti_rx_); diff --git a/srsenb/src/stack/mac/sched_phy_ch/sched_dci.cc b/srsenb/src/stack/mac/sched_phy_ch/sched_dci.cc index 3e964082b..d1fe66035 100644 --- a/srsenb/src/stack/mac/sched_phy_ch/sched_dci.cc +++ b/srsenb/src/stack/mac/sched_phy_ch/sched_dci.cc @@ -11,8 +11,8 @@ */ #include "srsenb/hdr/stack/mac/sched_phy_ch/sched_dci.h" -#include "srsenb/hdr/stack/mac/sched_common.h" #include "srsenb/hdr/stack/mac/sched_helpers.h" +#include "srsenb/hdr/stack/mac/sched_lte_common.h" #include "srsran/common/string_helpers.h" #include diff --git a/srsenb/test/mac/nr/sched_nr_sim_ue.cc b/srsenb/test/mac/nr/sched_nr_sim_ue.cc index 86e9bbef9..599efbc27 100644 --- a/srsenb/test/mac/nr/sched_nr_sim_ue.cc +++ b/srsenb/test/mac/nr/sched_nr_sim_ue.cc @@ -93,8 +93,8 @@ int sched_nr_sim_base::add_user(uint16_t rnti, const sched_nr_interface::ue_cfg_ { TESTASSERT(ue_db.count(rnti) == 0); - ue_db.insert(std::make_pair(rnti, sched_nr_ue_sim(rnti, ue_cfg_, current_tti_rx, preamble_idx))); sched_ptr->ue_cfg(rnti, ue_cfg_); + ue_db.insert(std::make_pair(rnti, sched_nr_ue_sim(rnti, ue_cfg_, current_tti_rx, preamble_idx))); return SRSRAN_SUCCESS; } diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index b3638c5c9..98dd3daeb 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -17,6 +17,33 @@ namespace srsenb { +sched_nr_interface::ue_cfg_t get_default_ue_cfg(uint32_t nof_cc) +{ + sched_nr_interface::ue_cfg_t uecfg{}; + uecfg.carriers.resize(nof_cc); + for (uint32_t cc = 0; cc < nof_cc; ++cc) { + uecfg.carriers[cc].active = true; + } + uecfg.phy_cfg.pdcch.coreset_present[0] = true; + uecfg.phy_cfg.pdcch.coreset[0].id = 0; + for (uint32_t i = 0; i < 100 / 6; ++i) { + uecfg.phy_cfg.pdcch.coreset[0].freq_resources[i] = true; + } + uecfg.phy_cfg.pdcch.coreset[0].duration = 1; + uecfg.phy_cfg.pdcch.search_space_present[0] = true; + uecfg.phy_cfg.pdcch.search_space[0].id = 0; + uecfg.phy_cfg.pdcch.search_space[0].coreset_id = 0; + uecfg.phy_cfg.pdcch.search_space[0].duration = 1; + uecfg.phy_cfg.pdcch.search_space[0].type = srsran_search_space_type_common_0; + uecfg.phy_cfg.pdcch.search_space[0].nof_candidates[0] = 1; + uecfg.phy_cfg.pdcch.search_space[0].nof_candidates[1] = 1; + uecfg.phy_cfg.pdcch.search_space[0].nof_candidates[2] = 1; + uecfg.phy_cfg.pdcch.search_space[0].nof_candidates[3] = 1; + uecfg.phy_cfg.pdcch.search_space[0].nof_formats = 1; + uecfg.phy_cfg.pdcch.search_space[0].formats[0] = srsran_dci_format_nr_0_0; + return uecfg; +} + struct task_job_manager { std::mutex mutex; std::condition_variable cond_var; @@ -70,10 +97,7 @@ void sched_nr_cfg_serialized_test() sched_nr_sim_base sched_tester(cfg, cells_cfg, "Serialized Test"); - sched_nr_interface::ue_cfg_t uecfg; - uecfg.carriers.resize(nof_sectors); - uecfg.carriers[0].active = true; - uecfg.carriers[1].active = true; + sched_nr_interface::ue_cfg_t uecfg = get_default_ue_cfg(2); sched_tester.add_user(0x46, uecfg, 0); @@ -107,11 +131,7 @@ void sched_nr_cfg_parallel_cc_test() sched_nr_sim_base sched_tester(cfg, cells_cfg, "Parallel CC Test"); - sched_nr_interface::ue_cfg_t uecfg; - uecfg.carriers.resize(cells_cfg.size()); - for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { - uecfg.carriers[cc].active = true; - } + sched_nr_interface::ue_cfg_t uecfg = get_default_ue_cfg(cells_cfg.size()); sched_tester.add_user(0x46, uecfg, 0); for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { @@ -148,11 +168,7 @@ void sched_nr_cfg_parallel_sf_test() sched_nr sched(cfg); sched.cell_cfg(cells_cfg); - sched_nr_interface::ue_cfg_t uecfg; - uecfg.carriers.resize(cells_cfg.size()); - for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { - uecfg.carriers[cc].active = true; - } + sched_nr_interface::ue_cfg_t uecfg = get_default_ue_cfg(cells_cfg.size()); sched.ue_cfg(0x46, uecfg); for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { diff --git a/srsenb/test/mac/sched_common_test_suite.h b/srsenb/test/mac/sched_common_test_suite.h index 4568b97dc..7ff5c9f93 100644 --- a/srsenb/test/mac/sched_common_test_suite.h +++ b/srsenb/test/mac/sched_common_test_suite.h @@ -13,7 +13,7 @@ #ifndef SRSRAN_SCHED_COMMON_TEST_SUITE_H #define SRSRAN_SCHED_COMMON_TEST_SUITE_H -#include "srsenb/hdr/stack/mac/sched_common.h" +#include "srsenb/hdr/stack/mac/sched_lte_common.h" #include "srsenb/hdr/stack/mac/sched_phy_ch/sched_phy_resource.h" #include "srsran/adt/span.h" #include "srsran/common/tti_point.h" diff --git a/srsenb/test/mac/sched_dci_test.cc b/srsenb/test/mac/sched_dci_test.cc index 6f78e615b..9d59b58f2 100644 --- a/srsenb/test/mac/sched_dci_test.cc +++ b/srsenb/test/mac/sched_dci_test.cc @@ -11,7 +11,7 @@ */ #include "sched_test_utils.h" -#include "srsenb/hdr/stack/mac/sched_common.h" +#include "srsenb/hdr/stack/mac/sched_lte_common.h" #include "srsenb/hdr/stack/mac/sched_phy_ch/sched_dci.h" #include "srsran/common/common_lte.h" #include "srsran/common/test_common.h" From 4c316aa9ea1687df4e4f407a7aaf73f095eaeca7 Mon Sep 17 00:00:00 2001 From: Francisco Date: Mon, 28 Jun 2021 14:33:38 +0100 Subject: [PATCH 37/43] sched,nr: integrate mac-phy interface types into the scheduler --- srsenb/hdr/stack/mac/nr/sched_nr_common.h | 2 + srsenb/hdr/stack/mac/nr/sched_nr_harq.h | 2 + srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 20 ++-- srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h | 16 ++- .../hdr/stack/mac/nr/sched_nr_phy_helpers.h | 33 ++++++ srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h | 12 ++- srsenb/src/stack/mac/nr/CMakeLists.txt | 2 +- .../src/stack/mac/nr/sched_nr_phy_helpers.cc | 102 ++++++++++++++++++ srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 25 +++-- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 3 +- srsenb/test/mac/nr/sched_nr_sim_ue.cc | 4 +- srsenb/test/mac/nr/sched_nr_test.cc | 6 +- 12 files changed, 193 insertions(+), 34 deletions(-) create mode 100644 srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h create mode 100644 srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_common.h b/srsenb/hdr/stack/mac/nr/sched_nr_common.h index 51d82c58b..669d8f6b0 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_common.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_common.h @@ -25,6 +25,8 @@ static const size_t MAX_NOF_AGGR_LEVELS = 5; namespace sched_nr_impl { +const static size_t MAX_GRANTS = sched_nr_interface::MAX_GRANTS; + using sched_cfg_t = sched_nr_interface::sched_cfg_t; using cell_cfg_t = sched_nr_interface::cell_cfg_t; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h index 3b7fa4280..464c57814 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h @@ -34,6 +34,8 @@ public: uint32_t nof_retx() const { return tb[0].n_rtx; } uint32_t max_nof_retx() const { return max_retx; } uint32_t tbs() const { return tb[0].tbs; } + uint32_t ndi() const { return tb[0].ndi; } + uint32_t mcs() const { return tb[0].mcs; } bool ack_info(uint32_t tb_idx, bool ack); diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index f69a1200c..10ec47495 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -17,6 +17,7 @@ #include "srsran/adt/bounded_vector.h" #include "srsran/adt/span.h" #include "srsran/common/tti_point.h" +#include "srsran/interfaces/gnb_interfaces.h" #include "srsran/interfaces/rrc_nr_interface_types.h" #include "srsran/phy/phch/dci_nr.h" @@ -78,15 +79,22 @@ public: ///// Sched Result ///// - struct pdsch_grant { - srsran_dci_dl_nr_t dci; - rbg_bitmap bitmap; + const static int MAX_GRANTS = 64; + + using pdcch_dl_t = mac_interface_phy_nr::pdcch_dl_t; + using pdcch_ul_t = mac_interface_phy_nr::pdcch_ul_t; + using pdcch_dl_list_t = srsran::bounded_vector; + using pdcch_ul_list_t = srsran::bounded_vector; + + struct pdsch_t { + srsran_sch_cfg_nr_t sch = {}; ///< PDSCH configuration }; - using pdsch_list = srsran::bounded_vector; + using pdsch_list_t = srsran::bounded_vector; struct dl_tti_request_t { - tti_point pdsch_tti; - pdsch_list pdsch; + tti_point pdsch_tti; + pdcch_dl_list_t pdcchs; + pdsch_list_t pdschs; }; struct pusch_grant { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h index 78741d5c1..c0f4c6882 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h @@ -29,12 +29,10 @@ enum class pdcch_grant_type_t { sib, dl_data, ul_data }; class slot_ue; -struct pdcch_dl_t { - srsran_dci_cfg_nr_t dci_cfg = {}; - srsran_dci_dl_nr_t dci = {}; -}; -static const size_t MAX_NOF_PDCCH_DL_GRANTS = 16; -using pdcch_dl_list_t = srsran::bounded_vector; +using pdcch_dl_t = sched_nr_interface::pdcch_dl_t; +using pdcch_dl_list_t = sched_nr_interface::pdcch_dl_list_t; +using pdcch_ul_t = sched_nr_interface::pdcch_ul_t; +using pdcch_ul_list_t = sched_nr_interface::pdcch_ul_list_t; class coreset_region { @@ -76,8 +74,8 @@ private: pdcch_grant_type_t alloc_type; slot_ue* ue; }; - srsran::bounded_vector dci_list; - pdcch_dl_list_t& pdcch_dl_list; + srsran::bounded_vector dci_list; + pdcch_dl_list_t& pdcch_dl_list; // DFS decision tree of PDCCH grants struct tree_node { @@ -88,7 +86,7 @@ private: /// Accumulation of all PDCCH masks for the current solution (DFS path) coreset_bitmap total_mask, current_mask; }; - using alloc_tree_dfs_t = srsran::bounded_vector; + using alloc_tree_dfs_t = srsran::bounded_vector; alloc_tree_dfs_t dfs_tree, saved_dfs_tree; srsran::span get_cce_loc_table(const alloc_record& record) const; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h b/srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h new file mode 100644 index 000000000..d72582209 --- /dev/null +++ b/srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h @@ -0,0 +1,33 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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. + * + */ + +#ifndef SRSRAN_SCHED_NR_PHY_HELPERS_H +#define SRSRAN_SCHED_NR_PHY_HELPERS_H + +#include "sched_nr_common.h" + +namespace srsenb { +namespace sched_nr_impl { + +uint32_t get_P(uint32_t bwp_nof_prb, bool config_1_or_2); +uint32_t get_nof_rbgs(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2); + +void bitmap_to_prb_array(const rbgmask_t& bitmap, uint32_t bwp_nof_prb, srsran_sch_grant_nr_t& grant); + +class slot_ue; +void fill_dci_ue_cfg(const slot_ue& ue, srsran_dci_dl_nr_t& dci); +void fill_dci_ue_cfg(const slot_ue& ue, srsran_dci_ul_nr_t& dci); + +} // namespace sched_nr_impl +} // namespace srsenb + +#endif // SRSRAN_SCHED_NR_PHY_HELPERS_H diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h index 2f2d6c408..23602693e 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h @@ -25,7 +25,9 @@ namespace sched_nr_impl { using pdsch_bitmap = srsran::bounded_bitset<25, true>; using pusch_bitmap = srsran::bounded_bitset<25, true>; -using pdsch_list = sched_nr_interface::pdsch_list; +using pdsch_t = sched_nr_interface::pdsch_t; +using pdsch_list_t = sched_nr_interface::pdsch_list_t; + using pusch_list = sched_nr_interface::pusch_list; struct pucch_t {}; @@ -35,9 +37,10 @@ using slot_coreset_list = srsran::bounded_vector pucch_grants; @@ -53,9 +56,12 @@ struct bwp_res_grid { bwp_slot_grid& operator[](tti_point tti) { return slots[tti.sf_idx()]; }; const bwp_slot_grid& operator[](tti_point tti) const { return slots[tti.sf_idx()]; }; uint32_t id() const { return bwp_id; } + uint32_t nof_prbs() const { return cell_cfg->cell_cfg.nof_prb; } private: - uint32_t bwp_id; + uint32_t bwp_id; + const sched_cell_params* cell_cfg = nullptr; + srsran::bounded_vector slots; }; diff --git a/srsenb/src/stack/mac/nr/CMakeLists.txt b/srsenb/src/stack/mac/nr/CMakeLists.txt index 76499a48f..dee5663ec 100644 --- a/srsenb/src/stack/mac/nr/CMakeLists.txt +++ b/srsenb/src/stack/mac/nr/CMakeLists.txt @@ -6,6 +6,6 @@ # the distribution. # -set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc sched_nr_rb_grid.cc sched_nr_harq.cc sched_nr_pdcch.cc sched_nr_common.cc) +set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc sched_nr_rb_grid.cc sched_nr_harq.cc sched_nr_pdcch.cc sched_nr_common.cc sched_nr_phy_helpers.cc) add_library(srsgnb_mac STATIC ${SOURCES}) diff --git a/srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc b/srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc new file mode 100644 index 000000000..c4f014ee6 --- /dev/null +++ b/srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc @@ -0,0 +1,102 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 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 "srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_harq.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_ue.h" + +namespace srsenb { +namespace sched_nr_impl { + +/// Table 6.1.2.2.1-1 - Nominal RBG size P +uint32_t get_P(uint32_t bwp_nof_prb, bool config_1_or_2) +{ + srsran_assert(bwp_nof_prb > 0 and bwp_nof_prb <= 275, "Invalid BWP size"); + if (bwp_nof_prb <= 36) { + return config_1_or_2 ? 2 : 4; + } + if (bwp_nof_prb <= 72) { + return config_1_or_2 ? 4 : 8; + } + if (bwp_nof_prb <= 144) { + return config_1_or_2 ? 8 : 16; + } + return 16; +} + +uint32_t get_nof_rbgs(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2) +{ + uint32_t P = get_P(bwp_nof_prb, config1_or_2); + return srsran::ceil_div(bwp_nof_prb + (bwp_start % P), P); +} + +uint32_t get_rbg_size(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2, uint32_t rbg_idx) +{ + uint32_t P = get_P(bwp_nof_prb, config1_or_2); + uint32_t nof_rbgs = get_nof_rbgs(bwp_nof_prb, bwp_start, config1_or_2); + if (rbg_idx == 0) { + return P - (bwp_start % P); + } + if (rbg_idx == nof_rbgs - 1) { + uint32_t ret = (bwp_start + bwp_nof_prb) % P; + return ret > 0 ? ret : P; + } + return P; +} + +void bitmap_to_prb_array(const rbgmask_t& bitmap, uint32_t bwp_nof_prb, srsran_sch_grant_nr_t& grant) +{ + uint32_t count = 0; + grant.nof_prb = bwp_nof_prb; + for (uint32_t rbg = 0; rbg < bitmap.size(); ++rbg) { + bool val = bitmap.test(rbg); + uint32_t rbg_size = get_rbg_size(bwp_nof_prb, 0, true, rbg); + for (uint32_t prb = count; prb < count + rbg_size; ++prb) { + grant.prb_idx[prb] = val; + } + } +} + +void fill_dci_harq(const harq_proc& h, srsran_dci_dl_nr_t& dci) +{ + dci.pid = h.pid; + dci.ndi = h.ndi(); + dci.mcs = h.mcs(); +} + +void fill_dci_ue_cfg(const slot_ue& ue, srsran_dci_dl_nr_t& dci) +{ + dci.bwp_id = ue.bwp_id; + dci.cc_id = ue.cc; + dci.ctx.rnti = ue.rnti; + dci.tpc = 1; + fill_dci_harq(*ue.h_dl, dci); +} + +void fill_dci_harq(const harq_proc& h, srsran_dci_ul_nr_t& dci) +{ + dci.pid = h.pid; + dci.ndi = h.ndi(); + dci.mcs = h.mcs(); +} + +void fill_dci_ue_cfg(const slot_ue& ue, srsran_dci_ul_nr_t& dci) +{ + dci.bwp_id = ue.bwp_id; + dci.cc_id = ue.cc; + dci.ctx.rnti = ue.rnti; + dci.tpc = 1; + fill_dci_harq(*ue.h_ul, dci); +} + +} // namespace sched_nr_impl +} // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc index 3245388fe..276998309 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -11,11 +11,11 @@ */ #include "srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h" namespace srsenb { namespace sched_nr_impl { -using pdsch_grant = sched_nr_interface::pdsch_grant; using pusch_grant = sched_nr_interface::pusch_grant; bwp_slot_grid::bwp_slot_grid(const sched_cell_params& cell_params, uint32_t bwp_id_, uint32_t slot_idx_) : @@ -37,7 +37,7 @@ void bwp_slot_grid::reset() pucch_grants.clear(); } -bwp_res_grid::bwp_res_grid(const sched_cell_params& cell_cfg_, uint32_t bwp_id_) : bwp_id(bwp_id_) +bwp_res_grid::bwp_res_grid(const sched_cell_params& cell_cfg_, uint32_t bwp_id_) : bwp_id(bwp_id_), cell_cfg(&cell_cfg_) { for (uint32_t sl = 0; sl < SCHED_NR_NOF_SUBFRAMES; ++sl) { slots.emplace_back(cell_cfg_, bwp_id, sl); @@ -63,7 +63,7 @@ alloc_result slot_bwp_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) logger.warning("SCHED: Trying to allocate PDSCH for rnti=0x%x with no available HARQs", ue.rnti); return alloc_result::no_rnti_opportunity; } - pdsch_list& pdsch_grants = bwp_grid[ue.pdsch_tti].pdsch_grants; + pdsch_list_t& pdsch_grants = bwp_grid[ue.pdsch_tti].pdsch_grants; if (pdsch_grants.full()) { logger.warning("SCHED: Maximum number of DL allocations reached"); return alloc_result::no_grant_space; @@ -91,11 +91,12 @@ alloc_result slot_bwp_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) } // Allocation Successful + pdcch_dl_t& pdcch = bwp_grid[ue.pdcch_tti].pdcch_dl_list.back(); + fill_dci_ue_cfg(ue, pdcch.dci); pdsch_grants.emplace_back(); - pdsch_grant& grant = pdsch_grants.back(); - grant.dci.ctx.rnti = ue.rnti; - grant.dci.pid = ue.h_dl->pid; - grant.bitmap = dl_mask; + pdsch_t& grant = pdsch_grants.back(); + grant.sch.grant.rnti = ue.rnti; + bitmap_to_prb_array(dl_mask, bwp_grid.nof_prbs(), grant.sch.grant); pdsch_mask |= dl_mask; return alloc_result::success; @@ -116,6 +117,12 @@ alloc_result slot_bwp_sched::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) if ((pusch_mask & ul_mask).any()) { return alloc_result::sch_collision; } + const uint32_t aggr_idx = 3, coreset_id = 0; + if (not bwp_grid[ue.pdcch_tti].coresets[coreset_id].alloc_dci( + pdcch_grant_type_t::ul_data, aggr_idx, coreset_id, &ue)) { + // Could not find space in PDCCH + return alloc_result::no_cch_space; + } int mcs = -1, tbs = -1; if (ue.h_ul->empty()) { @@ -129,11 +136,11 @@ alloc_result slot_bwp_sched::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) } // Allocation Successful + pdcch_ul_t& pdcch = bwp_grid[ue.pdcch_tti].pdcch_ul_list.back(); + fill_dci_ue_cfg(ue, pdcch.dci); pusch_grants.emplace_back(); pusch_grant& grant = pusch_grants.back(); grant.dci.ctx.rnti = ue.rnti; - grant.dci.pid = ue.h_dl->pid; - grant.dci.mcs = mcs; grant.bitmap = ul_mask; pusch_mask |= ul_mask; diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index a8e77eb3e..d6a4dc8d9 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -158,7 +158,8 @@ bool sched_worker_manager::run_tti(tti_point tti_rx_, uint32_t cc, slot_res_t& t // Copy requested TTI DL and UL sched result tti_req.dl_res.pdsch_tti = tti_rx_ + TX_ENB_DELAY; - tti_req.dl_res.pdsch = cell_grid_list[cc].bwps[0][tti_req.dl_res.pdsch_tti].pdsch_grants; + tti_req.dl_res.pdcchs = cell_grid_list[cc].bwps[0][tti_req.dl_res.pdsch_tti].pdcch_dl_list; + tti_req.dl_res.pdschs = cell_grid_list[cc].bwps[0][tti_req.dl_res.pdsch_tti].pdsch_grants; cell_grid_list[cc].bwps[0][tti_req.dl_res.pdsch_tti].reset(); tti_req.ul_res.pusch_tti = tti_rx_ + TX_ENB_DELAY; tti_req.ul_res.pusch = cell_grid_list[cc].bwps[0][tti_req.ul_res.pusch_tti].pusch_grants; diff --git a/srsenb/test/mac/nr/sched_nr_sim_ue.cc b/srsenb/test/mac/nr/sched_nr_sim_ue.cc index 599efbc27..807ac7a53 100644 --- a/srsenb/test/mac/nr/sched_nr_sim_ue.cc +++ b/srsenb/test/mac/nr/sched_nr_sim_ue.cc @@ -44,8 +44,8 @@ int sched_nr_ue_sim::update(const sched_nr_cc_output_res_t& cc_out) void sched_nr_ue_sim::update_dl_harqs(const sched_nr_cc_output_res_t& cc_out) { uint32_t cc = cc_out.cc; - for (uint32_t i = 0; i < cc_out.dl_cc_result->pdsch.size(); ++i) { - const auto& data = cc_out.dl_cc_result->pdsch[i]; + for (uint32_t i = 0; i < cc_out.dl_cc_result->pdschs.size(); ++i) { + const auto& data = cc_out.dl_cc_result->pdcchs[i]; if (data.dci.ctx.rnti != ctxt.rnti) { continue; } diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index 98dd3daeb..9b622f0b6 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -64,9 +64,9 @@ struct task_job_manager { void finish_task(const sched_nr_interface::tti_request_t& res) { std::unique_lock lock(mutex); - TESTASSERT(res.dl_res.pdsch.size() <= 1); + TESTASSERT(res.dl_res.pdschs.size() <= 1); res_count++; - pdsch_count += res.dl_res.pdsch.size(); + pdsch_count += res.dl_res.pdschs.size(); if (tasks-- >= max_tasks or tasks == 0) { cond_var.notify_one(); } @@ -111,7 +111,7 @@ void sched_nr_cfg_serialized_test() sched_nr_cc_output_res_t out{tti, cc, &res.dl_res, &res.ul_res}; sched_tester.update(out); tasks.finish_task(res); - TESTASSERT(res.dl_res.pdsch.size() == 1); + TESTASSERT(res.dl_res.pdschs.size() == 1); } } From b6a3b8c5b1e1359ae6433e99b7a444b975e763e5 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 29 Jun 2021 14:25:14 +0200 Subject: [PATCH 38/43] rlc: fix dtor TSAN was complaining about destroying a locked mutex --- lib/src/upper/rlc.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index 389130857..16559bf5c 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -27,9 +27,11 @@ rlc::rlc(const char* logname) : logger(srslog::fetch_basic_logger(logname)), poo rlc::~rlc() { // destroy all remaining entities - srsran::rwlock_write_guard lock(rwlock); - rlc_array.clear(); - rlc_array_mrb.clear(); + { + srsran::rwlock_write_guard lock(rwlock); + rlc_array.clear(); + rlc_array_mrb.clear(); + } pthread_rwlock_destroy(&rwlock); } From 4d014e7cebdaab592576eaf8fd4ea55df0dfa630 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 29 Jun 2021 10:14:53 +0100 Subject: [PATCH 39/43] s1ap,feature: make the ts1 reloc timers configurable via the enb.conf --- lib/include/srsran/interfaces/enb_s1ap_interfaces.h | 2 ++ lib/include/srsran/interfaces/sched_interface.h | 2 +- srsenb/enb.conf.example | 4 ++++ srsenb/hdr/stack/s1ap/s1ap.h | 3 --- srsenb/src/main.cc | 2 ++ srsenb/src/stack/s1ap/s1ap.cc | 4 ++-- 6 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/include/srsran/interfaces/enb_s1ap_interfaces.h b/lib/include/srsran/interfaces/enb_s1ap_interfaces.h index 233857470..5e6b11859 100644 --- a/lib/include/srsran/interfaces/enb_s1ap_interfaces.h +++ b/lib/include/srsran/interfaces/enb_s1ap_interfaces.h @@ -30,6 +30,8 @@ struct s1ap_args_t { std::string s1c_bind_addr; uint16_t s1c_bind_port; std::string enb_name; + uint32_t ts1_reloc_prep_timeout; + uint32_t ts1_reloc_overall_timeout; }; // S1AP interface for RRC diff --git a/lib/include/srsran/interfaces/sched_interface.h b/lib/include/srsran/interfaces/sched_interface.h index e9549b244..ec9d3a32d 100644 --- a/lib/include/srsran/interfaces/sched_interface.h +++ b/lib/include/srsran/interfaces/sched_interface.h @@ -55,7 +55,7 @@ public: uint32_t max_nof_ctrl_symbols = 3; int min_aggr_level = 0; int max_aggr_level = 3; - bool adaptive_aggr_level = true; + bool adaptive_aggr_level = false; bool pucch_mux_enabled = false; float target_bler = 0.05; float max_delta_dl_cqi = 5; diff --git a/srsenb/enb.conf.example b/srsenb/enb.conf.example index 4eacc23e1..ceed0689a 100644 --- a/srsenb/enb.conf.example +++ b/srsenb/enb.conf.example @@ -333,6 +333,8 @@ enable = false # eea_pref_list: Ordered preference list for the selection of encryption algorithm (EEA) (default: EEA0, EEA2, EEA1). # eia_pref_list: Ordered preference list for the selection of integrity algorithm (EIA) (default: EIA2, EIA1, EIA0). # gtpu_tunnel_timeout: Time that GTPU takes to release indirect forwarding tunnel since the last received GTPU PDU (0 for no timer). +#ts1_reloc_prep_timeout: S1AP TS 36.413 TS1RelocPrep Expiry Timeout value in milliseconds +#ts1_reloc_overall_timeout: S1AP TS 36.413 TS1RelocPrep Expiry Timeout value in milliseconds # ##################################################################### [expert] @@ -361,3 +363,5 @@ enable = false #eia_pref_list = EIA2, EIA1, EIA0 #gtpu_tunnel_timeout = 0 #extended_cp = false +#ts1_reloc_prep_timeout = 10000 +#ts1_reloc_overall_timeout = 10000 diff --git a/srsenb/hdr/stack/s1ap/s1ap.h b/srsenb/hdr/stack/s1ap/s1ap.h index 57b330f4e..0be19f3b5 100644 --- a/srsenb/hdr/stack/s1ap/s1ap.h +++ b/srsenb/hdr/stack/s1ap/s1ap.h @@ -55,9 +55,6 @@ public: using erab_id_list = srsran::bounded_vector; using erab_item_list = srsran::bounded_vector; - static const uint32_t ts1_reloc_prep_timeout_ms = 10000; - static const uint32_t ts1_reloc_overall_timeout_ms = 10000; - s1ap(srsran::task_sched_handle task_sched_, srslog::basic_logger& logger, srsran::socket_manager_itf* rx_socket_handler); diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 3b264fe74..a3f31fb26 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -234,6 +234,8 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("expert.gtpu_tunnel_timeout", bpo::value(&args->stack.gtpu_indirect_tunnel_timeout_msec)->default_value(0), "Maximum time that GTPU takes to release indirect forwarding tunnel since the last received GTPU PDU. (0 for infinity)") ("expert.rlf_release_timer_ms", bpo::value(&args->general.rlf_release_timer_ms)->default_value(4000), "Time taken by eNB to release UE context after it detects an RLF") ("expert.extended_cp", bpo::value(&args->phy.extended_cp)->default_value(false), "Use extended cyclic prefix") + ("expert.ts1_reloc_prep_timeout", bpo::value(&args->stack.s1ap.ts1_reloc_prep_timeout)->default_value(10000), "S1AP TS 36.413 TS1RelocPrep Expiry Timeout value in milliseconds") + ("expert.ts1_reloc_overall_timeout", bpo::value(&args->stack.s1ap.ts1_reloc_overall_timeout)->default_value(10000), "S1AP TS 36.413 TS1RelocPrep Expiry Timeout value in milliseconds") // eMBMS section diff --git a/srsenb/src/stack/s1ap/s1ap.cc b/srsenb/src/stack/s1ap/s1ap.cc index 9ad267ea4..e5302c2e2 100644 --- a/srsenb/src/stack/s1ap/s1ap.cc +++ b/srsenb/src/stack/s1ap/s1ap.cc @@ -2006,10 +2006,10 @@ s1ap::ue::ue(s1ap* s1ap_ptr_) : s1ap_ptr(s1ap_ptr_), ho_prep_proc(this), logger( // initialize timers ts1_reloc_prep = s1ap_ptr->task_sched.get_unique_timer(); - ts1_reloc_prep.set(ts1_reloc_prep_timeout_ms, + ts1_reloc_prep.set(s1ap_ptr->args.ts1_reloc_prep_timeout, [this](uint32_t tid) { ho_prep_proc.trigger(ho_prep_proc_t::ts1_reloc_prep_expired{}); }); ts1_reloc_overall = s1ap_ptr->task_sched.get_unique_timer(); - ts1_reloc_overall.set(ts1_reloc_overall_timeout_ms, [this](uint32_t tid) { + ts1_reloc_overall.set(s1ap_ptr->args.ts1_reloc_overall_timeout, [this](uint32_t tid) { //> If the UE Context Release procedure is not initiated towards the eNB before the expiry of the timer // TS1RELOCOverall, the eNB shall request the MME to release the UE context. s1ap_ptr->user_release(ctxt.rnti, asn1::s1ap::cause_radio_network_opts::ts1relocoverall_expiry); From 30802777cf9aef539536b9d325131c8b32c03cbf Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 29 Jun 2021 12:45:14 +0100 Subject: [PATCH 40/43] fix,enb: fix enb.conf param description --- srsenb/enb.conf.example | 2 +- srsenb/src/main.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/srsenb/enb.conf.example b/srsenb/enb.conf.example index ceed0689a..f7760089d 100644 --- a/srsenb/enb.conf.example +++ b/srsenb/enb.conf.example @@ -334,7 +334,7 @@ enable = false # eia_pref_list: Ordered preference list for the selection of integrity algorithm (EIA) (default: EIA2, EIA1, EIA0). # gtpu_tunnel_timeout: Time that GTPU takes to release indirect forwarding tunnel since the last received GTPU PDU (0 for no timer). #ts1_reloc_prep_timeout: S1AP TS 36.413 TS1RelocPrep Expiry Timeout value in milliseconds -#ts1_reloc_overall_timeout: S1AP TS 36.413 TS1RelocPrep Expiry Timeout value in milliseconds +#ts1_reloc_overall_timeout: S1AP TS 36.413 TS1RelocOverall Expiry Timeout value in milliseconds # ##################################################################### [expert] diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index a3f31fb26..6a94d7379 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -235,7 +235,7 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("expert.rlf_release_timer_ms", bpo::value(&args->general.rlf_release_timer_ms)->default_value(4000), "Time taken by eNB to release UE context after it detects an RLF") ("expert.extended_cp", bpo::value(&args->phy.extended_cp)->default_value(false), "Use extended cyclic prefix") ("expert.ts1_reloc_prep_timeout", bpo::value(&args->stack.s1ap.ts1_reloc_prep_timeout)->default_value(10000), "S1AP TS 36.413 TS1RelocPrep Expiry Timeout value in milliseconds") - ("expert.ts1_reloc_overall_timeout", bpo::value(&args->stack.s1ap.ts1_reloc_overall_timeout)->default_value(10000), "S1AP TS 36.413 TS1RelocPrep Expiry Timeout value in milliseconds") + ("expert.ts1_reloc_overall_timeout", bpo::value(&args->stack.s1ap.ts1_reloc_overall_timeout)->default_value(10000), "S1AP TS 36.413 TS1RelocOverall Expiry Timeout value in milliseconds") // eMBMS section From 171d5727bef97461dcac08883fd9f70bf2d831a8 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 25 Jun 2021 14:24:56 +0100 Subject: [PATCH 41/43] Moved lib RLC into it's own folder --- .../srsran/interfaces/enb_metrics_interface.h | 2 +- .../srsran/{upper => rlc}/bearer_mem_pool.h | 0 lib/include/srsran/{upper => rlc}/rlc.h | 6 +- .../srsran/{upper => rlc}/rlc_am_base.h | 2 +- .../srsran/{upper => rlc}/rlc_am_lte.h | 10 +-- lib/include/srsran/{upper => rlc}/rlc_am_nr.h | 2 +- .../srsran/{upper => rlc}/rlc_common.h | 4 +- .../srsran/{upper => rlc}/rlc_metrics.h | 0 lib/include/srsran/{upper => rlc}/rlc_tm.h | 2 +- .../srsran/{upper => rlc}/rlc_um_base.h | 2 +- .../srsran/{upper => rlc}/rlc_um_lte.h | 2 +- lib/include/srsran/{upper => rlc}/rlc_um_nr.h | 2 +- lib/src/CMakeLists.txt | 1 + lib/src/rlc/CMakeLists.txt | 21 ++++++ lib/src/{upper => rlc}/bearer_mem_pool.cc | 8 +-- lib/src/{upper => rlc}/rlc.cc | 12 ++-- lib/src/{upper => rlc}/rlc_am_base.cc | 2 +- lib/src/{upper => rlc}/rlc_am_lte.cc | 2 +- lib/src/{upper => rlc}/rlc_am_nr.cc | 2 +- lib/src/{upper => rlc}/rlc_tm.cc | 2 +- lib/src/{upper => rlc}/rlc_um_base.cc | 2 +- lib/src/{upper => rlc}/rlc_um_lte.cc | 2 +- lib/src/{upper => rlc}/rlc_um_nr.cc | 2 +- lib/src/upper/CMakeLists.txt | 11 +--- lib/test/rlc/CMakeLists.txt | 64 +++++++++++++++++++ .../{upper => rlc}/rlc_am_control_test.cc | 0 lib/test/{upper => rlc}/rlc_am_data_test.cc | 0 lib/test/{upper => rlc}/rlc_am_nr_pdu_test.cc | 0 lib/test/{upper => rlc}/rlc_am_test.cc | 0 lib/test/{upper => rlc}/rlc_common_test.cc | 0 lib/test/{upper => rlc}/rlc_stress_test.cc | 0 lib/test/{upper => rlc}/rlc_test_common.h | 0 lib/test/{upper => rlc}/rlc_um_data_test.cc | 0 lib/test/{upper => rlc}/rlc_um_nr_pdu_test.cc | 0 lib/test/{upper => rlc}/rlc_um_nr_test.cc | 0 lib/test/{upper => rlc}/rlc_um_test.cc | 0 lib/test/upper/CMakeLists.txt | 45 ------------- srsenb/hdr/stack/upper/rlc.h | 2 +- srsenb/hdr/stack/upper/rlc_nr.h | 2 +- srsenb/src/CMakeLists.txt | 2 +- srsenb/src/common/rnti_pool.cc | 2 +- srsenb/src/stack/enb_stack_lte.cc | 2 +- srsue/hdr/stack/ue_stack_lte.h | 2 +- srsue/hdr/stack/ue_stack_nr.h | 2 +- srsue/hdr/ue_metrics_interface.h | 2 +- srsue/src/CMakeLists.txt | 2 +- srsue/src/test/ttcn3/hdr/ttcn3_syssim.h | 2 +- srsue/src/test/ttcn3/src/CMakeLists.txt | 1 + srsue/src/test/ttcn3/src/ttcn3_syssim.cc | 2 +- 49 files changed, 133 insertions(+), 100 deletions(-) rename lib/include/srsran/{upper => rlc}/bearer_mem_pool.h (100%) rename lib/include/srsran/{upper => rlc}/rlc.h (97%) rename lib/include/srsran/{upper => rlc}/rlc_am_base.h (95%) rename lib/include/srsran/{upper => rlc}/rlc_am_lte.h (98%) rename lib/include/srsran/{upper => rlc}/rlc_am_nr.h (98%) rename lib/include/srsran/{upper => rlc}/rlc_common.h (99%) rename lib/include/srsran/{upper => rlc}/rlc_metrics.h (100%) rename lib/include/srsran/{upper => rlc}/rlc_tm.h (98%) rename lib/include/srsran/{upper => rlc}/rlc_um_base.h (99%) rename lib/include/srsran/{upper => rlc}/rlc_um_lte.h (99%) rename lib/include/srsran/{upper => rlc}/rlc_um_nr.h (99%) create mode 100644 lib/src/rlc/CMakeLists.txt rename lib/src/{upper => rlc}/bearer_mem_pool.cc (85%) rename lib/src/{upper => rlc}/rlc.cc (98%) rename lib/src/{upper => rlc}/rlc_am_base.cc (93%) rename lib/src/{upper => rlc}/rlc_am_lte.cc (99%) rename lib/src/{upper => rlc}/rlc_am_nr.cc (99%) rename lib/src/{upper => rlc}/rlc_tm.cc (99%) rename lib/src/{upper => rlc}/rlc_um_base.cc (99%) rename lib/src/{upper => rlc}/rlc_um_lte.cc (99%) rename lib/src/{upper => rlc}/rlc_um_nr.cc (99%) create mode 100644 lib/test/rlc/CMakeLists.txt rename lib/test/{upper => rlc}/rlc_am_control_test.cc (100%) rename lib/test/{upper => rlc}/rlc_am_data_test.cc (100%) rename lib/test/{upper => rlc}/rlc_am_nr_pdu_test.cc (100%) rename lib/test/{upper => rlc}/rlc_am_test.cc (100%) rename lib/test/{upper => rlc}/rlc_common_test.cc (100%) rename lib/test/{upper => rlc}/rlc_stress_test.cc (100%) rename lib/test/{upper => rlc}/rlc_test_common.h (100%) rename lib/test/{upper => rlc}/rlc_um_data_test.cc (100%) rename lib/test/{upper => rlc}/rlc_um_nr_pdu_test.cc (100%) rename lib/test/{upper => rlc}/rlc_um_nr_test.cc (100%) rename lib/test/{upper => rlc}/rlc_um_test.cc (100%) diff --git a/lib/include/srsran/interfaces/enb_metrics_interface.h b/lib/include/srsran/interfaces/enb_metrics_interface.h index 9a89c0293..cdd9dc913 100644 --- a/lib/include/srsran/interfaces/enb_metrics_interface.h +++ b/lib/include/srsran/interfaces/enb_metrics_interface.h @@ -22,9 +22,9 @@ #include "srsenb/hdr/stack/s1ap/s1ap_metrics.h" #include "srsran/common/metrics_hub.h" #include "srsran/radio/radio_metrics.h" +#include "srsran/rlc/rlc_metrics.h" #include "srsran/system/sys_metrics.h" #include "srsran/upper/pdcp_metrics.h" -#include "srsran/upper/rlc_metrics.h" #include "srsue/hdr/stack/upper/gw_metrics.h" namespace srsenb { diff --git a/lib/include/srsran/upper/bearer_mem_pool.h b/lib/include/srsran/rlc/bearer_mem_pool.h similarity index 100% rename from lib/include/srsran/upper/bearer_mem_pool.h rename to lib/include/srsran/rlc/bearer_mem_pool.h diff --git a/lib/include/srsran/upper/rlc.h b/lib/include/srsran/rlc/rlc.h similarity index 97% rename from lib/include/srsran/upper/rlc.h rename to lib/include/srsran/rlc/rlc.h index 6a93ef55e..ef62f3bbe 100644 --- a/lib/include/srsran/upper/rlc.h +++ b/lib/include/srsran/rlc/rlc.h @@ -19,8 +19,8 @@ #include "srsran/interfaces/ue_pdcp_interfaces.h" #include "srsran/interfaces/ue_rlc_interfaces.h" #include "srsran/interfaces/ue_rrc_interfaces.h" -#include "srsran/upper/rlc_common.h" -#include "srsran/upper/rlc_metrics.h" +#include "srsran/rlc/rlc_common.h" +#include "srsran/rlc/rlc_metrics.h" namespace srsran { @@ -39,7 +39,7 @@ public: srsue::rrc_interface_rlc* rrc_, srsran::timer_handler* timers_, uint32_t lcid_); - + void init(srsue::pdcp_interface_rlc* pdcp_, srsue::rrc_interface_rlc* rrc_, srsran::timer_handler* timers_, diff --git a/lib/include/srsran/upper/rlc_am_base.h b/lib/include/srsran/rlc/rlc_am_base.h similarity index 95% rename from lib/include/srsran/upper/rlc_am_base.h rename to lib/include/srsran/rlc/rlc_am_base.h index 9aa7020c8..6743ae4db 100644 --- a/lib/include/srsran/upper/rlc_am_base.h +++ b/lib/include/srsran/rlc/rlc_am_base.h @@ -15,8 +15,8 @@ #include "srsran/common/buffer_pool.h" #include "srsran/common/common.h" +#include "srsran/rlc/rlc_common.h" #include "srsran/upper/byte_buffer_queue.h" -#include "srsran/upper/rlc_common.h" #include #include #include diff --git a/lib/include/srsran/upper/rlc_am_lte.h b/lib/include/srsran/rlc/rlc_am_lte.h similarity index 98% rename from lib/include/srsran/upper/rlc_am_lte.h rename to lib/include/srsran/rlc/rlc_am_lte.h index 9d1f88d36..6574e8297 100644 --- a/lib/include/srsran/upper/rlc_am_lte.h +++ b/lib/include/srsran/rlc/rlc_am_lte.h @@ -23,9 +23,9 @@ #include "srsran/common/task_scheduler.h" #include "srsran/common/timeout.h" #include "srsran/interfaces/pdcp_interface_types.h" +#include "srsran/rlc/rlc_am_base.h" +#include "srsran/rlc/rlc_common.h" #include "srsran/upper/byte_buffer_queue.h" -#include "srsran/upper/rlc_am_base.h" -#include "srsran/upper/rlc_common.h" #include #include #include @@ -367,10 +367,10 @@ private: void reestablish(); void stop(); - int write_sdu(unique_byte_buffer_t sdu); + int write_sdu(unique_byte_buffer_t sdu); uint32_t read_pdu(uint8_t* payload, uint32_t nof_bytes); - void discard_sdu(uint32_t discard_sn); - bool sdu_queue_is_full(); + void discard_sdu(uint32_t discard_sn); + bool sdu_queue_is_full(); bool has_data(); uint32_t get_buffer_state(); diff --git a/lib/include/srsran/upper/rlc_am_nr.h b/lib/include/srsran/rlc/rlc_am_nr.h similarity index 98% rename from lib/include/srsran/upper/rlc_am_nr.h rename to lib/include/srsran/rlc/rlc_am_nr.h index a825938a2..c1ac15bf1 100644 --- a/lib/include/srsran/upper/rlc_am_nr.h +++ b/lib/include/srsran/rlc/rlc_am_nr.h @@ -15,8 +15,8 @@ #include "srsran/common/buffer_pool.h" #include "srsran/common/common.h" +#include "srsran/rlc/rlc_am_base.h" #include "srsran/upper/byte_buffer_queue.h" -#include "srsran/upper/rlc_am_base.h" #include #include #include diff --git a/lib/include/srsran/upper/rlc_common.h b/lib/include/srsran/rlc/rlc_common.h similarity index 99% rename from lib/include/srsran/upper/rlc_common.h rename to lib/include/srsran/rlc/rlc_common.h index fcbbf33e1..922952b7d 100644 --- a/lib/include/srsran/upper/rlc_common.h +++ b/lib/include/srsran/rlc/rlc_common.h @@ -15,8 +15,8 @@ #include "srsran/adt/circular_buffer.h" #include "srsran/interfaces/rlc_interface_types.h" -#include "srsran/upper/bearer_mem_pool.h" -#include "srsran/upper/rlc_metrics.h" +#include "srsran/rlc/bearer_mem_pool.h" +#include "srsran/rlc/rlc_metrics.h" #include namespace srsran { diff --git a/lib/include/srsran/upper/rlc_metrics.h b/lib/include/srsran/rlc/rlc_metrics.h similarity index 100% rename from lib/include/srsran/upper/rlc_metrics.h rename to lib/include/srsran/rlc/rlc_metrics.h diff --git a/lib/include/srsran/upper/rlc_tm.h b/lib/include/srsran/rlc/rlc_tm.h similarity index 98% rename from lib/include/srsran/upper/rlc_tm.h rename to lib/include/srsran/rlc/rlc_tm.h index 858f9ff3b..9c21720ee 100644 --- a/lib/include/srsran/upper/rlc_tm.h +++ b/lib/include/srsran/rlc/rlc_tm.h @@ -15,8 +15,8 @@ #include "srsran/common/buffer_pool.h" #include "srsran/common/common.h" +#include "srsran/rlc/rlc_common.h" #include "srsran/upper/byte_buffer_queue.h" -#include "srsran/upper/rlc_common.h" namespace srsue { diff --git a/lib/include/srsran/upper/rlc_um_base.h b/lib/include/srsran/rlc/rlc_um_base.h similarity index 99% rename from lib/include/srsran/upper/rlc_um_base.h rename to lib/include/srsran/rlc/rlc_um_base.h index b17357a38..05d0a0179 100644 --- a/lib/include/srsran/upper/rlc_um_base.h +++ b/lib/include/srsran/rlc/rlc_um_base.h @@ -17,8 +17,8 @@ #include "srsran/common/buffer_pool.h" #include "srsran/common/common.h" #include "srsran/common/task_scheduler.h" +#include "srsran/rlc/rlc_common.h" #include "srsran/upper/byte_buffer_queue.h" -#include "srsran/upper/rlc_common.h" #include #include #include diff --git a/lib/include/srsran/upper/rlc_um_lte.h b/lib/include/srsran/rlc/rlc_um_lte.h similarity index 99% rename from lib/include/srsran/upper/rlc_um_lte.h rename to lib/include/srsran/rlc/rlc_um_lte.h index 17bf8ccb9..8da49c646 100644 --- a/lib/include/srsran/upper/rlc_um_lte.h +++ b/lib/include/srsran/rlc/rlc_um_lte.h @@ -15,8 +15,8 @@ #include "srsran/common/buffer_pool.h" #include "srsran/common/common.h" +#include "srsran/rlc/rlc_um_base.h" #include "srsran/upper/byte_buffer_queue.h" -#include "srsran/upper/rlc_um_base.h" #include #include #include diff --git a/lib/include/srsran/upper/rlc_um_nr.h b/lib/include/srsran/rlc/rlc_um_nr.h similarity index 99% rename from lib/include/srsran/upper/rlc_um_nr.h rename to lib/include/srsran/rlc/rlc_um_nr.h index 11c6bd55c..8a057871a 100644 --- a/lib/include/srsran/upper/rlc_um_nr.h +++ b/lib/include/srsran/rlc/rlc_um_nr.h @@ -16,8 +16,8 @@ #include "srsran/common/buffer_pool.h" #include "srsran/common/common.h" #include "srsran/interfaces/ue_interfaces.h" +#include "srsran/rlc/rlc_um_base.h" #include "srsran/upper/byte_buffer_queue.h" -#include "srsran/upper/rlc_um_base.h" #include #include #include diff --git a/lib/src/CMakeLists.txt b/lib/src/CMakeLists.txt index 1d0da18d6..cf7b4f922 100644 --- a/lib/src/CMakeLists.txt +++ b/lib/src/CMakeLists.txt @@ -11,6 +11,7 @@ add_subdirectory(common) add_subdirectory(mac) add_subdirectory(phy) add_subdirectory(radio) +add_subdirectory(rlc) add_subdirectory(srslog) add_subdirectory(system) add_subdirectory(upper) diff --git a/lib/src/rlc/CMakeLists.txt b/lib/src/rlc/CMakeLists.txt new file mode 100644 index 000000000..ed6e085fe --- /dev/null +++ b/lib/src/rlc/CMakeLists.txt @@ -0,0 +1,21 @@ +# +# Copyright 2013-2021 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(SOURCES rlc.cc + rlc_tm.cc + rlc_um_base.cc + rlc_um_lte.cc + rlc_am_base.cc + rlc_am_lte.cc + rlc_um_nr.cc + rlc_am_nr.cc + bearer_mem_pool.cc) + +add_library(srsran_rlc STATIC ${SOURCES}) +target_link_libraries(srsran_rlc srsran_common ${ATOMIC_LIBS}) +INSTALL(TARGETS srsran_rlc DESTINATION ${LIBRARY_DIR}) diff --git a/lib/src/upper/bearer_mem_pool.cc b/lib/src/rlc/bearer_mem_pool.cc similarity index 85% rename from lib/src/upper/bearer_mem_pool.cc rename to lib/src/rlc/bearer_mem_pool.cc index 764d8d122..c89fcb945 100644 --- a/lib/src/upper/bearer_mem_pool.cc +++ b/lib/src/rlc/bearer_mem_pool.cc @@ -10,11 +10,11 @@ * */ -#include "srsran/upper/bearer_mem_pool.h" +#include "srsran/rlc/bearer_mem_pool.h" #include "srsran/adt/pool/batch_mem_pool.h" -#include "srsran/upper/rlc_am_lte.h" -#include "srsran/upper/rlc_um_lte.h" -#include "srsran/upper/rlc_um_nr.h" +#include "srsran/rlc/rlc_am_lte.h" +#include "srsran/rlc/rlc_um_lte.h" +#include "srsran/rlc/rlc_um_nr.h" namespace srsran { diff --git a/lib/src/upper/rlc.cc b/lib/src/rlc/rlc.cc similarity index 98% rename from lib/src/upper/rlc.cc rename to lib/src/rlc/rlc.cc index 16559bf5c..e46fcc0a6 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/rlc/rlc.cc @@ -10,12 +10,12 @@ * */ -#include "srsran/upper/rlc.h" +#include "srsran/rlc/rlc.h" #include "srsran/common/rwlock_guard.h" -#include "srsran/upper/rlc_am_lte.h" -#include "srsran/upper/rlc_tm.h" -#include "srsran/upper/rlc_um_lte.h" -#include "srsran/upper/rlc_um_nr.h" +#include "srsran/rlc/rlc_am_lte.h" +#include "srsran/rlc/rlc_tm.h" +#include "srsran/rlc/rlc_um_lte.h" +#include "srsran/rlc/rlc_um_nr.h" namespace srsran { @@ -503,7 +503,7 @@ void rlc::change_lcid(uint32_t old_lcid, uint32_t new_lcid) // make sure old LCID exists and new LCID is still free if (valid_lcid(old_lcid) && not valid_lcid(new_lcid)) { // insert old rlc entity into new LCID - rlc_map_t::iterator it = rlc_array.find(old_lcid); + rlc_map_t::iterator it = rlc_array.find(old_lcid); std::unique_ptr rlc_entity = std::move(it->second); if (not rlc_array.insert(rlc_map_pair_t(new_lcid, std::move(rlc_entity))).second) { logger.error("Error inserting RLC entity into array."); diff --git a/lib/src/upper/rlc_am_base.cc b/lib/src/rlc/rlc_am_base.cc similarity index 93% rename from lib/src/upper/rlc_am_base.cc rename to lib/src/rlc/rlc_am_base.cc index b8bff63ea..9de01ac07 100644 --- a/lib/src/upper/rlc_am_base.cc +++ b/lib/src/rlc/rlc_am_base.cc @@ -10,7 +10,7 @@ * */ -#include "srsran/upper/rlc_am_base.h" +#include "srsran/rlc/rlc_am_base.h" #include namespace srsran { diff --git a/lib/src/upper/rlc_am_lte.cc b/lib/src/rlc/rlc_am_lte.cc similarity index 99% rename from lib/src/upper/rlc_am_lte.cc rename to lib/src/rlc/rlc_am_lte.cc index 026355535..4704e3cc2 100644 --- a/lib/src/upper/rlc_am_lte.cc +++ b/lib/src/rlc/rlc_am_lte.cc @@ -10,7 +10,7 @@ * */ -#include "srsran/upper/rlc_am_lte.h" +#include "srsran/rlc/rlc_am_lte.h" #include "srsran/common/string_helpers.h" #include "srsran/interfaces/ue_pdcp_interfaces.h" #include "srsran/interfaces/ue_rrc_interfaces.h" diff --git a/lib/src/upper/rlc_am_nr.cc b/lib/src/rlc/rlc_am_nr.cc similarity index 99% rename from lib/src/upper/rlc_am_nr.cc rename to lib/src/rlc/rlc_am_nr.cc index cb94d7bb4..1dedca3c8 100644 --- a/lib/src/upper/rlc_am_nr.cc +++ b/lib/src/rlc/rlc_am_nr.cc @@ -10,7 +10,7 @@ * */ -#include "srsran/upper/rlc_am_nr.h" +#include "srsran/rlc/rlc_am_nr.h" #include namespace srsran { diff --git a/lib/src/upper/rlc_tm.cc b/lib/src/rlc/rlc_tm.cc similarity index 99% rename from lib/src/upper/rlc_tm.cc rename to lib/src/rlc/rlc_tm.cc index 776d2b3cf..3a413def3 100644 --- a/lib/src/upper/rlc_tm.cc +++ b/lib/src/rlc/rlc_tm.cc @@ -10,7 +10,7 @@ * */ -#include "srsran/upper/rlc_tm.h" +#include "srsran/rlc/rlc_tm.h" #include "srsran/common/common_lte.h" #include "srsran/interfaces/ue_pdcp_interfaces.h" #include "srsran/interfaces/ue_rrc_interfaces.h" diff --git a/lib/src/upper/rlc_um_base.cc b/lib/src/rlc/rlc_um_base.cc similarity index 99% rename from lib/src/upper/rlc_um_base.cc rename to lib/src/rlc/rlc_um_base.cc index 1ac0d183b..26ce85370 100644 --- a/lib/src/upper/rlc_um_base.cc +++ b/lib/src/rlc/rlc_um_base.cc @@ -10,7 +10,7 @@ * */ -#include "srsran/upper/rlc_um_base.h" +#include "srsran/rlc/rlc_um_base.h" #include "srsran/interfaces/ue_rrc_interfaces.h" #include diff --git a/lib/src/upper/rlc_um_lte.cc b/lib/src/rlc/rlc_um_lte.cc similarity index 99% rename from lib/src/upper/rlc_um_lte.cc rename to lib/src/rlc/rlc_um_lte.cc index 57d309daa..545b907ad 100644 --- a/lib/src/upper/rlc_um_lte.cc +++ b/lib/src/rlc/rlc_um_lte.cc @@ -10,7 +10,7 @@ * */ -#include "srsran/upper/rlc_um_lte.h" +#include "srsran/rlc/rlc_um_lte.h" #include "srsran/interfaces/ue_pdcp_interfaces.h" #include diff --git a/lib/src/upper/rlc_um_nr.cc b/lib/src/rlc/rlc_um_nr.cc similarity index 99% rename from lib/src/upper/rlc_um_nr.cc rename to lib/src/rlc/rlc_um_nr.cc index 32fc1948d..9ec8032ea 100644 --- a/lib/src/upper/rlc_um_nr.cc +++ b/lib/src/rlc/rlc_um_nr.cc @@ -10,7 +10,7 @@ * */ -#include "srsran/upper/rlc_um_nr.h" +#include "srsran/rlc/rlc_um_nr.h" #include "srsran/interfaces/ue_pdcp_interfaces.h" #include diff --git a/lib/src/upper/CMakeLists.txt b/lib/src/upper/CMakeLists.txt index c6b65ba10..d09f74c8f 100644 --- a/lib/src/upper/CMakeLists.txt +++ b/lib/src/upper/CMakeLists.txt @@ -10,16 +10,7 @@ set(SOURCES gtpu.cc pdcp.cc pdcp_entity_base.cc pdcp_entity_lte.cc - rlc.cc - rlc_tm.cc - rlc_um_base.cc - rlc_um_lte.cc - rlc_am_base.cc - rlc_am_lte.cc - pdcp_entity_nr.cc - rlc_um_nr.cc - rlc_am_nr.cc - bearer_mem_pool.cc) + pdcp_entity_nr.cc) add_library(srsran_upper STATIC ${SOURCES}) target_link_libraries(srsran_upper srsran_common srsran_asn1 ${ATOMIC_LIBS}) diff --git a/lib/test/rlc/CMakeLists.txt b/lib/test/rlc/CMakeLists.txt new file mode 100644 index 000000000..135a8f19b --- /dev/null +++ b/lib/test/rlc/CMakeLists.txt @@ -0,0 +1,64 @@ +# +# Copyright 2013-2021 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(CTEST_LABELS "lib;rlc") + +add_executable(rlc_am_data_test rlc_am_data_test.cc) +target_link_libraries(rlc_am_data_test srsran_upper srsran_phy srsran_common) +add_lte_test(rlc_am_data_test rlc_am_data_test) + +add_executable(rlc_am_control_test rlc_am_control_test.cc) +target_link_libraries(rlc_am_control_test srsran_upper srsran_phy) +add_lte_test(rlc_am_control_test rlc_am_control_test) + +add_executable(rlc_am_test rlc_am_test.cc) +target_link_libraries(rlc_am_test srsran_upper srsran_phy srsran_common) +add_lte_test(rlc_am_test rlc_am_test) + +add_executable(rlc_am_nr_pdu_test rlc_am_nr_pdu_test.cc) +target_link_libraries(rlc_am_nr_pdu_test srsran_upper srsran_phy) +add_nr_test(rlc_am_nr_pdu_test rlc_am_nr_pdu_test) + +add_executable(rlc_stress_test rlc_stress_test.cc) +target_link_libraries(rlc_stress_test srsran_upper srsran_mac srsran_phy srsran_common ${Boost_LIBRARIES} ${ATOMIC_LIBS}) +add_lte_test(rlc_am_stress_test rlc_stress_test --mode=AM --loglevel 1 --sdu_gen_delay 250) +add_lte_test(rlc_um_stress_test rlc_stress_test --mode=UM --loglevel 1) +add_lte_test(rlc_tm_stress_test rlc_stress_test --mode=TM --loglevel 1 --random_opp=false) + +add_nr_test(rlc_um6_nr_stress_test rlc_stress_test --rat NR --mode=UM6 --loglevel 1) +add_nr_test(rlc_um12_nr_stress_test rlc_stress_test --rat NR --mode=UM12 --loglevel 1) + +add_executable(rlc_um_data_test rlc_um_data_test.cc) +target_link_libraries(rlc_um_data_test srsran_upper srsran_phy srsran_common) +add_test(rlc_um_data_test rlc_um_data_test) + +add_executable(rlc_um_test rlc_um_test.cc) +target_link_libraries(rlc_um_test srsran_upper srsran_phy) +add_test(rlc_um_test rlc_um_test) + +add_executable(rlc_common_test rlc_common_test.cc) +target_link_libraries(rlc_common_test srsran_upper srsran_phy) +add_test(rlc_common_test rlc_common_test) + +add_executable(rlc_um_nr_pdu_test rlc_um_nr_pdu_test.cc) +target_link_libraries(rlc_um_nr_pdu_test srsran_upper srsran_mac srsran_phy) +add_nr_test(rlc_um_nr_pdu_test rlc_um_nr_pdu_test) + +add_executable(rlc_um_nr_test rlc_um_nr_test.cc) +target_link_libraries(rlc_um_nr_test srsran_upper srsran_phy) +add_nr_test(rlc_um_nr_test rlc_um_nr_test) + +######################################################################## +# Option to run command after build (useful for remote builds) +######################################################################## +if (NOT ${BUILD_CMD} STREQUAL "") + message(STATUS "Added custom post-build command: ${BUILD_CMD}") + add_custom_command(TARGET ip_test POST_BUILD COMMAND ${BUILD_CMD}) +else(NOT ${BUILD_CMD} STREQUAL "") + message(STATUS "No post-build command defined") +endif (NOT ${BUILD_CMD} STREQUAL "") diff --git a/lib/test/upper/rlc_am_control_test.cc b/lib/test/rlc/rlc_am_control_test.cc similarity index 100% rename from lib/test/upper/rlc_am_control_test.cc rename to lib/test/rlc/rlc_am_control_test.cc diff --git a/lib/test/upper/rlc_am_data_test.cc b/lib/test/rlc/rlc_am_data_test.cc similarity index 100% rename from lib/test/upper/rlc_am_data_test.cc rename to lib/test/rlc/rlc_am_data_test.cc diff --git a/lib/test/upper/rlc_am_nr_pdu_test.cc b/lib/test/rlc/rlc_am_nr_pdu_test.cc similarity index 100% rename from lib/test/upper/rlc_am_nr_pdu_test.cc rename to lib/test/rlc/rlc_am_nr_pdu_test.cc diff --git a/lib/test/upper/rlc_am_test.cc b/lib/test/rlc/rlc_am_test.cc similarity index 100% rename from lib/test/upper/rlc_am_test.cc rename to lib/test/rlc/rlc_am_test.cc diff --git a/lib/test/upper/rlc_common_test.cc b/lib/test/rlc/rlc_common_test.cc similarity index 100% rename from lib/test/upper/rlc_common_test.cc rename to lib/test/rlc/rlc_common_test.cc diff --git a/lib/test/upper/rlc_stress_test.cc b/lib/test/rlc/rlc_stress_test.cc similarity index 100% rename from lib/test/upper/rlc_stress_test.cc rename to lib/test/rlc/rlc_stress_test.cc diff --git a/lib/test/upper/rlc_test_common.h b/lib/test/rlc/rlc_test_common.h similarity index 100% rename from lib/test/upper/rlc_test_common.h rename to lib/test/rlc/rlc_test_common.h diff --git a/lib/test/upper/rlc_um_data_test.cc b/lib/test/rlc/rlc_um_data_test.cc similarity index 100% rename from lib/test/upper/rlc_um_data_test.cc rename to lib/test/rlc/rlc_um_data_test.cc diff --git a/lib/test/upper/rlc_um_nr_pdu_test.cc b/lib/test/rlc/rlc_um_nr_pdu_test.cc similarity index 100% rename from lib/test/upper/rlc_um_nr_pdu_test.cc rename to lib/test/rlc/rlc_um_nr_pdu_test.cc diff --git a/lib/test/upper/rlc_um_nr_test.cc b/lib/test/rlc/rlc_um_nr_test.cc similarity index 100% rename from lib/test/upper/rlc_um_nr_test.cc rename to lib/test/rlc/rlc_um_nr_test.cc diff --git a/lib/test/upper/rlc_um_test.cc b/lib/test/rlc/rlc_um_test.cc similarity index 100% rename from lib/test/upper/rlc_um_test.cc rename to lib/test/rlc/rlc_um_test.cc diff --git a/lib/test/upper/CMakeLists.txt b/lib/test/upper/CMakeLists.txt index b17495db8..f0cb9272a 100644 --- a/lib/test/upper/CMakeLists.txt +++ b/lib/test/upper/CMakeLists.txt @@ -8,51 +8,6 @@ set(CTEST_LABELS "lib;upper") -add_executable(rlc_am_data_test rlc_am_data_test.cc) -target_link_libraries(rlc_am_data_test srsran_upper srsran_phy srsran_common) -add_lte_test(rlc_am_data_test rlc_am_data_test) - -add_executable(rlc_am_control_test rlc_am_control_test.cc) -target_link_libraries(rlc_am_control_test srsran_upper srsran_phy) -add_lte_test(rlc_am_control_test rlc_am_control_test) - -add_executable(rlc_am_test rlc_am_test.cc) -target_link_libraries(rlc_am_test srsran_upper srsran_phy srsran_common) -add_lte_test(rlc_am_test rlc_am_test) - -add_executable(rlc_am_nr_pdu_test rlc_am_nr_pdu_test.cc) -target_link_libraries(rlc_am_nr_pdu_test srsran_upper srsran_phy) -add_nr_test(rlc_am_nr_pdu_test rlc_am_nr_pdu_test) - -add_executable(rlc_stress_test rlc_stress_test.cc) -target_link_libraries(rlc_stress_test srsran_upper srsran_mac srsran_phy srsran_common ${Boost_LIBRARIES} ${ATOMIC_LIBS}) -add_lte_test(rlc_am_stress_test rlc_stress_test --mode=AM --loglevel 1 --sdu_gen_delay 250) -add_lte_test(rlc_um_stress_test rlc_stress_test --mode=UM --loglevel 1) -add_lte_test(rlc_tm_stress_test rlc_stress_test --mode=TM --loglevel 1 --random_opp=false) - -add_nr_test(rlc_um6_nr_stress_test rlc_stress_test --rat NR --mode=UM6 --loglevel 1) -add_nr_test(rlc_um12_nr_stress_test rlc_stress_test --rat NR --mode=UM12 --loglevel 1) - -add_executable(rlc_um_data_test rlc_um_data_test.cc) -target_link_libraries(rlc_um_data_test srsran_upper srsran_phy srsran_common) -add_test(rlc_um_data_test rlc_um_data_test) - -add_executable(rlc_um_test rlc_um_test.cc) -target_link_libraries(rlc_um_test srsran_upper srsran_phy) -add_test(rlc_um_test rlc_um_test) - -add_executable(rlc_common_test rlc_common_test.cc) -target_link_libraries(rlc_common_test srsran_upper srsran_phy) -add_test(rlc_common_test rlc_common_test) - -add_executable(rlc_um_nr_pdu_test rlc_um_nr_pdu_test.cc) -target_link_libraries(rlc_um_nr_pdu_test srsran_upper srsran_mac srsran_phy) -add_nr_test(rlc_um_nr_pdu_test rlc_um_nr_pdu_test) - -add_executable(rlc_um_nr_test rlc_um_nr_test.cc) -target_link_libraries(rlc_um_nr_test srsran_upper srsran_phy) -add_nr_test(rlc_um_nr_test rlc_um_nr_test) - add_executable(pdcp_nr_test_tx pdcp_nr_test_tx.cc) target_link_libraries(pdcp_nr_test_tx srsran_upper srsran_common) add_nr_test(pdcp_nr_test_tx pdcp_nr_test_tx) diff --git a/srsenb/hdr/stack/upper/rlc.h b/srsenb/hdr/stack/upper/rlc.h index 30fdc2875..a635de684 100644 --- a/srsenb/hdr/stack/upper/rlc.h +++ b/srsenb/hdr/stack/upper/rlc.h @@ -14,8 +14,8 @@ #include "srsran/interfaces/enb_metrics_interface.h" #include "srsran/interfaces/enb_rlc_interfaces.h" #include "srsran/interfaces/ue_interfaces.h" +#include "srsran/rlc/rlc.h" #include "srsran/srslog/srslog.h" -#include "srsran/upper/rlc.h" #include #ifndef SRSENB_RLC_H diff --git a/srsenb/hdr/stack/upper/rlc_nr.h b/srsenb/hdr/stack/upper/rlc_nr.h index 5e72e6382..4a1fa424a 100644 --- a/srsenb/hdr/stack/upper/rlc_nr.h +++ b/srsenb/hdr/stack/upper/rlc_nr.h @@ -14,7 +14,7 @@ #define SRSENB_RLC_NR_H #include "srsran/interfaces/gnb_interfaces.h" -#include "srsran/upper/rlc.h" +#include "srsran/rlc/rlc.h" #include namespace srsenb { diff --git a/srsenb/src/CMakeLists.txt b/srsenb/src/CMakeLists.txt index 98776f739..7f8a9895d 100644 --- a/srsenb/src/CMakeLists.txt +++ b/srsenb/src/CMakeLists.txt @@ -27,7 +27,7 @@ target_link_libraries(enb_cfg_parser ${LIBCONFIGPP_LIBRARIES}) add_executable(srsenb main.cc enb.cc metrics_stdout.cc metrics_csv.cc metrics_json.cc) set(SRSENB_SOURCES srsenb_phy srsenb_stack srsenb_common srsenb_s1ap srsenb_upper srsenb_mac srsenb_rrc srslog system) -set(SRSRAN_SOURCES srsran_common srsran_mac srsran_phy srsran_upper srsran_radio rrc_asn1 s1ap_asn1 enb_cfg_parser srslog system) +set(SRSRAN_SOURCES srsran_common srsran_mac srsran_phy srsran_upper srsran_rlc srsran_radio rrc_asn1 s1ap_asn1 enb_cfg_parser srslog system) set(SRSENB_SOURCES ${SRSENB_SOURCES} srsgnb_phy srsgnb_stack srsgnb_ngap srsgnb_upper srsgnb_mac srsgnb_rrc) set(SRSRAN_SOURCES ${SRSRAN_SOURCES} rrc_nr_asn1 ngap_nr_asn1) diff --git a/srsenb/src/common/rnti_pool.cc b/srsenb/src/common/rnti_pool.cc index 4c62932a9..6b2804876 100644 --- a/srsenb/src/common/rnti_pool.cc +++ b/srsenb/src/common/rnti_pool.cc @@ -16,8 +16,8 @@ #include "srsenb/hdr/stack/rrc/rrc_mobility.h" #include "srsenb/hdr/stack/rrc/rrc_ue.h" #include "srsran/adt/pool/circular_stack_pool.h" +#include "srsran/rlc/rlc.h" #include "srsran/upper/pdcp.h" -#include "srsran/upper/rlc.h" namespace srsenb { diff --git a/srsenb/src/stack/enb_stack_lte.cc b/srsenb/src/stack/enb_stack_lte.cc index 84cb4997b..e8918fb77 100644 --- a/srsenb/src/stack/enb_stack_lte.cc +++ b/srsenb/src/stack/enb_stack_lte.cc @@ -14,8 +14,8 @@ #include "srsenb/hdr/common/rnti_pool.h" #include "srsenb/hdr/enb.h" #include "srsran/interfaces/enb_metrics_interface.h" +#include "srsran/rlc/bearer_mem_pool.h" #include "srsran/srslog/event_trace.h" -#include "srsran/upper/bearer_mem_pool.h" using namespace srsran; diff --git a/srsue/hdr/stack/ue_stack_lte.h b/srsue/hdr/stack/ue_stack_lte.h index 4f9d5f1b2..b3916b913 100644 --- a/srsue/hdr/stack/ue_stack_lte.h +++ b/srsue/hdr/stack/ue_stack_lte.h @@ -26,8 +26,8 @@ #include "mac_nr/mac_nr.h" #include "rrc/rrc.h" #include "srsran/radio/radio.h" +#include "srsran/rlc/rlc.h" #include "srsran/upper/pdcp.h" -#include "srsran/upper/rlc.h" #include "upper/nas.h" #include "upper/usim.h" diff --git a/srsue/hdr/stack/ue_stack_nr.h b/srsue/hdr/stack/ue_stack_nr.h index 6e5189c81..c3704c7c3 100644 --- a/srsue/hdr/stack/ue_stack_nr.h +++ b/srsue/hdr/stack/ue_stack_nr.h @@ -21,8 +21,8 @@ #include "mac_nr/mac_nr.h" #include "rrc/rrc_nr.h" #include "srsran/radio/radio.h" +#include "srsran/rlc/rlc.h" #include "srsran/upper/pdcp.h" -#include "srsran/upper/rlc.h" #include "upper/nas.h" #include "upper/usim.h" diff --git a/srsue/hdr/ue_metrics_interface.h b/srsue/hdr/ue_metrics_interface.h index 43bca5f5f..7a42cc3f1 100644 --- a/srsue/hdr/ue_metrics_interface.h +++ b/srsue/hdr/ue_metrics_interface.h @@ -18,8 +18,8 @@ #include "phy/phy_metrics.h" #include "srsran/common/metrics_hub.h" #include "srsran/radio/radio_metrics.h" +#include "srsran/rlc/rlc_metrics.h" #include "srsran/system/sys_metrics.h" -#include "srsran/upper/rlc_metrics.h" #include "stack/mac/mac_metrics.h" #include "stack/rrc/rrc_metrics.h" #include "stack/upper/gw_metrics.h" diff --git a/srsue/src/CMakeLists.txt b/srsue/src/CMakeLists.txt index 1bd3e1725..83eec18c8 100644 --- a/srsue/src/CMakeLists.txt +++ b/srsue/src/CMakeLists.txt @@ -22,7 +22,7 @@ endif (RPATH) add_executable(srsue main.cc ue.cc metrics_stdout.cc metrics_csv.cc metrics_json.cc) set(SRSUE_SOURCES srsue_phy srsue_stack srsue_upper srsue_mac srsue_rrc srslog system) -set(SRSRAN_SOURCES srsran_common srsran_mac srsran_phy srsran_radio srsran_upper rrc_asn1 srslog system) +set(SRSRAN_SOURCES srsran_common srsran_mac srsran_phy srsran_radio srsran_upper srsran_rlc rrc_asn1 srslog system) set(SRSUE_SOURCES ${SRSUE_SOURCES} srsue_nr_stack srsue_rrc_nr srsue_mac_nr) set(SRSRAN_SOURCES ${SRSRAN_SOURCES} rrc_nr_asn1 ngap_nr_asn1) diff --git a/srsue/src/test/ttcn3/hdr/ttcn3_syssim.h b/srsue/src/test/ttcn3/hdr/ttcn3_syssim.h index 7de69a831..029f41dd9 100644 --- a/srsue/src/test/ttcn3/hdr/ttcn3_syssim.h +++ b/srsue/src/test/ttcn3/hdr/ttcn3_syssim.h @@ -14,9 +14,9 @@ #define SRSUE_TTCN3_SYSSIM_H #include "srsran/mac/pdu_queue.h" +#include "srsran/rlc/rlc.h" #include "srsran/test/ue_test_interfaces.h" #include "srsran/upper/pdcp.h" -#include "srsran/upper/rlc.h" #include "ttcn3_common.h" #include "ttcn3_drb_interface.h" #include "ttcn3_ip_ctrl_interface.h" diff --git a/srsue/src/test/ttcn3/src/CMakeLists.txt b/srsue/src/test/ttcn3/src/CMakeLists.txt index 6fc2619c6..9a53ad440 100644 --- a/srsue/src/test/ttcn3/src/CMakeLists.txt +++ b/srsue/src/test/ttcn3/src/CMakeLists.txt @@ -14,6 +14,7 @@ set(LINK_LIBRARIES srsue_stack srsue_rrc srsue_rrc_nr srsran_upper + srsran_rlc srsran_common srsran_mac srsran_phy diff --git a/srsue/src/test/ttcn3/src/ttcn3_syssim.cc b/srsue/src/test/ttcn3/src/ttcn3_syssim.cc index ab6c51fe3..698411149 100644 --- a/srsue/src/test/ttcn3/src/ttcn3_syssim.cc +++ b/srsue/src/test/ttcn3/src/ttcn3_syssim.cc @@ -13,10 +13,10 @@ #include "ttcn3_syssim.h" #include "dut_utils.h" #include "srsran/mac/pdu_queue.h" +#include "srsran/rlc/rlc.h" #include "srsran/srslog/srslog.h" #include "srsran/test/ue_test_interfaces.h" #include "srsran/upper/pdcp.h" -#include "srsran/upper/rlc.h" #include "swappable_sink.h" #include "ttcn3_common.h" #include "ttcn3_drb_interface.h" From 865298f8d5c002e57ef25ff6619046445b473b36 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 28 Jun 2021 11:21:44 +0100 Subject: [PATCH 42/43] Moved lib PDCP to its own folder --- lib/src/CMakeLists.txt | 1 + lib/src/pdcp/CMakeLists.txt | 16 +++++++++++++++ lib/src/{upper => pdcp}/pdcp.cc | 0 lib/src/{upper => pdcp}/pdcp_entity_base.cc | 0 lib/src/{upper => pdcp}/pdcp_entity_lte.cc | 0 lib/src/{upper => pdcp}/pdcp_entity_nr.cc | 0 lib/src/upper/CMakeLists.txt | 6 +----- lib/test/CMakeLists.txt | 3 ++- lib/test/{upper => pdcp}/CMakeLists.txt | 14 ++++++------- lib/test/{upper => pdcp}/pdcp_base_test.h | 0 lib/test/{upper => pdcp}/pdcp_lte_test.h | 0 .../pdcp_lte_test_discard_sdu.cc | 0 lib/test/{upper => pdcp}/pdcp_lte_test_rx.cc | 0 .../pdcp_lte_test_status_report.cc | 0 lib/test/{upper => pdcp}/pdcp_nr_test.h | 0 .../pdcp_nr_test_discard_sdu.cc | 0 lib/test/{upper => pdcp}/pdcp_nr_test_rx.cc | 0 lib/test/{upper => pdcp}/pdcp_nr_test_tx.cc | 0 lib/test/rlc/CMakeLists.txt | 20 +++++++++---------- lib/test/rlc/rlc_am_control_test.cc | 2 +- lib/test/rlc/rlc_am_data_test.cc | 2 +- lib/test/rlc/rlc_am_nr_pdu_test.cc | 4 ++-- lib/test/rlc/rlc_am_test.cc | 6 +++--- lib/test/rlc/rlc_common_test.cc | 2 +- lib/test/rlc/rlc_stress_test.cc | 2 +- lib/test/rlc/rlc_um_data_test.cc | 2 +- lib/test/rlc/rlc_um_nr_pdu_test.cc | 4 ++-- lib/test/rlc/rlc_um_nr_test.cc | 4 ++-- lib/test/rlc/rlc_um_test.cc | 2 +- srsenb/src/CMakeLists.txt | 2 +- srsue/src/CMakeLists.txt | 2 +- srsue/src/stack/rrc/test/CMakeLists.txt | 4 ++-- srsue/src/test/ttcn3/src/CMakeLists.txt | 1 + 33 files changed, 57 insertions(+), 42 deletions(-) create mode 100644 lib/src/pdcp/CMakeLists.txt rename lib/src/{upper => pdcp}/pdcp.cc (100%) rename lib/src/{upper => pdcp}/pdcp_entity_base.cc (100%) rename lib/src/{upper => pdcp}/pdcp_entity_lte.cc (100%) rename lib/src/{upper => pdcp}/pdcp_entity_nr.cc (100%) rename lib/test/{upper => pdcp}/CMakeLists.txt (75%) rename lib/test/{upper => pdcp}/pdcp_base_test.h (100%) rename lib/test/{upper => pdcp}/pdcp_lte_test.h (100%) rename lib/test/{upper => pdcp}/pdcp_lte_test_discard_sdu.cc (100%) rename lib/test/{upper => pdcp}/pdcp_lte_test_rx.cc (100%) rename lib/test/{upper => pdcp}/pdcp_lte_test_status_report.cc (100%) rename lib/test/{upper => pdcp}/pdcp_nr_test.h (100%) rename lib/test/{upper => pdcp}/pdcp_nr_test_discard_sdu.cc (100%) rename lib/test/{upper => pdcp}/pdcp_nr_test_rx.cc (100%) rename lib/test/{upper => pdcp}/pdcp_nr_test_tx.cc (100%) diff --git a/lib/src/CMakeLists.txt b/lib/src/CMakeLists.txt index cf7b4f922..2ff8d4d9a 100644 --- a/lib/src/CMakeLists.txt +++ b/lib/src/CMakeLists.txt @@ -12,6 +12,7 @@ add_subdirectory(mac) add_subdirectory(phy) add_subdirectory(radio) add_subdirectory(rlc) +add_subdirectory(pdcp) add_subdirectory(srslog) add_subdirectory(system) add_subdirectory(upper) diff --git a/lib/src/pdcp/CMakeLists.txt b/lib/src/pdcp/CMakeLists.txt new file mode 100644 index 000000000..2c1f8578f --- /dev/null +++ b/lib/src/pdcp/CMakeLists.txt @@ -0,0 +1,16 @@ +# +# Copyright 2013-2021 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(SOURCES pdcp.cc + pdcp_entity_base.cc + pdcp_entity_lte.cc + pdcp_entity_nr.cc) + +add_library(srsran_pdcp STATIC ${SOURCES}) +target_link_libraries(srsran_pdcp srsran_common srsran_asn1 ${ATOMIC_LIBS}) +INSTALL(TARGETS srsran_pdcp DESTINATION ${LIBRARY_DIR}) diff --git a/lib/src/upper/pdcp.cc b/lib/src/pdcp/pdcp.cc similarity index 100% rename from lib/src/upper/pdcp.cc rename to lib/src/pdcp/pdcp.cc diff --git a/lib/src/upper/pdcp_entity_base.cc b/lib/src/pdcp/pdcp_entity_base.cc similarity index 100% rename from lib/src/upper/pdcp_entity_base.cc rename to lib/src/pdcp/pdcp_entity_base.cc diff --git a/lib/src/upper/pdcp_entity_lte.cc b/lib/src/pdcp/pdcp_entity_lte.cc similarity index 100% rename from lib/src/upper/pdcp_entity_lte.cc rename to lib/src/pdcp/pdcp_entity_lte.cc diff --git a/lib/src/upper/pdcp_entity_nr.cc b/lib/src/pdcp/pdcp_entity_nr.cc similarity index 100% rename from lib/src/upper/pdcp_entity_nr.cc rename to lib/src/pdcp/pdcp_entity_nr.cc diff --git a/lib/src/upper/CMakeLists.txt b/lib/src/upper/CMakeLists.txt index d09f74c8f..dc8f12d41 100644 --- a/lib/src/upper/CMakeLists.txt +++ b/lib/src/upper/CMakeLists.txt @@ -6,11 +6,7 @@ # the distribution. # -set(SOURCES gtpu.cc - pdcp.cc - pdcp_entity_base.cc - pdcp_entity_lte.cc - pdcp_entity_nr.cc) +set(SOURCES gtpu.cc) add_library(srsran_upper STATIC ${SOURCES}) target_link_libraries(srsran_upper srsran_common srsran_asn1 ${ATOMIC_LIBS}) diff --git a/lib/test/CMakeLists.txt b/lib/test/CMakeLists.txt index 3b230ca0e..540fe5c6c 100644 --- a/lib/test/CMakeLists.txt +++ b/lib/test/CMakeLists.txt @@ -11,5 +11,6 @@ add_subdirectory(common) add_subdirectory(mac) add_subdirectory(phy) add_subdirectory(srslog) -add_subdirectory(upper) +add_subdirectory(rlc) +add_subdirectory(pdcp) add_subdirectory(adt) diff --git a/lib/test/upper/CMakeLists.txt b/lib/test/pdcp/CMakeLists.txt similarity index 75% rename from lib/test/upper/CMakeLists.txt rename to lib/test/pdcp/CMakeLists.txt index f0cb9272a..8280edeaa 100644 --- a/lib/test/upper/CMakeLists.txt +++ b/lib/test/pdcp/CMakeLists.txt @@ -6,30 +6,30 @@ # the distribution. # -set(CTEST_LABELS "lib;upper") +set(CTEST_LABELS "lib;pdcp") add_executable(pdcp_nr_test_tx pdcp_nr_test_tx.cc) -target_link_libraries(pdcp_nr_test_tx srsran_upper srsran_common) +target_link_libraries(pdcp_nr_test_tx srsran_pdcp srsran_common) add_nr_test(pdcp_nr_test_tx pdcp_nr_test_tx) add_executable(pdcp_nr_test_rx pdcp_nr_test_rx.cc) -target_link_libraries(pdcp_nr_test_rx srsran_upper srsran_common) +target_link_libraries(pdcp_nr_test_rx srsran_pdcp srsran_common) add_nr_test(pdcp_nr_test_rx pdcp_nr_test_rx) add_executable(pdcp_nr_test_discard_sdu pdcp_nr_test_discard_sdu.cc) -target_link_libraries(pdcp_nr_test_discard_sdu srsran_upper srsran_common ${ATOMIC_LIBS}) +target_link_libraries(pdcp_nr_test_discard_sdu srsran_pdcp srsran_common ${ATOMIC_LIBS}) add_nr_test(pdcp_nr_test_discard_sdu pdcp_nr_test_discard_sdu) add_executable(pdcp_lte_test_rx pdcp_lte_test_rx.cc) -target_link_libraries(pdcp_lte_test_rx srsran_upper srsran_common) +target_link_libraries(pdcp_lte_test_rx srsran_pdcp srsran_common) add_test(pdcp_lte_test_rx pdcp_lte_test_rx) add_executable(pdcp_lte_test_discard_sdu pdcp_lte_test_discard_sdu.cc) -target_link_libraries(pdcp_lte_test_discard_sdu srsran_upper srsran_common) +target_link_libraries(pdcp_lte_test_discard_sdu srsran_pdcp srsran_common) add_test(pdcp_lte_test_discard_sdu pdcp_lte_test_discard_sdu) add_executable(pdcp_lte_test_status_report pdcp_lte_test_status_report.cc) -target_link_libraries(pdcp_lte_test_status_report srsran_upper srsran_common) +target_link_libraries(pdcp_lte_test_status_report srsran_pdcp srsran_common) add_test(pdcp_lte_test_status_report pdcp_lte_test_status_report) ######################################################################## diff --git a/lib/test/upper/pdcp_base_test.h b/lib/test/pdcp/pdcp_base_test.h similarity index 100% rename from lib/test/upper/pdcp_base_test.h rename to lib/test/pdcp/pdcp_base_test.h diff --git a/lib/test/upper/pdcp_lte_test.h b/lib/test/pdcp/pdcp_lte_test.h similarity index 100% rename from lib/test/upper/pdcp_lte_test.h rename to lib/test/pdcp/pdcp_lte_test.h diff --git a/lib/test/upper/pdcp_lte_test_discard_sdu.cc b/lib/test/pdcp/pdcp_lte_test_discard_sdu.cc similarity index 100% rename from lib/test/upper/pdcp_lte_test_discard_sdu.cc rename to lib/test/pdcp/pdcp_lte_test_discard_sdu.cc diff --git a/lib/test/upper/pdcp_lte_test_rx.cc b/lib/test/pdcp/pdcp_lte_test_rx.cc similarity index 100% rename from lib/test/upper/pdcp_lte_test_rx.cc rename to lib/test/pdcp/pdcp_lte_test_rx.cc diff --git a/lib/test/upper/pdcp_lte_test_status_report.cc b/lib/test/pdcp/pdcp_lte_test_status_report.cc similarity index 100% rename from lib/test/upper/pdcp_lte_test_status_report.cc rename to lib/test/pdcp/pdcp_lte_test_status_report.cc diff --git a/lib/test/upper/pdcp_nr_test.h b/lib/test/pdcp/pdcp_nr_test.h similarity index 100% rename from lib/test/upper/pdcp_nr_test.h rename to lib/test/pdcp/pdcp_nr_test.h diff --git a/lib/test/upper/pdcp_nr_test_discard_sdu.cc b/lib/test/pdcp/pdcp_nr_test_discard_sdu.cc similarity index 100% rename from lib/test/upper/pdcp_nr_test_discard_sdu.cc rename to lib/test/pdcp/pdcp_nr_test_discard_sdu.cc diff --git a/lib/test/upper/pdcp_nr_test_rx.cc b/lib/test/pdcp/pdcp_nr_test_rx.cc similarity index 100% rename from lib/test/upper/pdcp_nr_test_rx.cc rename to lib/test/pdcp/pdcp_nr_test_rx.cc diff --git a/lib/test/upper/pdcp_nr_test_tx.cc b/lib/test/pdcp/pdcp_nr_test_tx.cc similarity index 100% rename from lib/test/upper/pdcp_nr_test_tx.cc rename to lib/test/pdcp/pdcp_nr_test_tx.cc diff --git a/lib/test/rlc/CMakeLists.txt b/lib/test/rlc/CMakeLists.txt index 135a8f19b..50cfab6c3 100644 --- a/lib/test/rlc/CMakeLists.txt +++ b/lib/test/rlc/CMakeLists.txt @@ -9,23 +9,23 @@ set(CTEST_LABELS "lib;rlc") add_executable(rlc_am_data_test rlc_am_data_test.cc) -target_link_libraries(rlc_am_data_test srsran_upper srsran_phy srsran_common) +target_link_libraries(rlc_am_data_test srsran_rlc srsran_phy srsran_common) add_lte_test(rlc_am_data_test rlc_am_data_test) add_executable(rlc_am_control_test rlc_am_control_test.cc) -target_link_libraries(rlc_am_control_test srsran_upper srsran_phy) +target_link_libraries(rlc_am_control_test srsran_rlc srsran_phy) add_lte_test(rlc_am_control_test rlc_am_control_test) add_executable(rlc_am_test rlc_am_test.cc) -target_link_libraries(rlc_am_test srsran_upper srsran_phy srsran_common) +target_link_libraries(rlc_am_test srsran_rlc srsran_phy srsran_common) add_lte_test(rlc_am_test rlc_am_test) add_executable(rlc_am_nr_pdu_test rlc_am_nr_pdu_test.cc) -target_link_libraries(rlc_am_nr_pdu_test srsran_upper srsran_phy) +target_link_libraries(rlc_am_nr_pdu_test srsran_rlc srsran_phy) add_nr_test(rlc_am_nr_pdu_test rlc_am_nr_pdu_test) add_executable(rlc_stress_test rlc_stress_test.cc) -target_link_libraries(rlc_stress_test srsran_upper srsran_mac srsran_phy srsran_common ${Boost_LIBRARIES} ${ATOMIC_LIBS}) +target_link_libraries(rlc_stress_test srsran_rlc srsran_mac srsran_phy srsran_common ${Boost_LIBRARIES} ${ATOMIC_LIBS}) add_lte_test(rlc_am_stress_test rlc_stress_test --mode=AM --loglevel 1 --sdu_gen_delay 250) add_lte_test(rlc_um_stress_test rlc_stress_test --mode=UM --loglevel 1) add_lte_test(rlc_tm_stress_test rlc_stress_test --mode=TM --loglevel 1 --random_opp=false) @@ -34,23 +34,23 @@ add_nr_test(rlc_um6_nr_stress_test rlc_stress_test --rat NR --mode=UM6 --logleve add_nr_test(rlc_um12_nr_stress_test rlc_stress_test --rat NR --mode=UM12 --loglevel 1) add_executable(rlc_um_data_test rlc_um_data_test.cc) -target_link_libraries(rlc_um_data_test srsran_upper srsran_phy srsran_common) +target_link_libraries(rlc_um_data_test srsran_rlc srsran_phy srsran_common) add_test(rlc_um_data_test rlc_um_data_test) add_executable(rlc_um_test rlc_um_test.cc) -target_link_libraries(rlc_um_test srsran_upper srsran_phy) +target_link_libraries(rlc_um_test srsran_rlc srsran_phy) add_test(rlc_um_test rlc_um_test) add_executable(rlc_common_test rlc_common_test.cc) -target_link_libraries(rlc_common_test srsran_upper srsran_phy) +target_link_libraries(rlc_common_test srsran_rlc srsran_phy) add_test(rlc_common_test rlc_common_test) add_executable(rlc_um_nr_pdu_test rlc_um_nr_pdu_test.cc) -target_link_libraries(rlc_um_nr_pdu_test srsran_upper srsran_mac srsran_phy) +target_link_libraries(rlc_um_nr_pdu_test srsran_rlc srsran_mac srsran_phy) add_nr_test(rlc_um_nr_pdu_test rlc_um_nr_pdu_test) add_executable(rlc_um_nr_test rlc_um_nr_test.cc) -target_link_libraries(rlc_um_nr_test srsran_upper srsran_phy) +target_link_libraries(rlc_um_nr_test srsran_rlc srsran_phy) add_nr_test(rlc_um_nr_test rlc_um_nr_test) ######################################################################## diff --git a/lib/test/rlc/rlc_am_control_test.cc b/lib/test/rlc/rlc_am_control_test.cc index 38ea7481f..0fce797f4 100644 --- a/lib/test/rlc/rlc_am_control_test.cc +++ b/lib/test/rlc/rlc_am_control_test.cc @@ -11,7 +11,7 @@ */ #include "srsran/common/test_common.h" -#include "srsran/upper/rlc_am_lte.h" +#include "srsran/rlc/rlc_am_lte.h" #include // Simple status PDU diff --git a/lib/test/rlc/rlc_am_data_test.cc b/lib/test/rlc/rlc_am_data_test.cc index fc40c1002..9779db916 100644 --- a/lib/test/rlc/rlc_am_data_test.cc +++ b/lib/test/rlc/rlc_am_data_test.cc @@ -11,7 +11,7 @@ */ #include "srsran/common/test_common.h" -#include "srsran/upper/rlc_am_lte.h" +#include "srsran/rlc/rlc_am_lte.h" #include // Fixed header only diff --git a/lib/test/rlc/rlc_am_nr_pdu_test.cc b/lib/test/rlc/rlc_am_nr_pdu_test.cc index b31136fcf..6b72a6fc2 100644 --- a/lib/test/rlc/rlc_am_nr_pdu_test.cc +++ b/lib/test/rlc/rlc_am_nr_pdu_test.cc @@ -11,8 +11,8 @@ */ #include "srsran/config.h" -#include "srsran/upper/rlc.h" -#include "srsran/upper/rlc_am_nr.h" +#include "srsran/rlc/rlc.h" +#include "srsran/rlc/rlc_am_nr.h" #include #include diff --git a/lib/test/rlc/rlc_am_test.cc b/lib/test/rlc/rlc_am_test.cc index 3ceff8f75..0186f5a7c 100644 --- a/lib/test/rlc/rlc_am_test.cc +++ b/lib/test/rlc/rlc_am_test.cc @@ -16,7 +16,7 @@ #include "srsran/common/threads.h" #include "srsran/interfaces/ue_pdcp_interfaces.h" #include "srsran/interfaces/ue_rrc_interfaces.h" -#include "srsran/upper/rlc_am_lte.h" +#include "srsran/rlc/rlc_am_lte.h" #define NBUFS 5 #define HAVE_PCAP 0 @@ -75,8 +75,8 @@ public: const char* get_rb_name(uint32_t lcid) { return ""; } std::vector sdus; - rlc_pcap* pcap = nullptr; - bool max_retx_triggered = false; + rlc_pcap* pcap = nullptr; + bool max_retx_triggered = false; bool protocol_failure_triggered = false; std::map notified_counts; // Map of PDCP SNs to number of notifications diff --git a/lib/test/rlc/rlc_common_test.cc b/lib/test/rlc/rlc_common_test.cc index cdcf198c1..1623c4623 100644 --- a/lib/test/rlc/rlc_common_test.cc +++ b/lib/test/rlc/rlc_common_test.cc @@ -10,7 +10,7 @@ * */ -#include "srsran/upper/rlc.h" +#include "srsran/rlc/rlc.h" #include #define TESTASSERT(cond) \ diff --git a/lib/test/rlc/rlc_stress_test.cc b/lib/test/rlc/rlc_stress_test.cc index d2530bfe2..cc6478be1 100644 --- a/lib/test/rlc/rlc_stress_test.cc +++ b/lib/test/rlc/rlc_stress_test.cc @@ -16,7 +16,7 @@ #include "srsran/common/test_common.h" #include "srsran/common/threads.h" #include "srsran/common/tsan_options.h" -#include "srsran/upper/rlc.h" +#include "srsran/rlc/rlc.h" #include #include #include diff --git a/lib/test/rlc/rlc_um_data_test.cc b/lib/test/rlc/rlc_um_data_test.cc index 1f69e9c7e..f5681ac14 100644 --- a/lib/test/rlc/rlc_um_data_test.cc +++ b/lib/test/rlc/rlc_um_data_test.cc @@ -11,7 +11,7 @@ */ #include "srsran/common/test_common.h" -#include "srsran/upper/rlc_um_lte.h" +#include "srsran/rlc/rlc_um_lte.h" #include // Fixed header only diff --git a/lib/test/rlc/rlc_um_nr_pdu_test.cc b/lib/test/rlc/rlc_um_nr_pdu_test.cc index e84c774a7..06e2bdaca 100644 --- a/lib/test/rlc/rlc_um_nr_pdu_test.cc +++ b/lib/test/rlc/rlc_um_nr_pdu_test.cc @@ -11,8 +11,8 @@ */ #include "srsran/config.h" -#include "srsran/upper/rlc.h" -#include "srsran/upper/rlc_um_nr.h" +#include "srsran/rlc/rlc.h" +#include "srsran/rlc/rlc_um_nr.h" #include #include diff --git a/lib/test/rlc/rlc_um_nr_test.cc b/lib/test/rlc/rlc_um_nr_test.cc index 2f0e014a5..82a58f341 100644 --- a/lib/test/rlc/rlc_um_nr_test.cc +++ b/lib/test/rlc/rlc_um_nr_test.cc @@ -13,8 +13,8 @@ #include "rlc_test_common.h" #include "srsran/config.h" #include "srsran/interfaces/ue_pdcp_interfaces.h" -#include "srsran/upper/rlc.h" -#include "srsran/upper/rlc_um_nr.h" +#include "srsran/rlc/rlc.h" +#include "srsran/rlc/rlc_um_nr.h" #include #include diff --git a/lib/test/rlc/rlc_um_test.cc b/lib/test/rlc/rlc_um_test.cc index 6edbf86b1..38018a638 100644 --- a/lib/test/rlc/rlc_um_test.cc +++ b/lib/test/rlc/rlc_um_test.cc @@ -11,7 +11,7 @@ */ #include "rlc_test_common.h" -#include "srsran/upper/rlc_um_lte.h" +#include "srsran/rlc/rlc_um_lte.h" #include #define TESTASSERT(cond) \ diff --git a/srsenb/src/CMakeLists.txt b/srsenb/src/CMakeLists.txt index 7f8a9895d..6cbf72f82 100644 --- a/srsenb/src/CMakeLists.txt +++ b/srsenb/src/CMakeLists.txt @@ -27,7 +27,7 @@ target_link_libraries(enb_cfg_parser ${LIBCONFIGPP_LIBRARIES}) add_executable(srsenb main.cc enb.cc metrics_stdout.cc metrics_csv.cc metrics_json.cc) set(SRSENB_SOURCES srsenb_phy srsenb_stack srsenb_common srsenb_s1ap srsenb_upper srsenb_mac srsenb_rrc srslog system) -set(SRSRAN_SOURCES srsran_common srsran_mac srsran_phy srsran_upper srsran_rlc srsran_radio rrc_asn1 s1ap_asn1 enb_cfg_parser srslog system) +set(SRSRAN_SOURCES srsran_common srsran_mac srsran_phy srsran_upper srsran_rlc srsran_pdcp srsran_radio rrc_asn1 s1ap_asn1 enb_cfg_parser srslog system) set(SRSENB_SOURCES ${SRSENB_SOURCES} srsgnb_phy srsgnb_stack srsgnb_ngap srsgnb_upper srsgnb_mac srsgnb_rrc) set(SRSRAN_SOURCES ${SRSRAN_SOURCES} rrc_nr_asn1 ngap_nr_asn1) diff --git a/srsue/src/CMakeLists.txt b/srsue/src/CMakeLists.txt index 83eec18c8..70285a03a 100644 --- a/srsue/src/CMakeLists.txt +++ b/srsue/src/CMakeLists.txt @@ -22,7 +22,7 @@ endif (RPATH) add_executable(srsue main.cc ue.cc metrics_stdout.cc metrics_csv.cc metrics_json.cc) set(SRSUE_SOURCES srsue_phy srsue_stack srsue_upper srsue_mac srsue_rrc srslog system) -set(SRSRAN_SOURCES srsran_common srsran_mac srsran_phy srsran_radio srsran_upper srsran_rlc rrc_asn1 srslog system) +set(SRSRAN_SOURCES srsran_common srsran_mac srsran_phy srsran_radio srsran_upper srsran_rlc srsran_pdcp rrc_asn1 srslog system) set(SRSUE_SOURCES ${SRSUE_SOURCES} srsue_nr_stack srsue_rrc_nr srsue_mac_nr) set(SRSRAN_SOURCES ${SRSRAN_SOURCES} rrc_nr_asn1 ngap_nr_asn1) diff --git a/srsue/src/stack/rrc/test/CMakeLists.txt b/srsue/src/stack/rrc/test/CMakeLists.txt index 9a79ce608..0a999b53d 100644 --- a/srsue/src/stack/rrc/test/CMakeLists.txt +++ b/srsue/src/stack/rrc/test/CMakeLists.txt @@ -11,7 +11,7 @@ target_link_libraries(rrc_reconfig_test srsue_upper srsran_upper srsran_phy rrc_ add_test(rrc_reconfig_test rrc_reconfig_test) add_executable(rrc_meas_test rrc_meas_test.cc) -target_link_libraries(rrc_meas_test srsue_rrc srsue_upper srsran_upper srsran_phy rrc_asn1 rrc_nr_asn1) +target_link_libraries(rrc_meas_test srsue_rrc srsue_upper srsran_upper srsran_pdcp srsran_phy rrc_asn1 rrc_nr_asn1) add_test(rrc_meas_test rrc_meas_test) add_executable(rrc_phy_ctrl_test rrc_phy_ctrl_test.cc) @@ -33,4 +33,4 @@ if (NOT ${BUILD_CMD} STREQUAL "") add_custom_command(TARGET ip_test POST_BUILD COMMAND ${BUILD_CMD}) else(NOT ${BUILD_CMD} STREQUAL "") message(STATUS "No post-build command defined") -endif (NOT ${BUILD_CMD} STREQUAL "") \ No newline at end of file +endif (NOT ${BUILD_CMD} STREQUAL "") diff --git a/srsue/src/test/ttcn3/src/CMakeLists.txt b/srsue/src/test/ttcn3/src/CMakeLists.txt index 9a53ad440..9daefdbea 100644 --- a/srsue/src/test/ttcn3/src/CMakeLists.txt +++ b/srsue/src/test/ttcn3/src/CMakeLists.txt @@ -20,6 +20,7 @@ set(LINK_LIBRARIES srsue_stack srsran_phy srsran_radio srsran_upper + srsran_pdcp srsue_phy srsue_mac srsue_mac_nr From 1b676aa406cd457e9da5b546f3123a6c65a4b2c3 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 28 Jun 2021 17:54:06 +0100 Subject: [PATCH 43/43] Moved lib GTPU to its own folder --- lib/src/CMakeLists.txt | 2 +- lib/src/{upper => gtpu}/CMakeLists.txt | 6 +++--- lib/src/{upper => gtpu}/gtpu.cc | 0 srsenb/src/CMakeLists.txt | 2 +- srsenb/test/ngap/CMakeLists.txt | 2 +- srsenb/test/s1ap/CMakeLists.txt | 2 +- srsenb/test/upper/CMakeLists.txt | 2 +- srsepc/src/CMakeLists.txt | 6 ++++-- srsue/src/CMakeLists.txt | 2 +- srsue/src/stack/rrc/test/CMakeLists.txt | 8 ++++---- srsue/src/stack/upper/test/CMakeLists.txt | 10 +++++----- srsue/src/test/ttcn3/src/CMakeLists.txt | 5 +++-- 12 files changed, 25 insertions(+), 22 deletions(-) rename lib/src/{upper => gtpu}/CMakeLists.txt (56%) rename lib/src/{upper => gtpu}/gtpu.cc (100%) diff --git a/lib/src/CMakeLists.txt b/lib/src/CMakeLists.txt index 2ff8d4d9a..fb5f62463 100644 --- a/lib/src/CMakeLists.txt +++ b/lib/src/CMakeLists.txt @@ -13,6 +13,6 @@ add_subdirectory(phy) add_subdirectory(radio) add_subdirectory(rlc) add_subdirectory(pdcp) +add_subdirectory(gtpu) add_subdirectory(srslog) add_subdirectory(system) -add_subdirectory(upper) diff --git a/lib/src/upper/CMakeLists.txt b/lib/src/gtpu/CMakeLists.txt similarity index 56% rename from lib/src/upper/CMakeLists.txt rename to lib/src/gtpu/CMakeLists.txt index dc8f12d41..a2a9f8ff4 100644 --- a/lib/src/upper/CMakeLists.txt +++ b/lib/src/gtpu/CMakeLists.txt @@ -8,6 +8,6 @@ set(SOURCES gtpu.cc) -add_library(srsran_upper STATIC ${SOURCES}) -target_link_libraries(srsran_upper srsran_common srsran_asn1 ${ATOMIC_LIBS}) -INSTALL(TARGETS srsran_upper DESTINATION ${LIBRARY_DIR}) +add_library(srsran_gtpu STATIC ${SOURCES}) +target_link_libraries(srsran_gtpu srsran_common srsran_asn1 ${ATOMIC_LIBS}) +INSTALL(TARGETS srsran_gtpu DESTINATION ${LIBRARY_DIR}) diff --git a/lib/src/upper/gtpu.cc b/lib/src/gtpu/gtpu.cc similarity index 100% rename from lib/src/upper/gtpu.cc rename to lib/src/gtpu/gtpu.cc diff --git a/srsenb/src/CMakeLists.txt b/srsenb/src/CMakeLists.txt index 6cbf72f82..e5a3c6f03 100644 --- a/srsenb/src/CMakeLists.txt +++ b/srsenb/src/CMakeLists.txt @@ -27,7 +27,7 @@ target_link_libraries(enb_cfg_parser ${LIBCONFIGPP_LIBRARIES}) add_executable(srsenb main.cc enb.cc metrics_stdout.cc metrics_csv.cc metrics_json.cc) set(SRSENB_SOURCES srsenb_phy srsenb_stack srsenb_common srsenb_s1ap srsenb_upper srsenb_mac srsenb_rrc srslog system) -set(SRSRAN_SOURCES srsran_common srsran_mac srsran_phy srsran_upper srsran_rlc srsran_pdcp srsran_radio rrc_asn1 s1ap_asn1 enb_cfg_parser srslog system) +set(SRSRAN_SOURCES srsran_common srsran_mac srsran_phy srsran_gtpu srsran_rlc srsran_pdcp srsran_radio rrc_asn1 s1ap_asn1 enb_cfg_parser srslog system) set(SRSENB_SOURCES ${SRSENB_SOURCES} srsgnb_phy srsgnb_stack srsgnb_ngap srsgnb_upper srsgnb_mac srsgnb_rrc) set(SRSRAN_SOURCES ${SRSRAN_SOURCES} rrc_nr_asn1 ngap_nr_asn1) diff --git a/srsenb/test/ngap/CMakeLists.txt b/srsenb/test/ngap/CMakeLists.txt index 0824d8aac..c64ab8e3f 100644 --- a/srsenb/test/ngap/CMakeLists.txt +++ b/srsenb/test/ngap/CMakeLists.txt @@ -7,7 +7,7 @@ # add_executable(ngap_test ngap_test.cc) -target_link_libraries(ngap_test srsran_common ngap_nr_asn1 srsenb_upper srsran_upper ngap_nr_asn1 srsgnb_upper srsgnb_ngap ${SCTP_LIBRARIES}) +target_link_libraries(ngap_test srsran_common ngap_nr_asn1 srsenb_upper srsran_gtpu ngap_nr_asn1 srsgnb_upper srsgnb_ngap ${SCTP_LIBRARIES}) add_test(ngap_test ngap_test) diff --git a/srsenb/test/s1ap/CMakeLists.txt b/srsenb/test/s1ap/CMakeLists.txt index accc3eb73..6419653ef 100644 --- a/srsenb/test/s1ap/CMakeLists.txt +++ b/srsenb/test/s1ap/CMakeLists.txt @@ -7,6 +7,6 @@ # add_executable(s1ap_test s1ap_test.cc) -target_link_libraries(s1ap_test srsran_common s1ap_asn1 srsenb_s1ap srsenb_upper srsran_upper s1ap_asn1 ${SCTP_LIBRARIES}) +target_link_libraries(s1ap_test srsran_common s1ap_asn1 srsenb_s1ap srsenb_upper s1ap_asn1 ${SCTP_LIBRARIES}) add_test(s1ap_test s1ap_test) diff --git a/srsenb/test/upper/CMakeLists.txt b/srsenb/test/upper/CMakeLists.txt index 73cd6eab0..425a97e8a 100644 --- a/srsenb/test/upper/CMakeLists.txt +++ b/srsenb/test/upper/CMakeLists.txt @@ -11,7 +11,7 @@ add_executable(plmn_test plmn_test.cc) target_link_libraries(plmn_test rrc_asn1) add_executable(gtpu_test gtpu_test.cc) -target_link_libraries(gtpu_test srsran_common s1ap_asn1 srsenb_upper srsran_upper ${SCTP_LIBRARIES}) +target_link_libraries(gtpu_test srsran_common s1ap_asn1 srsenb_upper srsran_gtpu ${SCTP_LIBRARIES}) add_test(plmn_test plmn_test) add_test(gtpu_test gtpu_test) diff --git a/srsepc/src/CMakeLists.txt b/srsepc/src/CMakeLists.txt index 07c15e79f..fac9a9ca5 100644 --- a/srsepc/src/CMakeLists.txt +++ b/srsepc/src/CMakeLists.txt @@ -27,7 +27,8 @@ target_link_libraries( srsepc srsepc_mme srsepc_hss srsepc_sgw s1ap_asn1 - srsran_upper + srsran_gtpu + srsran_asn1 srsran_common srslog ${CMAKE_THREAD_LIBS_INIT} @@ -38,7 +39,8 @@ target_link_libraries( srsepc srsepc_mme add_executable(srsmbms mbms-gw/main.cc ) target_link_libraries(srsmbms srsepc_mbms_gw - srsran_upper + srsran_asn1 + srsran_gtpu srsran_common srslog ${CMAKE_THREAD_LIBS_INIT} diff --git a/srsue/src/CMakeLists.txt b/srsue/src/CMakeLists.txt index 70285a03a..7b37cff78 100644 --- a/srsue/src/CMakeLists.txt +++ b/srsue/src/CMakeLists.txt @@ -22,7 +22,7 @@ endif (RPATH) add_executable(srsue main.cc ue.cc metrics_stdout.cc metrics_csv.cc metrics_json.cc) set(SRSUE_SOURCES srsue_phy srsue_stack srsue_upper srsue_mac srsue_rrc srslog system) -set(SRSRAN_SOURCES srsran_common srsran_mac srsran_phy srsran_radio srsran_upper srsran_rlc srsran_pdcp rrc_asn1 srslog system) +set(SRSRAN_SOURCES srsran_common srsran_mac srsran_phy srsran_radio srsran_gtpu srsran_rlc srsran_pdcp rrc_asn1 srslog system) set(SRSUE_SOURCES ${SRSUE_SOURCES} srsue_nr_stack srsue_rrc_nr srsue_mac_nr) set(SRSRAN_SOURCES ${SRSRAN_SOURCES} rrc_nr_asn1 ngap_nr_asn1) diff --git a/srsue/src/stack/rrc/test/CMakeLists.txt b/srsue/src/stack/rrc/test/CMakeLists.txt index 0a999b53d..ef592dc2d 100644 --- a/srsue/src/stack/rrc/test/CMakeLists.txt +++ b/srsue/src/stack/rrc/test/CMakeLists.txt @@ -7,11 +7,11 @@ # add_executable(rrc_reconfig_test rrc_reconfig_test.cc) -target_link_libraries(rrc_reconfig_test srsue_upper srsran_upper srsran_phy rrc_asn1) +target_link_libraries(rrc_reconfig_test srsue_upper srsran_phy srsran_asn1 rrc_asn1 srslog) add_test(rrc_reconfig_test rrc_reconfig_test) add_executable(rrc_meas_test rrc_meas_test.cc) -target_link_libraries(rrc_meas_test srsue_rrc srsue_upper srsran_upper srsran_pdcp srsran_phy rrc_asn1 rrc_nr_asn1) +target_link_libraries(rrc_meas_test srsue_rrc srsue_upper srsran_pdcp srsran_phy rrc_asn1 rrc_nr_asn1) add_test(rrc_meas_test rrc_meas_test) add_executable(rrc_phy_ctrl_test rrc_phy_ctrl_test.cc) @@ -19,11 +19,11 @@ target_link_libraries(rrc_phy_ctrl_test srsran_common srsue_rrc ${ATOMIC_LIBS}) add_test(rrc_phy_ctrl_test rrc_phy_ctrl_test) add_executable(rrc_cell_test rrc_cell_test.cc) -target_link_libraries(rrc_cell_test srsue_rrc srsue_upper srsran_upper srsran_phy rrc_asn1 rrc_nr_asn1) +target_link_libraries(rrc_cell_test srsue_rrc srsue_upper srsran_pdcp srsran_phy rrc_asn1 rrc_nr_asn1) add_test(rrc_cell_test rrc_cell_test) add_executable(ue_rrc_nr_test ue_rrc_nr_test.cc) -target_link_libraries(ue_rrc_nr_test srsue_rrc_nr srsue_upper srsran_common srsran_upper srsran_phy rrc_asn1 rrc_nr_asn1) +target_link_libraries(ue_rrc_nr_test srsue_rrc_nr srsue_upper srsran_common srsran_pdcp srsran_phy rrc_asn1 rrc_nr_asn1) ######################################################################## # Option to run command after build (useful for remote builds) diff --git a/srsue/src/stack/upper/test/CMakeLists.txt b/srsue/src/stack/upper/test/CMakeLists.txt index 54f6b5b83..56dc8c469 100644 --- a/srsue/src/stack/upper/test/CMakeLists.txt +++ b/srsue/src/stack/upper/test/CMakeLists.txt @@ -7,24 +7,24 @@ # add_executable(usim_test usim_test.cc) -target_link_libraries(usim_test srsue_upper srsran_upper srsran_phy rrc_asn1) +target_link_libraries(usim_test srsue_upper srsran_phy rrc_asn1 srslog) add_test(usim_test usim_test) if(HAVE_PCSC) add_executable(pcsc_usim_test pcsc_usim_test.cc) - target_link_libraries(pcsc_usim_test srsue_upper srsran_upper srsran_phy) + target_link_libraries(pcsc_usim_test srsue_upper srsran_phy srsran_common srslog) endif(HAVE_PCSC) add_executable(nas_test nas_test.cc) -target_link_libraries(nas_test srsue_upper srsran_upper srsran_phy rrc_asn1) +target_link_libraries(nas_test srsue_upper srsran_common srsran_phy rrc_asn1 srsran_asn1) add_test(nas_test nas_test) add_executable(gw_test gw_test.cc) -target_link_libraries(gw_test srsue_upper srsran_upper srsran_phy) +target_link_libraries(gw_test srsue_upper srsran_common srsran_phy) add_test(gw_test gw_test) add_executable(tft_test tft_test.cc) -target_link_libraries(tft_test srsue_upper srsran_upper srsran_phy) +target_link_libraries(tft_test srsue_upper srsran_common srsran_phy) add_test(tft_test tft_test) ######################################################################## diff --git a/srsue/src/test/ttcn3/src/CMakeLists.txt b/srsue/src/test/ttcn3/src/CMakeLists.txt index 9daefdbea..1f600b470 100644 --- a/srsue/src/test/ttcn3/src/CMakeLists.txt +++ b/srsue/src/test/ttcn3/src/CMakeLists.txt @@ -13,13 +13,14 @@ set(LINK_LIBRARIES srsue_stack srsue_upper srsue_rrc srsue_rrc_nr - srsran_upper + srsran_gtpu + srsran_pdcp srsran_rlc srsran_common srsran_mac srsran_phy srsran_radio - srsran_upper + srsran_gtpu srsran_pdcp srsue_phy srsue_mac