diff --git a/lib/include/srslte/interfaces/sched_interface.h b/lib/include/srslte/interfaces/sched_interface.h index f8d3738ed..b48af0f21 100644 --- a/lib/include/srslte/interfaces/sched_interface.h +++ b/lib/include/srslte/interfaces/sched_interface.h @@ -246,8 +246,8 @@ public: virtual bool ue_exists(uint16_t rnti) = 0; /* Manages UE bearers and associated configuration */ - virtual int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, ue_bearer_cfg_t* cfg) = 0; - virtual int bearer_ue_rem(uint16_t rnti, uint32_t lc_id) = 0; + virtual int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, const ue_bearer_cfg_t& cfg) = 0; + virtual int bearer_ue_rem(uint16_t rnti, uint32_t lc_id) = 0; virtual uint32_t get_ul_buffer(uint16_t rnti) = 0; virtual uint32_t get_dl_buffer(uint16_t rnti) = 0; diff --git a/srsenb/hdr/stack/mac/sched.h b/srsenb/hdr/stack/mac/sched.h index de1f78c8c..228cfabcd 100644 --- a/srsenb/hdr/stack/mac/sched.h +++ b/srsenb/hdr/stack/mac/sched.h @@ -49,7 +49,7 @@ public: void phy_config_enabled(uint16_t rnti, bool enabled); - int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, ue_bearer_cfg_t* cfg) final; + int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, const ue_bearer_cfg_t& cfg) final; int bearer_ue_rem(uint16_t rnti, uint32_t lc_id) final; uint32_t get_ul_buffer(uint16_t rnti) final; diff --git a/srsenb/src/stack/mac/mac.cc b/srsenb/src/stack/mac/mac.cc index 722db3bf4..66773b765 100644 --- a/srsenb/src/stack/mac/mac.cc +++ b/srsenb/src/stack/mac/mac.cc @@ -158,7 +158,7 @@ int mac::bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer int ret = -1; srslte::rwlock_read_guard lock(rwlock); if (ue_db.count(rnti)) { - ret = scheduler.bearer_ue_cfg(rnti, lc_id, cfg); + ret = scheduler.bearer_ue_cfg(rnti, lc_id, *cfg); } else { Error("User rnti=0x%x not found\n", rnti); } diff --git a/srsenb/src/stack/mac/sched.cc b/srsenb/src/stack/mac/sched.cc index ae4d58084..464ac75e5 100644 --- a/srsenb/src/stack/mac/sched.cc +++ b/srsenb/src/stack/mac/sched.cc @@ -138,9 +138,9 @@ void sched::phy_config_enabled(uint16_t rnti, bool enabled) rnti, [this, enabled](sched_ue& ue) { ue.phy_config_enabled(last_tti, enabled); }, __PRETTY_FUNCTION__); } -int sched::bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t* cfg_) +int sched::bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, const sched_interface::ue_bearer_cfg_t& cfg_) { - return ue_db_access(rnti, [lc_id, cfg_](sched_ue& ue) { ue.set_bearer_cfg(lc_id, *cfg_); }); + return ue_db_access(rnti, [lc_id, cfg_](sched_ue& ue) { ue.set_bearer_cfg(lc_id, cfg_); }); } int sched::bearer_ue_rem(uint16_t rnti, uint32_t lc_id) diff --git a/srsenb/test/mac/sched_ca_test.cc b/srsenb/test/mac/sched_ca_test.cc index 68b9d82ad..9ce41b374 100644 --- a/srsenb/test/mac/sched_ca_test.cc +++ b/srsenb/test/mac/sched_ca_test.cc @@ -122,11 +122,11 @@ int test_scell_activation(test_scell_activation_params params) tti_ev::user_cfg_ev* user = generator.add_new_default_user(duration, sim_args.default_ue_sim_cfg.ue_cfg); user->rnti = rnti1; tester.test_next_ttis(generator.tti_events); - TESTASSERT(tester.ue_tester->user_exists(rnti1)); + TESTASSERT(tester.sched_sim->user_exists(rnti1)); // Event (TTI=prach_tti+msg4_tot_delay): First Tx (Msg4). Goes in SRB0 and contains ConRes - while (not tester.ue_tester->get_user_ctxt(rnti1)->get_ctxt().msg3_tti_rx.is_valid() or - srsenb::to_tx_ul(tester.ue_tester->get_user_ctxt(rnti1)->get_ctxt().msg3_tti_rx).to_uint() > + while (not tester.sched_sim->find_rnti(rnti1)->get_ctxt().msg3_tti_rx.is_valid() or + srsenb::to_tx_ul(tester.sched_sim->find_rnti(rnti1)->get_ctxt().msg3_tti_rx).to_uint() > generator.tti_counter) { generator.step_tti(); tester.test_next_ttis(generator.tti_events); @@ -134,7 +134,7 @@ int test_scell_activation(test_scell_activation_params params) generator.step_tti(); generator.add_dl_data(rnti1, msg4_size); tester.test_next_ttis(generator.tti_events); - while (not tester.ue_tester->get_user_ctxt(rnti1)->get_ctxt().conres_rx) { + while (not tester.sched_sim->find_rnti(rnti1)->get_ctxt().conres_rx) { generator.step_tti(); tester.test_next_ttis(generator.tti_events); } diff --git a/srsenb/test/mac/sched_sim_ue.cc b/srsenb/test/mac/sched_sim_ue.cc index 92d02668f..c05dc1f57 100644 --- a/srsenb/test/mac/sched_sim_ue.cc +++ b/srsenb/test/mac/sched_sim_ue.cc @@ -12,6 +12,7 @@ #include "sched_sim_ue.h" #include "lib/include/srslte/mac/pdu.h" +#include "sched_test_utils.h" namespace srsenb { @@ -46,7 +47,6 @@ ue_sim::ue_sim(uint16_t rnti_, ctxt.rnti = rnti_; ctxt.prach_tti_rx = prach_tti_rx_; ctxt.preamble_idx = preamble_idx; - pending_feedback.cc_list.resize(cell_params->size()); set_cfg(ue_cfg_); } @@ -67,108 +67,8 @@ void ue_sim::bearer_cfg(uint32_t lc_id, const sched_interface::ue_bearer_cfg_t& ctxt.ue_cfg.ue_bearers.at(lc_id) = cfg; } -ue_sim::sync_tti_events ue_sim::get_pending_events(srslte::tti_point tti_rx, sched_interface* sched) -{ - pending_feedback.tti_rx = tti_rx; - for (uint32_t enb_cc_idx = 0; enb_cc_idx < pending_feedback.cc_list.size(); ++enb_cc_idx) { - auto& cc_feedback = pending_feedback.cc_list[enb_cc_idx]; - cc_feedback = {}; - if (ctxt.enb_to_ue_cc_idx(enb_cc_idx) < 0) { - continue; - } - - cc_feedback.configured = true; - cc_feedback.ue_cc_idx = ctxt.enb_to_ue_cc_idx(enb_cc_idx); - for (uint32_t pid = 0; pid < SRSLTE_FDD_NOF_HARQ; ++pid) { - auto& dl_h = ctxt.cc_list[cc_feedback.ue_cc_idx].dl_harqs[pid]; - auto& ul_h = ctxt.cc_list[cc_feedback.ue_cc_idx].ul_harqs[pid]; - - // Set default DL ACK - if (dl_h.active and to_tx_dl_ack(dl_h.last_tti_rx) == tti_rx) { - cc_feedback.dl_pid = pid; - cc_feedback.dl_ack = false; // default is NACK - } - - // Set default UL ACK - if (ul_h.active and to_tx_ul(ul_h.last_tti_rx) == tti_rx) { - cc_feedback.ul_pid = pid; - cc_feedback.ul_ack = false; - } - - // Set default DL CQI - if (srslte_cqi_periodic_send( - &ctxt.ue_cfg.supported_cc_list[cc_feedback.ue_cc_idx].dl_cfg.cqi_report, tti_rx.to_uint(), SRSLTE_FDD)) { - cc_feedback.dl_cqi = 0; - } - - // TODO: UL CQI - } - } - return {this, sched}; -} - -void ue_sim::push_feedback(sched_interface* sched) -{ - for (uint32_t enb_cc_idx = 0; enb_cc_idx < pending_feedback.cc_list.size(); ++enb_cc_idx) { - const auto& cc_feedback = pending_feedback.cc_list[enb_cc_idx]; - if (not cc_feedback.configured) { - continue; - } - - if (cc_feedback.dl_pid >= 0) { - auto& h = ctxt.cc_list[cc_feedback.ue_cc_idx].dl_harqs[cc_feedback.dl_pid]; - - if (cc_feedback.dl_ack) { - log_h->info( - "DL ACK rnti=0x%x tti_dl_tx=%u pid=%d\n", ctxt.rnti, to_tx_dl(h.last_tti_rx).to_uint(), cc_feedback.dl_pid); - } - // update scheduler - if (sched->dl_ack_info( - pending_feedback.tti_rx.to_uint(), ctxt.rnti, enb_cc_idx, cc_feedback.tb, cc_feedback.dl_ack) < 0) { - log_h->error("The ACKed DL Harq pid=%d does not exist.\n", cc_feedback.dl_pid); - error_count++; - } - - // set UE sim context - if (cc_feedback.dl_ack or 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 = ctxt.cc_list[cc_feedback.ue_cc_idx].ul_harqs[cc_feedback.dl_pid]; - - if (cc_feedback.ul_ack) { - log_h->info( - "UL ACK rnti=0x%x tti_ul_tx=%u pid=%d\n", ctxt.rnti, to_tx_ul(h.last_tti_rx).to_uint(), cc_feedback.dl_pid); - } - - // update scheduler - if (sched->ul_crc_info(pending_feedback.tti_rx.to_uint(), ctxt.rnti, enb_cc_idx, cc_feedback.ul_ack) < 0) { - log_h->error("The ACKed UL Harq pid=%d does not exist.\n", cc_feedback.ul_pid); - error_count++; - } - } - - if (cc_feedback.dl_cqi >= 0) { - sched->dl_cqi_info(pending_feedback.tti_rx.to_uint(), ctxt.rnti, enb_cc_idx, cc_feedback.dl_cqi); - } - - if (cc_feedback.ul_cqi >= 0) { - sched->ul_snr_info(pending_feedback.tti_rx.to_uint(), ctxt.rnti, enb_cc_idx, cc_feedback.ul_cqi, 0); - } - } -} - int ue_sim::update(const sf_output_res_t& sf_out) { - if (error_count > 0) { - return SRSLTE_ERROR; - } - if (pending_feedback.tti_rx != sf_out.tti_rx) { - // generate default events - auto default_events = get_pending_events(sf_out.tti_rx, nullptr); - } update_conn_state(sf_out); update_dl_harqs(sf_out); update_ul_harqs(sf_out); @@ -318,45 +218,182 @@ void ue_sim::update_conn_state(const sf_output_res_t& sf_out) } } -void ue_db_sim::add_user(uint16_t rnti, - const sched_interface::ue_cfg_t& ue_cfg_, - srslte::tti_point prach_tti_rx_, - uint32_t preamble_idx) +int sched_sim_base::add_user(uint16_t rnti, const sched_interface::ue_cfg_t& ue_cfg_, uint32_t preamble_idx) { - ue_db.insert(std::make_pair(rnti, ue_sim(rnti, *cell_params, ue_cfg_, prach_tti_rx_, preamble_idx))); + CONDERROR(!srslte_prach_tti_opportunity_config_fdd( + (*cell_params)[ue_cfg_.supported_cc_list[0].enb_cc_idx].prach_config, current_tti_rx.to_uint(), -1), + "New user added in a non-PRACH TTI\n"); + TESTASSERT(ue_db.count(rnti) == 0); + + final_ue_cfg[rnti] = ue_cfg_; + auto rach_cfg = generate_rach_ue_cfg(ue_cfg_); + ue_db.insert(std::make_pair(rnti, ue_sim(rnti, *cell_params, rach_cfg, current_tti_rx, preamble_idx))); + + CONDERROR(sched_ptr->ue_cfg(rnti, generate_rach_ue_cfg(ue_cfg_)) != SRSLTE_SUCCESS, + "Configuring new user rnti=0x%x to sched\n", + rnti); + + sched_interface::dl_sched_rar_info_t rar_info = {}; + rar_info.prach_tti = current_tti_rx.to_uint(); + rar_info.temp_crnti = rnti; + rar_info.msg3_size = 7; + rar_info.preamble_idx = preamble_idx; + uint32_t pcell_idx = ue_cfg_.supported_cc_list[0].enb_cc_idx; + TESTASSERT(sched_ptr->dl_rach_info(pcell_idx, rar_info) == SRSLTE_SUCCESS); + + return SRSLTE_SUCCESS; } -void ue_db_sim::ue_recfg(uint16_t rnti, const sched_interface::ue_cfg_t& ue_cfg_) +int sched_sim_base::ue_recfg(uint16_t rnti, const sched_interface::ue_cfg_t& ue_cfg_) { ue_db.at(rnti).set_cfg(ue_cfg_); + + CONDERROR(ue_db.count(rnti) == 0, "User must already exist to be configured\n"); + CONDERROR(sched_ptr->ue_cfg(rnti, ue_cfg_) != SRSLTE_SUCCESS, "Configuring new user rnti=0x%x to sched\n", rnti); + + return SRSLTE_SUCCESS; } -void ue_db_sim::bearer_cfg(uint16_t rnti, uint32_t lc_id, const sched_interface::ue_bearer_cfg_t& cfg) +int sched_sim_base::bearer_cfg(uint16_t rnti, uint32_t lc_id, const sched_interface::ue_bearer_cfg_t& cfg) { ue_db.at(rnti).bearer_cfg(lc_id, cfg); + return sched_ptr->bearer_ue_cfg(rnti, lc_id, cfg); } -void ue_db_sim::rem_user(uint16_t rnti) +int sched_sim_base::rem_user(uint16_t rnti) { ue_db.erase(rnti); + return sched_ptr->ue_rem(rnti); } -void ue_db_sim::update(const sf_output_res_t& sf_out) +void sched_sim_base::update(const sf_output_res_t& sf_out) { for (auto& ue_pair : ue_db) { ue_pair.second.update(sf_out); } } -std::map ue_db_sim::get_ues_ctxt() const +sim_enb_ctxt_t sched_sim_base::get_enb_ctxt() const { - std::map ret; + sim_enb_ctxt_t ctxt; + ctxt.cell_params = cell_params; for (auto& ue_pair : ue_db) { - ret.insert(std::make_pair(ue_pair.first, &ue_pair.second.get_ctxt())); + ctxt.ue_db.insert(std::make_pair(ue_pair.first, &ue_pair.second.get_ctxt())); } - return ret; + return ctxt; +} + +void sched_sim_base::set_default_tti_events(const sim_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]; + if (ue_ctxt.enb_to_ue_cc_idx(enb_cc_idx) < 0) { + continue; + } + + cc_feedback.configured = true; + cc_feedback.ue_cc_idx = ue_ctxt.enb_to_ue_cc_idx(enb_cc_idx); + for (uint32_t pid = 0; pid < SRSLTE_FDD_NOF_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 to_tx_dl_ack(dl_h.last_tti_rx) == 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 to_tx_ul(ul_h.last_tti_rx) == current_tti_rx) { + cc_feedback.ul_pid = pid; + cc_feedback.ul_ack = true; + } + + // Set default DL CQI + if (srslte_cqi_periodic_send(&ue_ctxt.ue_cfg.supported_cc_list[cc_feedback.ue_cc_idx].dl_cfg.cqi_report, + current_tti_rx.to_uint(), + SRSLTE_FDD)) { + cc_feedback.dl_cqi = 28; + } + + // TODO: UL CQI + } + } +} + +void sched_sim_base::apply_tti_events(sim_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) { + log_h->info("DL ACK rnti=0x%x tti_dl_tx=%u pid=%d\n", + ue_ctxt.rnti, + to_tx_dl(h.last_tti_rx).to_uint(), + cc_feedback.dl_pid); + } + + // update scheduler + if (sched_ptr->dl_ack_info( + events.tti_rx.to_uint(), ue_ctxt.rnti, enb_cc_idx, cc_feedback.tb, cc_feedback.dl_ack) < 0) { + log_h->error("The ACKed DL Harq pid=%d does not exist.\n", cc_feedback.dl_pid); + error_counter++; + } + + // 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.dl_pid]; + + if (cc_feedback.ul_ack) { + log_h->info("UL ACK rnti=0x%x tti_ul_tx=%u pid=%d\n", + ue_ctxt.rnti, + to_tx_ul(h.last_tti_rx).to_uint(), + cc_feedback.dl_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) { + log_h->error("The ACKed UL Harq pid=%d does not exist.\n", cc_feedback.ul_pid); + error_counter++; + } + } + + if (cc_feedback.dl_cqi >= 0) { + sched_ptr->dl_cqi_info(events.tti_rx.to_uint(), ue_ctxt.rnti, enb_cc_idx, cc_feedback.dl_cqi); + } + + if (cc_feedback.ul_cqi >= 0) { + sched_ptr->ul_snr_info(events.tti_rx.to_uint(), ue_ctxt.rnti, enb_cc_idx, cc_feedback.ul_cqi, 0); + } + } +} + +void sched_sim_base::new_tti(srslte::tti_point tti_rx) +{ + current_tti_rx = tti_rx; + for (auto& ue : ue_db) { + ue_tti_events events; + set_default_tti_events(ue.second.get_ctxt(), events); + before_sched(ue.second.get_ctxt(), events); + apply_tti_events(ue.second.get_ctxt(), events); + } } } // namespace srsenb diff --git a/srsenb/test/mac/sched_sim_ue.h b/srsenb/test/mac/sched_sim_ue.h index f667f0e78..bab95e778 100644 --- a/srsenb/test/mac/sched_sim_ue.h +++ b/srsenb/test/mac/sched_sim_ue.h @@ -86,54 +86,38 @@ public: const sim_ue_ctxt_t& get_ctxt() const { return ctxt; } sim_ue_ctxt_t& get_ctxt() { return ctxt; } - class sync_tti_events - { - public: - sync_tti_events(ue_sim* ue_, sched_interface* sched_) : ue(ue_), sched(sched_) {} - sync_tti_events(const sync_tti_events&) = delete; - sync_tti_events(sync_tti_events&&) = default; - sync_tti_events& operator=(const sync_tti_events&) = delete; - sync_tti_events& operator=(sync_tti_events&&) = default; - ~sync_tti_events() { ue->push_feedback(sched); } - ue_tti_events* operator->() { return &ue->pending_feedback; } - ue_tti_events* operator*() { return &ue->pending_feedback; } - - private: - ue_sim* ue; - sched_interface* sched; - }; - sync_tti_events get_pending_events(srslte::tti_point tti_rx, sched_interface* sched); - private: void update_conn_state(const sf_output_res_t& sf_out); void update_dl_harqs(const sf_output_res_t& sf_out); void update_ul_harqs(const sf_output_res_t& sf_out); - void push_feedback(sched_interface* sched); srslte::log_ref log_h{"MAC"}; const std::vector* cell_params; sim_ue_ctxt_t ctxt; - ue_tti_events pending_feedback; - uint32_t error_count = 0; }; -class ue_db_sim +class sched_sim_base { public: - ue_db_sim(const std::vector& cell_params_) : cell_params(&cell_params_) {} - void add_user(uint16_t rnti, - const sched_interface::ue_cfg_t& ue_cfg_, - srslte::tti_point prach_tti_rx_, - uint32_t preamble_idx); - void ue_recfg(uint16_t rnti, const sched_interface::ue_cfg_t& ue_cfg_); - void bearer_cfg(uint16_t rnti, uint32_t lc_id, const sched_interface::ue_bearer_cfg_t& cfg); - void rem_user(uint16_t rnti); - - void update(const sf_output_res_t& sf_out); - std::map get_ues_ctxt() const; - ue_sim& at(uint16_t rnti) { return ue_db.at(rnti); } - const ue_sim& at(uint16_t rnti) const { return ue_db.at(rnti); } - ue_sim* find_rnti(uint16_t rnti) + sched_sim_base(sched_interface* sched_ptr_, const std::vector& cell_params_) : + sched_ptr(sched_ptr_), cell_params(&cell_params_) + { + sched_ptr->cell_cfg(cell_params_); // call parent cfg + } + virtual ~sched_sim_base() = default; + + int add_user(uint16_t rnti, const sched_interface::ue_cfg_t& ue_cfg_, uint32_t preamble_idx); + int ue_recfg(uint16_t rnti, const sched_interface::ue_cfg_t& ue_cfg_); + int bearer_cfg(uint16_t rnti, uint32_t lc_id, const sched_interface::ue_bearer_cfg_t& cfg); + int rem_user(uint16_t rnti); + + void new_tti(srslte::tti_point tti_rx); + void update(const sf_output_res_t& sf_out); + + sim_enb_ctxt_t get_enb_ctxt() const; + ue_sim& at(uint16_t rnti) { return ue_db.at(rnti); } + const ue_sim& at(uint16_t rnti) const { return ue_db.at(rnti); } + ue_sim* find_rnti(uint16_t rnti) { auto it = ue_db.find(rnti); return it != ue_db.end() ? &it->second : nullptr; @@ -143,13 +127,31 @@ public: 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_interface::ue_cfg_t* get_user_cfg(uint16_t rnti) const + { + const ue_sim* ret = find_rnti(rnti); + return ret == nullptr ? nullptr : &ret->get_ctxt().ue_cfg; + } std::map::iterator begin() { return ue_db.begin(); } std::map::iterator end() { return ue_db.end(); } + // configurable by simulator concrete implementation + virtual void before_sched(const sim_ue_ctxt_t& ue_ctxt, ue_tti_events& pending_events) = 0; + private: + void set_default_tti_events(const sim_ue_ctxt_t& ue_ctxt, ue_tti_events& pending_events); + void apply_tti_events(sim_ue_ctxt_t& ue_ctxt, const ue_tti_events& events); + + srslte::log_ref log_h{"MAC"}; + sched_interface* sched_ptr; const std::vector* cell_params; - std::map ue_db; + + srslte::tti_point current_tti_rx; + std::map ue_db; + std::map final_ue_cfg; + uint32_t error_counter = 0; }; } // namespace srsenb diff --git a/srsenb/test/mac/sched_test_common.cc b/srsenb/test/mac/sched_test_common.cc index b88e61cd6..330d87a73 100644 --- a/srsenb/test/mac/sched_test_common.cc +++ b/srsenb/test/mac/sched_test_common.cc @@ -12,7 +12,6 @@ #include "sched_test_common.h" #include "srsenb/hdr/stack/mac/sched.h" -#include "srsenb/hdr/stack/mac/sched_helpers.h" #include "srsenb/hdr/stack/upper/common_enb.h" #include "srslte/mac/pdu.h" @@ -48,103 +47,50 @@ std::default_random_engine& ::srsenb::get_rand_gen() * User State Tester ***********************/ -void user_state_sched_tester::new_tti(sched* sched_ptr, tti_point tti_rx) +void sched_sim_random::before_sched(const sim_ue_ctxt_t& ue_ctxt, ue_tti_events& pending_events) { - tic++; - for (auto& u : sim_users) { - auto pending_feedback = u.second.get_pending_events(tti_rx, sched_ptr); - auto& ctxt = u.second.get_ctxt(); - const auto& sim_cfg = ue_sim_cfg_map.at(u.first); - - for (uint32_t enb_cc_idx = 0; enb_cc_idx < pending_feedback->cc_list.size(); ++enb_cc_idx) { - auto& cc_feedback = pending_feedback->cc_list[enb_cc_idx]; - if (not cc_feedback.configured) { - continue; - } - - // ACK DL HARQs - if (cc_feedback.dl_pid >= 0) { - auto& h = ctxt.cc_list[cc_feedback.ue_cc_idx].dl_harqs[cc_feedback.dl_pid]; - cc_feedback.dl_ack = randf() < sim_cfg.prob_dl_ack_mask[h.nof_retxs % sim_cfg.prob_dl_ack_mask.size()]; - } - - // ACK UL HARQs - if (cc_feedback.ul_pid >= 0) { - auto& h = ctxt.cc_list[cc_feedback.ue_cc_idx].ul_harqs[cc_feedback.ul_pid]; - cc_feedback.ul_ack = randf() < sim_cfg.prob_ul_ack_mask[h.nof_retxs % sim_cfg.prob_ul_ack_mask.size()]; - } - - // DL CQI - if (cc_feedback.dl_cqi >= 0) { - cc_feedback.dl_cqi = std::uniform_int_distribution{5, 24}(get_rand_gen()); - } + const auto& sim_cfg = ue_sim_cfg_map.at(ue_ctxt.rnti); - // UL CQI - if (cc_feedback.ul_cqi >= 0) { - cc_feedback.ul_cqi = std::uniform_int_distribution{5, 40}(get_rand_gen()); - } + 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]; + if (not cc_feedback.configured) { + continue; } - } -} -int user_state_sched_tester::add_user(uint16_t rnti, uint32_t preamble_idx, const ue_ctxt_test_cfg& cfg_) -{ - CONDERROR(!srslte_prach_tti_opportunity_config_fdd( - cell_params[cfg_.ue_cfg.supported_cc_list[0].enb_cc_idx].prach_config, tic.to_uint(), -1), - "New user added in a non-PRACH TTI\n"); - TESTASSERT(sim_users.find_rnti(rnti) == nullptr); - sim_users.add_user(rnti, generate_rach_ue_cfg(cfg_.ue_cfg), tic, preamble_idx); - ue_sim_cfg_map[rnti] = cfg_; + // ACK DL HARQs + if (cc_feedback.dl_pid >= 0) { + auto& h = ue_ctxt.cc_list[cc_feedback.ue_cc_idx].dl_harqs[cc_feedback.dl_pid]; + cc_feedback.dl_ack = randf() < sim_cfg.prob_dl_ack_mask[h.nof_retxs % sim_cfg.prob_dl_ack_mask.size()]; + } - return SRSLTE_SUCCESS; -} + // ACK UL HARQs + if (cc_feedback.ul_pid >= 0) { + auto& h = ue_ctxt.cc_list[cc_feedback.ue_cc_idx].ul_harqs[cc_feedback.ul_pid]; + cc_feedback.ul_ack = randf() < sim_cfg.prob_ul_ack_mask[h.nof_retxs % sim_cfg.prob_ul_ack_mask.size()]; + } -int user_state_sched_tester::user_reconf(uint16_t rnti, const srsenb::sched_interface::ue_cfg_t& ue_cfg) -{ - TESTASSERT(sim_users.find_rnti(rnti) != nullptr); - sim_users.ue_recfg(rnti, ue_cfg); - return SRSLTE_SUCCESS; -} + // DL CQI + if (cc_feedback.dl_cqi >= 0) { + cc_feedback.dl_cqi = std::uniform_int_distribution{5, 24}(get_rand_gen()); + } -int user_state_sched_tester::bearer_cfg(uint16_t rnti, - uint32_t lcid, - const srsenb::sched_interface::ue_bearer_cfg_t& bearer_cfg) -{ - sim_users.bearer_cfg(rnti, lcid, bearer_cfg); - return SRSLTE_SUCCESS; + // UL CQI + if (cc_feedback.ul_cqi >= 0) { + cc_feedback.ul_cqi = std::uniform_int_distribution{5, 40}(get_rand_gen()); + } + } } -bool user_state_sched_tester::is_drb_cfg(uint16_t rnti) const +bool is_drb_cfg(const sched_interface::ue_cfg_t& ue_cfg) { - const ue_sim& ue = sim_users.at(rnti); - for (uint32_t i = 2; i < ue.get_ctxt().ue_cfg.ue_bearers.size(); ++i) { - if (ue.get_ctxt().ue_cfg.ue_bearers[i].direction != sched_interface::ue_bearer_cfg_t::IDLE) { + for (uint32_t i = 2; i < ue_cfg.ue_bearers.size(); ++i) { + if (ue_cfg.ue_bearers[i].direction != sched_interface::ue_bearer_cfg_t::IDLE) { return true; } } return false; } -void user_state_sched_tester::rem_user(uint16_t rnti) -{ - sim_users.rem_user(rnti); - ue_sim_cfg_map.erase(rnti); -} - -int user_state_sched_tester::test_all(const sf_output_res_t& sf_out) -{ - // Perform UE-dedicated sched result tests - sim_enb_ctxt_t enb_ctxt; - enb_ctxt.cell_params = &cell_params; - enb_ctxt.ue_db = sim_users.get_ues_ctxt(); - TESTASSERT(test_all_ues(enb_ctxt, sf_out) == SRSLTE_SUCCESS); - - // Update Simulated UEs state - sim_users.update(sf_out); - - return SRSLTE_SUCCESS; -} - /*********************** * Sim Stats Storage **********************/ @@ -183,17 +129,16 @@ sched_result_stats::user_stats* sched_result_stats::get_user(uint16_t rnti) const sched::ue_cfg_t* common_sched_tester::get_current_ue_cfg(uint16_t rnti) const { - return ue_tester->get_user_cfg(rnti); + return sched_sim->get_user_cfg(rnti); } int common_sched_tester::sim_cfg(sim_sched_args args) { sim_args0 = std::move(args); - sched::cell_cfg(sim_args0.cell_cfg); // call parent cfg sched::set_sched_cfg(&sim_args0.sched_args); - ue_tester.reset(new user_state_sched_tester{sim_args0.cell_cfg}); + sched_sim.reset(new sched_sim_random{this, sim_args0.cell_cfg}); sched_stats.reset(new sched_result_stats{sim_args0.cell_cfg}); tester_log = sim_args0.sim_log; @@ -203,40 +148,21 @@ int common_sched_tester::sim_cfg(sim_sched_args args) int common_sched_tester::add_user(uint16_t rnti, const ue_ctxt_test_cfg& ue_cfg_) { - CONDERROR(ue_cfg(rnti, generate_rach_ue_cfg(ue_cfg_.ue_cfg)) != SRSLTE_SUCCESS, - "Configuring new user rnti=0x%x to sched\n", - rnti); - // CONDERROR(!srslte_prach_tti_opportunity_config_fdd( - // sched_cell_params[CARRIER_IDX].cfg.prach_config, tti_info.tti_params.tti_rx, -1), - // "New user added in a non-PRACH TTI\n"); - - dl_sched_rar_info_t rar_info = {}; - rar_info.prach_tti = tti_rx.to_uint(); - rar_info.temp_crnti = rnti; - rar_info.msg3_size = 7; - rar_info.preamble_idx = tti_info.nof_prachs++; - uint32_t pcell_idx = ue_cfg_.ue_cfg.supported_cc_list[0].enb_cc_idx; - dl_rach_info(pcell_idx, rar_info); - - ue_tester->add_user(rnti, rar_info.preamble_idx, ue_cfg_); - tester_log->info("Adding user rnti=0x%x\n", rnti); - return SRSLTE_SUCCESS; + sched_sim->ue_sim_cfg_map[rnti] = ue_cfg_; + return sched_sim->add_user(rnti, ue_cfg_.ue_cfg, tti_info.nof_prachs++); } int common_sched_tester::reconf_user(uint16_t rnti, const sched_interface::ue_cfg_t& ue_cfg_) { - CONDERROR(not ue_tester->user_exists(rnti), "User must already exist to be configured\n"); - CONDERROR(ue_cfg(rnti, ue_cfg_) != SRSLTE_SUCCESS, "Configuring new user rnti=0x%x to sched\n", rnti); - ue_tester->user_reconf(rnti, ue_cfg_); - return SRSLTE_SUCCESS; + return sched_sim->ue_recfg(rnti, ue_cfg_); } -void common_sched_tester::rem_user(uint16_t rnti) +int common_sched_tester::rem_user(uint16_t rnti) { tester_log->info("Removing user rnti=0x%x\n", rnti); - sched::ue_rem(rnti); - ue_tester->rem_user(rnti); + sched_sim->ue_sim_cfg_map.erase(rnti); + return sched_sim->rem_user(rnti); } void common_sched_tester::new_test_tti() @@ -256,13 +182,23 @@ void common_sched_tester::new_test_tti() tester_log->step(tti_rx.to_uint()); } +int common_sched_tester::run_ue_ded_tests_and_update_ctxt(const sf_output_res_t& sf_out) +{ + // Perform UE-dedicated sched result tests + sim_enb_ctxt_t enb_ctxt = sched_sim->get_enb_ctxt(); + TESTASSERT(test_all_ues(enb_ctxt, sf_out) == SRSLTE_SUCCESS); + + // Update Simulated UEs state + sched_sim->update(sf_out); + return SRSLTE_SUCCESS; +} + int common_sched_tester::process_results() { // Perform common eNB result tests sf_output_res_t sf_out{sched_cell_params, tti_rx, tti_info.ul_sched_result, tti_info.dl_sched_result}; TESTASSERT(test_all_common(sf_out) == SRSLTE_SUCCESS); - - TESTASSERT(ue_tester->test_all(sf_out) == SRSLTE_SUCCESS); + TESTASSERT(run_ue_ded_tests_and_update_ctxt(sf_out) == SRSLTE_SUCCESS); sched_stats->process_results(tti_rx, tti_info.dl_sched_result, tti_info.ul_sched_result); @@ -274,7 +210,7 @@ int common_sched_tester::process_tti_events(const tti_ev& tti_ev) for (const tti_ev::user_cfg_ev& ue_ev : tti_ev.user_updates) { // There is a new configuration if (ue_ev.ue_sim_cfg != nullptr) { - if (not ue_tester->user_exists(ue_ev.rnti)) { + if (not sched_sim->user_exists(ue_ev.rnti)) { // new user TESTASSERT(add_user(ue_ev.rnti, *ue_ev.ue_sim_cfg) == SRSLTE_SUCCESS); } else { @@ -285,17 +221,17 @@ int common_sched_tester::process_tti_events(const tti_ev& tti_ev) // There is a user to remove if (ue_ev.rem_user) { - rem_user(ue_ev.rnti); + TESTASSERT(rem_user(ue_ev.rnti) == SRSLTE_SUCCESS); } // configure bearers if (ue_ev.bearer_cfg != nullptr) { - CONDERROR(not ue_tester->user_exists(ue_ev.rnti), "User rnti=0x%x does not exist\n", ue_ev.rnti); + CONDERROR(not sched_sim->user_exists(ue_ev.rnti), "User rnti=0x%x does not exist\n", ue_ev.rnti); // TODO: Instantiate more bearers - bearer_ue_cfg(ue_ev.rnti, 0, ue_ev.bearer_cfg.get()); + TESTASSERT(sched_sim->bearer_cfg(ue_ev.rnti, 0, *ue_ev.bearer_cfg) == SRSLTE_SUCCESS); } - const ue_sim* user = ue_tester->get_user_ctxt(ue_ev.rnti); + const ue_sim* user = sched_sim->find_rnti(ue_ev.rnti); if (user != nullptr) { const auto& ue_sim_ctxt = user->get_ctxt(); @@ -303,7 +239,8 @@ int common_sched_tester::process_tti_events(const tti_ev& tti_ev) to_tx_ul(ue_sim_ctxt.msg3_tti_rx) <= tti_rx) { // Msg3 has been received but Msg4 has not been yet transmitted // Setup default UE config - reconf_user(ue_sim_ctxt.rnti, generate_setup_ue_cfg(sim_args0.default_ue_sim_cfg.ue_cfg)); + TESTASSERT(reconf_user(ue_sim_ctxt.rnti, generate_setup_ue_cfg(sim_args0.default_ue_sim_cfg.ue_cfg)) == + SRSLTE_SUCCESS); // Schedule RRC Setup and ConRes CE uint32_t pending_dl_new_data = ue_db[ue_ev.rnti].get_pending_dl_rlc_data(); @@ -325,16 +262,15 @@ int common_sched_tester::process_tti_events(const tti_ev& tti_ev) // If Msg4 has already been tx and there DL data to transmit uint32_t lcid = RB_ID_DRB1; uint32_t pending_dl_new_data = ue_db[ue_ev.rnti].get_pending_dl_rlc_data(); - if (ue_tester->is_drb_cfg(ue_ev.rnti) or pending_dl_new_data == 0) { + if (is_drb_cfg(sched_sim->find_rnti(ue_ev.rnti)->get_ctxt().ue_cfg) or pending_dl_new_data == 0) { // If RRCSetup finished - if (not ue_tester->is_drb_cfg(ue_ev.rnti)) { + if (not is_drb_cfg(sched_sim->find_rnti(ue_ev.rnti)->get_ctxt().ue_cfg)) { reconf_user(ue_sim_ctxt.rnti, sim_args0.default_ue_sim_cfg.ue_cfg); // setup lcid==drb1 bearer sched::ue_bearer_cfg_t cfg = {}; cfg.direction = ue_bearer_cfg_t::BOTH; cfg.group = 1; - ue_tester->bearer_cfg(ue_ev.rnti, lcid, cfg); - bearer_ue_cfg(ue_ev.rnti, lcid, &cfg); + TESTASSERT(sched_sim->bearer_cfg(ue_ev.rnti, lcid, cfg) == SRSLTE_SUCCESS); } // DRB is set. Update DL buffer uint32_t tot_dl_data = pending_dl_new_data + ue_ev.buffer_ev->dl_data; // TODO: derive pending based on rx @@ -344,7 +280,7 @@ int common_sched_tester::process_tti_events(const tti_ev& tti_ev) } } - if (ue_ev.buffer_ev->sr_data > 0 and ue_tester->is_drb_cfg(ue_ev.rnti)) { + if (ue_ev.buffer_ev->sr_data > 0 and is_drb_cfg(sched_sim->find_rnti(ue_ev.rnti)->get_ctxt().ue_cfg)) { uint32_t tot_ul_data = ue_db[ue_ev.rnti].get_pending_ul_new_data(to_tx_ul(tti_rx), -1) + ue_ev.buffer_ev->sr_data; uint32_t lcg = 1; @@ -360,7 +296,7 @@ int common_sched_tester::run_tti(const tti_ev& tti_events) new_test_tti(); tester_log->info("---- tti=%u | nof_ues=%zd ----\n", tti_rx.to_uint(), ue_db.size()); - ue_tester->new_tti(this, tti_rx); + sched_sim->new_tti(tti_rx); process_tti_events(tti_events); before_sched(); diff --git a/srsenb/test/mac/sched_test_common.h b/srsenb/test/mac/sched_test_common.h index 422a81072..56b91490d 100644 --- a/srsenb/test/mac/sched_test_common.h +++ b/srsenb/test/mac/sched_test_common.h @@ -35,38 +35,12 @@ std::default_random_engine& get_rand_gen(); using dl_sched_res_list = std::vector; using ul_sched_res_list = std::vector; -class user_state_sched_tester +class sched_sim_random : public sched_sim_base { public: - explicit user_state_sched_tester(const std::vector& cell_params_) : - cell_params(cell_params_), sim_users(cell_params_) - {} - - void new_tti(sched* sched_ptr, tti_point tti_rx); - bool user_exists(uint16_t rnti) const { return sim_users.find_rnti(rnti) != nullptr; } - const ue_sim* get_user_ctxt(uint16_t rnti) const { return sim_users.find_rnti(rnti); } - const sched::ue_cfg_t* get_user_cfg(uint16_t rnti) const - { - const ue_sim* ue = get_user_ctxt(rnti); - return ue == nullptr ? nullptr : &ue->get_ctxt().ue_cfg; - } - - /* Config users */ - int add_user(uint16_t rnti, uint32_t preamble_idx, const ue_ctxt_test_cfg& cfg); - int user_reconf(uint16_t rnti, const srsenb::sched_interface::ue_cfg_t& ue_cfg); - int bearer_cfg(uint16_t rnti, uint32_t lcid, const srsenb::sched_interface::ue_bearer_cfg_t& bearer_cfg); - void rem_user(uint16_t rnti); - - int test_all(const sf_output_res_t& sf_out); - - bool is_drb_cfg(uint16_t rnti) const; - -private: - const std::vector& cell_params; - - ue_db_sim sim_users; + using sched_sim_base::sched_sim_base; + void before_sched(const sim_ue_ctxt_t& ue_ctxt, ue_tti_events& pending_events) override; std::map ue_sim_cfg_map; - srslte::tti_point tic; }; class sched_result_stats @@ -108,16 +82,18 @@ public: const ue_cfg_t* get_current_ue_cfg(uint16_t rnti) const; - int sim_cfg(sim_sched_args args); - virtual int add_user(uint16_t rnti, const ue_ctxt_test_cfg& ue_cfg_); - virtual int reconf_user(uint16_t rnti, const sched_interface::ue_cfg_t& ue_cfg_); - virtual void rem_user(uint16_t rnti); - virtual int process_results(); - int process_tti_events(const tti_ev& tti_ev); + int sim_cfg(sim_sched_args args); + virtual int add_user(uint16_t rnti, const ue_ctxt_test_cfg& ue_cfg_); + virtual int reconf_user(uint16_t rnti, const sched_interface::ue_cfg_t& ue_cfg_); + virtual int rem_user(uint16_t rnti); + virtual int process_results(); + int process_tti_events(const tti_ev& tti_ev); int test_next_ttis(const std::vector& tti_events); int run_tti(const tti_ev& tti_events); + int run_ue_ded_tests_and_update_ctxt(const sf_output_res_t& sf_out); + // args sim_sched_args sim_args0; ///< arguments used to generate TTI events srslte::log* tester_log = nullptr; @@ -127,9 +103,11 @@ public: tti_point tti_rx; uint32_t tti_count = 0; - // testers - std::unique_ptr ue_tester; - std::unique_ptr sched_stats; + // eNB+UE state handlers + std::unique_ptr sched_sim; + + // statistics + std::unique_ptr sched_stats; protected: virtual void new_test_tti(); diff --git a/srsenb/test/mac/sched_test_rand.cc b/srsenb/test/mac/sched_test_rand.cc index 81ecb29ac..8a25165c7 100644 --- a/srsenb/test/mac/sched_test_rand.cc +++ b/srsenb/test/mac/sched_test_rand.cc @@ -128,9 +128,9 @@ struct sched_tester : public srsenb::common_sched_tester { // sched results sched_tti_data tti_data; - void rem_user(uint16_t rnti) override; - int assert_no_empty_allocs(); - int test_harqs(); + int rem_user(uint16_t rnti) override; + int assert_no_empty_allocs(); + int test_harqs(); private: void new_test_tti() override; @@ -139,10 +139,10 @@ private: int update_ue_stats(); }; -void sched_tester::rem_user(uint16_t rnti) +int sched_tester::rem_user(uint16_t rnti) { - common_sched_tester::rem_user(rnti); tti_data.ue_data.erase(rnti); + return common_sched_tester::rem_user(rnti); } void sched_tester::new_test_tti() @@ -203,7 +203,7 @@ int sched_tester::process_results() TESTASSERT(test_pdsch_collisions(sf_out, CARRIER_IDX, &cc_result->dl_mask) == SRSLTE_SUCCESS); // UE dedicated tests - TESTASSERT(ue_tester->test_all(sf_out) == SRSLTE_SUCCESS); + TESTASSERT(run_ue_ded_tests_and_update_ctxt(sf_out) == SRSLTE_SUCCESS); assert_no_empty_allocs(); test_harqs(); update_ue_stats();