From 1afc137032acc8df48de861b3bd6df518954f54d Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 22 Sep 2020 21:47:16 +0200 Subject: [PATCH] [REBASE] Make PHY non-blocking and fefactor HO procedure (#1753) * Make PHY non-blocking and fefactor HO procedure * makes entire PHY non-blocking through command interface * adds dedicated queue for cell_search/cell_select commands * refactor HO procedure to run faster, in one stack cycle. Looks closer to the specs * force ue to always apply SIB2 configuration during reestablishment * Run update_measurements in all workers Co-authored-by: Ismael Gomez --- .../srslte/interfaces/phy_interface_types.h | 52 ++++ lib/include/srslte/interfaces/ue_interfaces.h | 55 ++-- lib/include/srslte/test/ue_test_interfaces.h | 29 +-- srsue/hdr/phy/cc_worker.h | 27 +- srsue/hdr/phy/phy.h | 83 ++++-- srsue/hdr/phy/prach.h | 5 +- srsue/hdr/phy/sf_worker.h | 14 +- srsue/hdr/phy/sync.h | 13 +- srsue/hdr/phy/sync_state.h | 10 +- srsue/hdr/stack/mac/mac.h | 4 +- srsue/hdr/stack/mac/proc_ra.h | 7 +- srsue/hdr/stack/rrc/phy_controller.h | 3 +- srsue/hdr/stack/rrc/rrc.h | 18 +- srsue/hdr/stack/rrc/rrc_cell.h | 6 +- srsue/hdr/stack/rrc/rrc_meas.h | 2 +- srsue/hdr/stack/rrc/rrc_nr.h | 3 +- srsue/hdr/stack/rrc/rrc_procedures.h | 12 +- srsue/hdr/stack/ue_stack_lte.h | 6 +- srsue/src/phy/cc_worker.cc | 59 +++-- srsue/src/phy/phy.cc | 226 ++++++++++++----- srsue/src/phy/phy_common.cc | 23 +- srsue/src/phy/prach.cc | 34 +-- srsue/src/phy/sf_worker.cc | 70 +++-- srsue/src/phy/sync.cc | 159 ++++++++---- srsue/src/stack/mac/dl_harq.cc | 4 - srsue/src/stack/mac/mac.cc | 20 +- srsue/src/stack/mac/proc_ra.cc | 61 ++--- srsue/src/stack/mac/ul_harq.cc | 2 +- srsue/src/stack/rrc/phy_controller.cc | 16 +- srsue/src/stack/rrc/rrc.cc | 123 +++++---- srsue/src/stack/rrc/rrc_cell.cc | 4 +- srsue/src/stack/rrc/rrc_meas.cc | 16 +- srsue/src/stack/rrc/rrc_nr.cc | 3 +- srsue/src/stack/rrc/rrc_procedures.cc | 240 ++++++++++-------- srsue/src/stack/ue_stack_lte.cc | 29 ++- srsue/test/mac_test.cc | 50 +++- srsue/test/phy/scell_search_test.cc | 5 + srsue/test/phy/ue_phy_test.cc | 53 +++- srsue/test/ttcn3/hdr/lte_ttcn3_phy.h | 20 +- srsue/test/ttcn3/src/lte_ttcn3_phy.cc | 60 ++--- srsue/test/ttcn3/src/ttcn3_syssim.cc | 2 +- srsue/test/upper/rrc_meas_test.cc | 102 +++----- srsue/test/upper/rrc_phy_ctrl_test.cc | 8 +- 43 files changed, 1029 insertions(+), 709 deletions(-) create mode 100644 lib/include/srslte/interfaces/phy_interface_types.h diff --git a/lib/include/srslte/interfaces/phy_interface_types.h b/lib/include/srslte/interfaces/phy_interface_types.h new file mode 100644 index 000000000..173fdd558 --- /dev/null +++ b/lib/include/srslte/interfaces/phy_interface_types.h @@ -0,0 +1,52 @@ +/* + * Copyright 2013-2020 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#ifndef SRSLTE_PHY_INTERFACE_TYPES_H +#define SRSLTE_PHY_INTERFACE_TYPES_H + +#include "srslte/phy/phch/prach.h" + +/// Common types defined by the PHY layer. + +inline bool operator==(const srslte_tdd_config_t& a, const srslte_tdd_config_t& b) +{ + return (a.sf_config == b.sf_config && a.ss_config == b.ss_config && a.configured == b.configured); +} + +inline bool operator!=(const srslte_tdd_config_t& a, const srslte_tdd_config_t& b) +{ + return !(a == b); +} + +inline bool operator==(const srslte_prach_cfg_t& a, const srslte_prach_cfg_t& b) +{ + return (a.config_idx == b.config_idx && a.root_seq_idx == b.root_seq_idx && a.zero_corr_zone == b.zero_corr_zone && + a.freq_offset == b.freq_offset && a.num_ra_preambles == b.num_ra_preambles && a.hs_flag == b.hs_flag && + a.tdd_config == b.tdd_config && a.enable_successive_cancellation == b.enable_successive_cancellation && + a.enable_freq_domain_offset_calc == b.enable_freq_domain_offset_calc); +} + +inline bool operator!=(const srslte_prach_cfg_t& a, const srslte_prach_cfg_t& b) +{ + return !(a == b); +} + +#endif // SRSLTE_PHY_INTERFACE_TYPES_H diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index 37b008927..87d95e89a 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -129,10 +129,16 @@ public: class rrc_interface_mac : public rrc_interface_mac_common { public: - virtual void ho_ra_completed() = 0; + virtual void ra_completed() = 0; virtual void release_pucch_srs() = 0; }; +struct phy_cell_t { + uint32_t pci; + uint32_t earfcn; + float cfo_hz; +}; + // RRC interface for PHY class rrc_interface_phy_lte { @@ -149,6 +155,16 @@ public: virtual void in_sync() = 0; virtual void out_of_sync() = 0; virtual void new_cell_meas(const std::vector& meas) = 0; + + typedef struct { + enum { CELL_FOUND = 0, CELL_NOT_FOUND, ERROR } found; + enum { MORE_FREQS = 0, NO_MORE_FREQS } last_freq; + } cell_search_ret_t; + + virtual void cell_search_complete(cell_search_ret_t ret, phy_cell_t found_cell) = 0; + virtual void cell_select_complete(bool status) = 0; + virtual void set_config_complete(bool status) = 0; + virtual void set_scell_complete(bool status) = 0; }; // RRC interface for NAS @@ -430,8 +446,6 @@ public: class mac_interface_rrc : public mac_interface_rrc_common { public: - virtual void clear_rntis() = 0; - /* Instructs the MAC to start receiving BCCH */ virtual void bcch_start_rx(int si_window_start, int si_window_length) = 0; virtual void bcch_stop_rx() = 0; @@ -445,18 +459,15 @@ public: /* Instructs the MAC to start receiving an MCH */ virtual void mch_start_rx(uint32_t lcid) = 0; - virtual void set_config(srslte::mac_cfg_t& mac_cfg) = 0; + virtual void set_config(srslte::mac_cfg_t& mac_cfg) = 0; + virtual void set_rach_ded_cfg(uint32_t preamble_index, uint32_t prach_mask) = 0; virtual void get_rntis(ue_rnti_t* rntis) = 0; virtual void set_contention_id(uint64_t uecri) = 0; virtual void set_ho_rnti(uint16_t crnti, uint16_t target_pci) = 0; - virtual void start_noncont_ho(uint32_t preamble_index, uint32_t prach_mask) = 0; - virtual void start_cont_ho() = 0; - virtual void reconfiguration(const uint32_t& cc_idx, const bool& enable) = 0; virtual void reset() = 0; - virtual void wait_uplink() = 0; }; /** PHY interface @@ -563,9 +574,6 @@ public: uint32_t preamble_format; } prach_info_t; - /* Configure PRACH using parameters written by RRC */ - virtual void configure_prach_params() = 0; - virtual void prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm, float ta_base_sec = 0.0f) = 0; virtual prach_info_t prach_get_info() = 0; @@ -580,10 +588,8 @@ public: class phy_interface_rrc_lte { public: - virtual void set_config(srslte::phy_cfg_t& config, - uint32_t cc_idx = 0, - uint32_t earfcn = 0, - srslte_cell_t* cell_info = nullptr) = 0; + virtual bool set_config(srslte::phy_cfg_t config, uint32_t cc_idx = 0) = 0; + virtual bool set_scell(srslte_cell_t cell_info, uint32_t cc_idx, uint32_t earfcn) = 0; virtual void set_config_tdd(srslte_tdd_config_t& tdd_config) = 0; virtual void set_config_mbsfn_sib2(srslte::mbsfn_sf_cfg_t* cfg_list, uint32_t nof_cfgs) = 0; virtual void set_config_mbsfn_sib13(const srslte::sib13_t& sib13) = 0; @@ -595,23 +601,10 @@ public: virtual void set_cells_to_meas(uint32_t earfcn, const std::set& pci) = 0; virtual void meas_stop() = 0; - typedef struct { - enum { CELL_FOUND = 0, CELL_NOT_FOUND, ERROR } found; - enum { MORE_FREQS = 0, NO_MORE_FREQS } last_freq; - } cell_search_ret_t; - - typedef struct { - uint32_t pci; - uint32_t earfcn; - float cfo_hz; - } phy_cell_t; - /* Cell search and selection procedures */ - virtual cell_search_ret_t cell_search(phy_cell_t* cell) = 0; - virtual bool cell_select(const phy_cell_t* cell = nullptr) = 0; - virtual bool cell_is_camping() = 0; - - virtual void reset() = 0; + virtual bool cell_search() = 0; + virtual bool cell_select(phy_cell_t cell) = 0; + virtual bool cell_is_camping() = 0; virtual void enable_pregen_signals(bool enable) = 0; }; diff --git a/lib/include/srslte/test/ue_test_interfaces.h b/lib/include/srslte/test/ue_test_interfaces.h index 548ef290c..177083290 100644 --- a/lib/include/srslte/test/ue_test_interfaces.h +++ b/lib/include/srslte/test/ue_test_interfaces.h @@ -67,27 +67,24 @@ public: class phy_dummy_interface : public phy_interface_rrc_lte { - void - set_config(srslte::phy_cfg_t& config, uint32_t cc_idx = 0, uint32_t earfcn = 0, srslte_cell_t* cell_info = nullptr) - {} - void set_config_tdd(srslte_tdd_config_t& tdd_config) {} - void set_config_mbsfn_sib2(srslte::mbsfn_sf_cfg_t* cfg_list, uint32_t nof_cfgs) {} - void set_config_mbsfn_sib13(const srslte::sib13_t& sib13) {} - void set_config_mbsfn_mcch(const srslte::mcch_msg_t& mcch) {} - void set_activation_deactivation_scell(uint32_t cmd) {} + bool set_config(srslte::phy_cfg_t config, uint32_t cc_idx = 0) override { return true; } + bool set_scell(srslte_cell_t cell_info, uint32_t cc_idx, uint32_t earfcn) override { return true; } + void set_config_tdd(srslte_tdd_config_t& tdd_config) override {} + void set_config_mbsfn_sib2(srslte::mbsfn_sf_cfg_t* cfg_list, uint32_t nof_cfgs) override {} + void set_config_mbsfn_sib13(const srslte::sib13_t& sib13) override {} + void set_config_mbsfn_mcch(const srslte::mcch_msg_t& mcch) override {} + void set_activation_deactivation_scell(uint32_t cmd) override {} /* Measurements interface */ - void set_cells_to_meas(uint32_t earfcn, const std::set& pci) {} - void meas_stop() {} + void set_cells_to_meas(uint32_t earfcn, const std::set& pci) override {} + void meas_stop() override {} /* Cell search and selection procedures */ - cell_search_ret_t cell_search(phy_cell_t* cell) { return {}; } - bool cell_select(const phy_cell_t* cell = nullptr) { return true; } - bool cell_is_camping() { return false; } + bool cell_search() override { return true; } + bool cell_select(phy_cell_t cell) override { return true; } + bool cell_is_camping() override { return false; } - void reset() {} - - void enable_pregen_signals(bool enable) {} + void enable_pregen_signals(bool enable) override {} }; } // namespace srsue diff --git a/srsue/hdr/phy/cc_worker.h b/srsue/hdr/phy/cc_worker.h index e3ced18d0..2fd798c3b 100644 --- a/srsue/hdr/phy/cc_worker.h +++ b/srsue/hdr/phy/cc_worker.h @@ -33,9 +33,6 @@ class cc_worker public: cc_worker(uint32_t cc_idx, uint32_t max_prb, phy_common* phy, srslte::log* log); ~cc_worker(); - void reset(); - - bool set_cell(srslte_cell_t cell); /* Functions used by main PHY thread */ cf_t* get_rx_buffer(uint32_t antenna_idx); @@ -43,13 +40,18 @@ public: uint32_t get_buffer_len(); void set_tti(uint32_t tti); - void set_cfo(float cfo); - - void set_tdd_config(srslte_tdd_config_t config); - void set_config(srslte::phy_cfg_t& phy_cfg); - void upd_config_dci(srslte_dci_cfg_t& dci_cfg); - void set_crnti(uint16_t rnti); - void enable_pregen_signals(bool enabled); + void set_cfo_unlocked(float cfo); + float get_ref_cfo() const; + + // Functions to set configuration. + // Warning: all these functions are unlocked and must be called while the worker is not processing data + void reset_cell_unlocked(); + bool set_cell_unlocked(srslte_cell_t cell_); + void set_tdd_config_unlocked(srslte_tdd_config_t config); + void set_config_unlocked(srslte::phy_cfg_t& phy_cfg); + void upd_config_dci_unlocked(srslte_dci_cfg_t& dci_cfg); + void set_crnti_unlocked(uint16_t rnti); + void enable_pregen_signals_unlocked(bool enabled); void set_uci_periodic_cqi(srslte_uci_data_t* uci_data); @@ -64,6 +66,8 @@ public: cf_t* rssi_power_buffer = nullptr); private: + void reset(); + void dl_phy_to_mac_grant(srslte_pdsch_grant_t* phy_grant, srslte_dci_dl_t* dl_dci, mac_interface_phy_lte::mac_grant_dl_t* mac_grant); @@ -116,9 +120,6 @@ private: /* Objects for UL */ srslte_ue_ul_t ue_ul = {}; srslte_ue_ul_cfg_t ue_ul_cfg = {}; - - // Mutex, for protecting what matters most: ue_ul, ue_ul_cfg, ue_dl, ue_dl_cfg, cell, pmch_cfg - std::mutex mutex; }; } // namespace srsue diff --git a/srsue/hdr/phy/phy.h b/srsue/hdr/phy/phy.h index 8f21df510..702986a47 100644 --- a/srsue/hdr/phy/phy.h +++ b/srsue/hdr/phy/phy.h @@ -27,7 +27,9 @@ #include "prach.h" #include "sf_worker.h" #include "srslte/common/log_filter.h" +#include "srslte/common/threads.h" #include "srslte/common/trace.h" +#include "srslte/interfaces/phy_interface_types.h" #include "srslte/interfaces/radio_interfaces.h" #include "srslte/interfaces/ue_interfaces.h" #include "srslte/radio/radio.h" @@ -39,6 +41,37 @@ namespace srsue { typedef _Complex float cf_t; +class phy_cmd_proc : public srslte::thread +{ +public: + phy_cmd_proc() : thread("PHY_CMD") { start(); } + + ~phy_cmd_proc() { stop(); } + + void add_cmd(std::function cmd) { cmd_queue.push(cmd); } + + void stop() + { + if (running) { + add_cmd([this]() { running = false; }); + wait_thread_finish(); + } + } + +private: + void run_thread() + { + std::function cmd; + while (running) { + cmd = cmd_queue.wait_pop(); + cmd(); + } + } + bool running = true; + // Queue for commands + srslte::block_queue > cmd_queue; +}; + class phy final : public ue_lte_phy_base, public srslte::thread { public: @@ -65,23 +98,40 @@ public: void radio_failure() final; /********** RRC INTERFACE ********************/ - void reset() final; - cell_search_ret_t cell_search(phy_cell_t* cell) final; - bool cell_select(const phy_cell_t* cell) final; + bool cell_search() final; + bool cell_select(phy_cell_t cell) final; + + // Sets the new PHY configuration for the given CC. The configuration is applied in the background. The notify() + // function will be called when the reconfiguration is completed. Unless the PRACH configuration has changed, the + // reconfiguration will not take more than 3 ms + bool set_config(srslte::phy_cfg_t config, uint32_t cc_idx) final; + + // Adds or modifies the cell configuration for a given CC. If the EARFCN has changed w.r.t. the previous value, or if + // the cell is new, this function might take a few hundred ms to complete, depending on the radio + bool set_scell(srslte_cell_t cell_info, uint32_t cc_idx, uint32_t earfcn) final; + + // Applies a TDD configuration in the background. This function will take less than 3 ms to execute. + void set_config_tdd(srslte_tdd_config_t& tdd_config) final; + + // Todo + void set_config_mbsfn_sib2(srslte::mbsfn_sf_cfg_t* cfg_list, uint32_t nof_cfgs) final; + void set_config_mbsfn_sib13(const srslte::sib13_t& sib13) final; + void set_config_mbsfn_mcch(const srslte::mcch_msg_t& mcch) final; + + // This function applies the new configuration immediately void set_cells_to_meas(uint32_t earfcn, const std::set& pci) final; + + // This function applies the new configuration immediately void meas_stop() final; // also MAC interface bool cell_is_camping() final; /********** MAC INTERFACE ********************/ - /* Sets a C-RNTI allowing the PHY to pregenerate signals if necessary */ + // Precomputes sequences for the given RNTI. The computation is done in the background. void set_crnti(uint16_t rnti) final; - /* Instructs the PHY to configure using the parameters written by set_param() */ - void configure_prach_params() final; - /* Transmits PRACH in the next opportunity */ void prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm, float ta_base_sec) final; prach_info_t prach_get_info() final; @@ -100,14 +150,6 @@ public: /* Sets RAR dci payload */ void set_rar_grant(uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN], uint16_t rnti) final; - /* Get/Set PHY parameters interface from RRC */ - void set_config(srslte::phy_cfg_t& config, uint32_t cc_idx, uint32_t earfcn, srslte_cell_t* cell_info) final; - void set_config_tdd(srslte_tdd_config_t& tdd_config) final; - - void set_config_mbsfn_sib2(srslte::mbsfn_sf_cfg_t* cfg_list, uint32_t nof_cfgs) final; - void set_config_mbsfn_sib13(const srslte::sib13_t& sib13) final; - void set_config_mbsfn_mcch(const srslte::mcch_msg_t& mcch) final; - /*Set MAC->PHY MCH period stopping point*/ void set_mch_period_stop(uint32_t stop) final; @@ -125,6 +167,8 @@ public: private: void run_thread() final; + void configure_prach_params(); + void reset(); std::mutex config_mutex; std::condition_variable config_cond; @@ -154,8 +198,15 @@ private: srslte::phy_cfg_t config = {}; phy_args_t args = {}; + // Since cell_search/cell_select operations take a lot of time, we use another queue to process the other commands + // in parallel and avoid accumulating in the queue + phy_cmd_proc cmd_worker_cell, cmd_worker; + + // Tracks the current selected cell (last call to cell_select) + srslte_cell_t selected_cell = {}; + static void set_default_args(phy_args_t& args); - bool check_args(const phy_args_t& args); + bool check_args(const phy_args_t& args); }; } // namespace srsue diff --git a/srsue/hdr/phy/prach.h b/srsue/hdr/phy/prach.h index 1181bee1b..3a6e6aeef 100644 --- a/srsue/hdr/phy/prach.h +++ b/srsue/hdr/phy/prach.h @@ -39,8 +39,9 @@ public: void init(uint32_t max_prb, srslte::log* log_h); void stop(); bool set_cell(srslte_cell_t cell, srslte_prach_cfg_t prach_cfg); + void reset_cfg(); bool prepare_to_send(uint32_t preamble_idx, int allowed_subframe = -1, float target_power_dbm = -1); - bool is_ready_to_send(uint32_t current_tti); + bool is_ready_to_send(uint32_t current_tti, uint32_t current_pci); bool is_pending() const; cf_t* generate(float cfo, uint32_t* nof_sf, float* target_power = NULL); @@ -71,7 +72,7 @@ private: srslte_prach_cfg_t cfg = {}; std::array, max_fs> buffer = {}; cf_t* signal_buffer = nullptr; - int preamble_idx = 0; + int preamble_idx = -1; uint32_t len = 0; int allowed_subframe = 0; int transmitted_tti = 0; diff --git a/srsue/hdr/phy/sf_worker.h b/srsue/hdr/phy/sf_worker.h index 8dcbb7a04..9749d127a 100644 --- a/srsue/hdr/phy/sf_worker.h +++ b/srsue/hdr/phy/sf_worker.h @@ -43,9 +43,9 @@ class sf_worker : public srslte::thread_pool::worker public: sf_worker(uint32_t max_prb, phy_common* phy, srslte::log* log, srslte::log* log_phy_lib_h); virtual ~sf_worker(); - void reset(); - bool set_cell(uint32_t cc_idx, srslte_cell_t cell); + void reset_cell_unlocked(uint32_t cc_idx); + bool set_cell_unlocked(uint32_t cc_idx, srslte_cell_t cell_); /* Functions used by main PHY thread */ cf_t* get_buffer(uint32_t cc_idx, uint32_t antenna_idx); @@ -53,12 +53,12 @@ public: void set_tti(uint32_t tti); void set_tx_time(const srslte::rf_timestamp_t& tx_time); void set_prach(cf_t* prach_ptr, float prach_power); - void set_cfo(const uint32_t& cc_idx, float cfo); + void set_cfo_unlocked(const uint32_t& cc_idx, float cfo); - void set_tdd_config(srslte_tdd_config_t config); - void set_config(uint32_t cc_idx, srslte::phy_cfg_t& phy_cfg); - void set_crnti(uint16_t rnti); - void enable_pregen_signals(bool enabled); + void set_tdd_config_unlocked(srslte_tdd_config_t config); + void set_config_unlocked(uint32_t cc_idx, srslte::phy_cfg_t phy_cfg); + void set_crnti_unlocked(uint16_t rnti); + void enable_pregen_signals_unlocked(bool enabled); ///< Methods for plotting called from GUI thread int read_ce_abs(float* ce_abs, uint32_t tx_antenna, uint32_t rx_antenna); diff --git a/srsue/hdr/phy/sync.h b/srsue/hdr/phy/sync.h index bcdf9f6fc..4a33f53d9 100644 --- a/srsue/hdr/phy/sync.h +++ b/srsue/hdr/phy/sync.h @@ -67,8 +67,10 @@ public: void radio_overflow(); // RRC interface for controling the SYNC state - phy_interface_rrc_lte::cell_search_ret_t cell_search(phy_interface_rrc_lte::phy_cell_t* cell); - bool cell_select(const phy_interface_rrc_lte::phy_cell_t* cell); + bool cell_search_init(); + rrc_interface_phy_lte::cell_search_ret_t cell_search_start(phy_cell_t* cell); + bool cell_select_init(phy_cell_t cell); + bool cell_select_start(phy_cell_t cell); bool cell_is_camping(); // RRC interface for controlling the neighbour cell measurement @@ -227,6 +229,13 @@ private: uint32_t in_sync_cnt = 0; std::mutex rrc_mutex; + enum { + PROC_IDLE = 0, + PROC_SELECT_START, + PROC_SELECT_RUNNING, + PROC_SEARCH_START, + PROC_SEARCH_RUNNING + } rrc_proc_state = PROC_IDLE; sync_state phy_state; diff --git a/srsue/hdr/phy/sync_state.h b/srsue/hdr/phy/sync_state.h index 920d26bca..56c16380a 100644 --- a/srsue/hdr/phy/sync_state.h +++ b/srsue/hdr/phy/sync_state.h @@ -75,7 +75,8 @@ public: void go_idle() { std::lock_guard lock(outside); - go_state(IDLE); + // Do not wait when transitioning to IDLE to avoid blocking + go_state_nowait(IDLE); } void run_cell_search() { @@ -125,6 +126,13 @@ private: } } + void go_state_nowait(state_t s) + { + std::unique_lock ul(inside); + next_state = s; + state_setting = true; + } + /* Waits until there is a call to set_state() and then run_state(). Returns when run_state() returns */ void wait_state_run() { diff --git a/srsue/hdr/stack/mac/mac.h b/srsue/hdr/stack/mac/mac.h index 629d79f9d..a5116fc52 100644 --- a/srsue/hdr/stack/mac/mac.h +++ b/srsue/hdr/stack/mac/mac.h @@ -81,7 +81,6 @@ public: void mch_start_rx(uint32_t lcid); void reconfiguration(const uint32_t& cc_idx, const bool& enable); void reset(); - void wait_uplink(); /******** set/get MAC configuration ****************/ void set_config(mac_cfg_t& mac_cfg); @@ -91,8 +90,7 @@ public: void reset_harq(uint32_t cc_idx); bool contention_resolution_id_rcv(uint64_t id); - void start_noncont_ho(uint32_t preamble_index, uint32_t prach_mask); - void start_cont_ho(); + void set_rach_ded_cfg(uint32_t preamble_index, uint32_t prach_mask); void get_rntis(ue_rnti_t* rntis); void set_ho_rnti(uint16_t crnti, uint16_t target_pci); diff --git a/srsue/hdr/stack/mac/proc_ra.h b/srsue/hdr/stack/mac/proc_ra.h index 12130e828..cb1a6971a 100644 --- a/srsue/hdr/stack/mac/proc_ra.h +++ b/srsue/hdr/stack/mac/proc_ra.h @@ -77,9 +77,10 @@ public: void reset(); void set_config(srslte::rach_cfg_t& rach_cfg); + void set_config_ded(uint32_t preamble_index, uint32_t prach_mask); void start_pdcch_order(); - void start_mac_order(uint32_t msg_len_bits = 56, bool is_ho = false); + void start_mac_order(uint32_t msg_len_bits = 56); void step(uint32_t tti); void update_rar_window(int& rar_window_start, int& rar_window_length); @@ -91,11 +92,9 @@ public: void new_grant_dl(mac_interface_phy_lte::mac_grant_dl_t grant, mac_interface_phy_lte::tb_action_dl_t* action); void tb_decoded_ok(const uint8_t cc_idx, const uint32_t tti); - void start_noncont(uint32_t preamble_index, uint32_t prach_mask); bool contention_resolution_id_received(uint64_t uecri); void start_pcap(srslte::mac_pcap* pcap); - void notify_phy_config_completed(uint32_t task_id); void notify_ra_completed(uint32_t task_id); bool is_idle() const { return state == IDLE; } @@ -149,7 +148,6 @@ private: enum { IDLE = 0, - WAITING_PHY_CONFIG, PDCCH_SETUP, RESPONSE_RECEPTION, BACKOFF_WAIT, @@ -183,7 +181,6 @@ private: std::mutex mutex; - bool ra_is_ho; bool started_by_pdcch; uint32_t rar_grant_nbytes; bool rar_received; diff --git a/srsue/hdr/stack/rrc/phy_controller.h b/srsue/hdr/stack/rrc/phy_controller.h index 2bfe45a6f..6e7b26bf7 100644 --- a/srsue/hdr/stack/rrc/phy_controller.h +++ b/srsue/hdr/stack/rrc/phy_controller.h @@ -31,8 +31,7 @@ namespace srsue { class phy_controller : public srslte::fsm_t { - using phy_cell_t = phy_interface_rrc_lte::phy_cell_t; - using cell_search_ret_t = phy_interface_rrc_lte::cell_search_ret_t; + using cell_search_ret_t = rrc_interface_phy_lte::cell_search_ret_t; public: static const uint32_t wait_sync_timeout_ms = 50; diff --git a/srsue/hdr/stack/rrc/rrc.h b/srsue/hdr/stack/rrc/rrc.h index c08f138fc..14a77ec59 100644 --- a/srsue/hdr/stack/rrc/rrc.h +++ b/srsue/hdr/stack/rrc/rrc.h @@ -123,9 +123,13 @@ public: void in_sync() final; void out_of_sync() final; void new_cell_meas(const std::vector& meas); + void cell_search_complete(cell_search_ret_t ret, phy_cell_t found_cell); + void cell_select_complete(bool status); + void set_config_complete(bool status); + void set_scell_complete(bool status); // MAC interface - void ho_ra_completed() final; + void ra_completed() final; void release_pucch_srs(); void run_tti(); void ra_problem(); @@ -141,22 +145,18 @@ public: void write_pdu_pcch(srslte::unique_byte_buffer_t pdu); void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu); - // STACK interface - void cell_search_completed(const phy_interface_rrc_lte::cell_search_ret_t& cs_ret, - const phy_interface_rrc_lte::phy_cell_t& found_cell); - void cell_select_completed(bool cs_ret); - bool srbs_flushed(); //< Check if data on SRBs still needs to be sent protected: // Moved to protected to be accessible by unit tests - void set_serving_cell(phy_interface_rrc_lte::phy_cell_t phy_cell, bool discard_serving); + void set_serving_cell(phy_cell_t phy_cell, bool discard_serving); bool has_neighbour_cell(uint32_t earfcn, uint32_t pci) const; + bool is_serving_cell(uint32_t earfcn, uint32_t pci) const; int start_cell_select(); private: typedef struct { - enum { PCCH, RLF, HO_COMPLETE, STOP } command; + enum { PCCH, RLF, RA_COMPLETE, STOP } command; srslte::unique_byte_buffer_t pdu; uint16_t lcid; } cmd_msg_t; @@ -301,7 +301,7 @@ private: class cell_reselection_proc; class connection_reest_proc; class ho_proc; - srslte::proc_t cell_searcher; + srslte::proc_t cell_searcher; srslte::proc_t si_acquirer; srslte::proc_t serv_cell_cfg; srslte::proc_t cell_selector; diff --git a/srsue/hdr/stack/rrc/rrc_cell.h b/srsue/hdr/stack/rrc/rrc_cell.h index 9f5fcaf7a..b497610a6 100644 --- a/srsue/hdr/stack/rrc/rrc_cell.h +++ b/srsue/hdr/stack/rrc/rrc_cell.h @@ -32,7 +32,7 @@ class cell_t { public: cell_t() { gettimeofday(&last_update, nullptr); } - explicit cell_t(phy_interface_rrc_lte::phy_cell_t phy_cell_) : cell_t() { phy_cell = phy_cell_; } + explicit cell_t(phy_cell_t phy_cell_) : cell_t() { phy_cell = phy_cell_; } // comparison based on pci and earfcn bool is_valid() { return phy_cell.earfcn != 0 && srslte_cellid_isvalid(phy_cell.pci); } @@ -110,7 +110,7 @@ public: bool is_sib_scheduled(uint32_t sib_index) const; - phy_interface_rrc_lte::phy_cell_t phy_cell = {0, 0, 0}; + phy_cell_t phy_cell = {0, 0, 0}; bool has_mcch = false; asn1::rrc::sib_type1_s sib1 = {}; asn1::rrc::sib_type2_s sib2 = {}; @@ -192,7 +192,7 @@ public: cell_t* find_cell(uint32_t earfcn, uint32_t pci); // serving cell handling - int set_serving_cell(phy_interface_rrc_lte::phy_cell_t phy_cell, bool discard_serving); + int set_serving_cell(phy_cell_t phy_cell, bool discard_serving); cell_t& serving_cell() { return *serv_cell; } const cell_t& serving_cell() const { return *serv_cell; } diff --git a/srsue/hdr/stack/rrc/rrc_meas.h b/srsue/hdr/stack/rrc/rrc_meas.h index 391c3c6c5..f3fd2ef5e 100644 --- a/srsue/hdr/stack/rrc/rrc_meas.h +++ b/srsue/hdr/stack/rrc/rrc_meas.h @@ -35,7 +35,7 @@ namespace srsue { using namespace asn1::rrc; -typedef std::vector cell_triggered_t; +typedef std::vector cell_triggered_t; // RRC Measurements class class rrc::rrc_meas diff --git a/srsue/hdr/stack/rrc/rrc_nr.h b/srsue/hdr/stack/rrc/rrc_nr.h index 261aa0d0c..b6ce44616 100644 --- a/srsue/hdr/stack/rrc/rrc_nr.h +++ b/srsue/hdr/stack/rrc/rrc_nr.h @@ -95,8 +95,7 @@ public: void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu) final; // STACK interface - void cell_search_completed(const phy_interface_rrc_lte::cell_search_ret_t& cs_ret, - const phy_interface_rrc_lte::phy_cell_t& found_cell); + void cell_search_completed(const rrc_interface_phy_lte::cell_search_ret_t& cs_ret, const phy_cell_t& found_cell); private: struct cmd_msg_t { diff --git a/srsue/hdr/stack/rrc/rrc_procedures.h b/srsue/hdr/stack/rrc/rrc_procedures.h index 4f523889a..56510bbaa 100644 --- a/srsue/hdr/stack/rrc/rrc_procedures.h +++ b/srsue/hdr/stack/rrc/rrc_procedures.h @@ -47,11 +47,11 @@ public: srslte::proc_outcome_t react(const bool& event); srslte::proc_outcome_t step_wait_measurement(); - phy_interface_rrc_lte::cell_search_ret_t get_result() const { return search_result.cs_ret; } + rrc_interface_phy_lte::cell_search_ret_t get_result() const { return search_result.cs_ret; } static const char* name() { return "Cell Search"; } private: - srslte::proc_outcome_t handle_cell_found(const phy_interface_rrc_lte::phy_cell_t& new_cell); + srslte::proc_outcome_t handle_cell_found(const phy_cell_t& new_cell); // conts rrc* rrc_ptr; @@ -147,7 +147,7 @@ private: search_state_t state; uint32_t neigh_index; bool serv_cell_select_attempted = false; - srslte::proc_future_t cell_search_fut; + srslte::proc_future_t cell_search_fut; srslte::proc_future_t serv_cell_cfg_fut; bool discard_serving = false; }; @@ -169,7 +169,7 @@ private: // state variables found_plmn_t found_plmns[MAX_FOUND_PLMNS]; int nof_plmns = 0; - srslte::proc_future_t cell_search_fut; + srslte::proc_future_t cell_search_fut; }; class rrc::connection_request_proc @@ -306,12 +306,12 @@ private: asn1::rrc::rrc_conn_recfg_r8_ies_s recfg_r8; // state - phy_interface_rrc_lte::phy_cell_t target_cell; + phy_cell_t target_cell; // helper to revert security config of source cell void reset_security_config(); - enum state_t { launch_phy_cell_select, wait_phy_cell_select_complete, wait_ra_completion } state; + enum state_t { wait_phy_cell_select_complete, wait_ra_completion } state; }; } // namespace srsue diff --git a/srsue/hdr/stack/ue_stack_lte.h b/srsue/hdr/stack/ue_stack_lte.h index 9ee034b4b..dd1b77722 100644 --- a/srsue/hdr/stack/ue_stack_lte.h +++ b/srsue/hdr/stack/ue_stack_lte.h @@ -79,6 +79,10 @@ public: void in_sync() final; void out_of_sync() final; void new_cell_meas(const std::vector& meas) override { rrc.new_cell_meas(meas); } + void cell_search_complete(cell_search_ret_t ret, phy_cell_t found_cell) final; + void cell_select_complete(bool status) final; + void set_config_complete(bool status) final; + void set_scell_complete(bool status) final; // MAC Interface for PHY uint16_t get_dl_sched_rnti(uint32_t tti) final { return mac.get_dl_sched_rnti(tti); } @@ -158,7 +162,7 @@ private: static const int STACK_MAIN_THREAD_PRIO = 4; // Next lower priority after PHY workers srslte::block_queue pending_stack_metrics; task_scheduler task_sched; - srslte::task_multiqueue::queue_handle sync_task_queue, ue_task_queue, gw_queue_id; + srslte::task_multiqueue::queue_handle sync_task_queue, ue_task_queue, gw_queue_id, cfg_task_queue; // TTI stats srslte::tprof tti_tprof; diff --git a/srsue/src/phy/cc_worker.cc b/srsue/src/phy/cc_worker.cc index fe0dc5715..a9bcd6140 100644 --- a/srsue/src/phy/cc_worker.cc +++ b/srsue/src/phy/cc_worker.cc @@ -119,13 +119,16 @@ void cc_worker::reset() { // constructor sets defaults srslte::phy_cfg_t empty_cfg; - set_config(empty_cfg); + set_config_unlocked(empty_cfg); } -bool cc_worker::set_cell(srslte_cell_t cell_) +void cc_worker::reset_cell_unlocked() { - std::unique_lock lock(mutex); + cell_initiated = false; +} +bool cc_worker::set_cell_unlocked(srslte_cell_t cell_) +{ if (cell.id != cell_.id || !cell_initiated) { cell = cell_; @@ -175,27 +178,29 @@ void cc_worker::set_tti(uint32_t tti) sf_cfg_ul.shortened = false; } -void cc_worker::set_cfo(float cfo) +void cc_worker::set_cfo_unlocked(float cfo) { - std::unique_lock lock(mutex); ue_ul_cfg.cfo_value = cfo; } -void cc_worker::set_crnti(uint16_t rnti) +float cc_worker::get_ref_cfo() const +{ + return ue_dl.chest_res.cfo; +} + +void cc_worker::set_crnti_unlocked(uint16_t rnti) { - std::unique_lock lock(mutex); srslte_ue_dl_set_rnti(&ue_dl, rnti); srslte_ue_ul_set_rnti(&ue_ul, rnti); } -void cc_worker::set_tdd_config(srslte_tdd_config_t config) +void cc_worker::set_tdd_config_unlocked(srslte_tdd_config_t config) { - std::unique_lock lock(mutex); sf_cfg_dl.tdd_config = config; sf_cfg_ul.tdd_config = config; } -void cc_worker::enable_pregen_signals(bool enabled) +void cc_worker::enable_pregen_signals_unlocked(bool enabled) { pregen_enabled = enabled; } @@ -208,13 +213,17 @@ void cc_worker::enable_pregen_signals(bool enabled) bool cc_worker::work_dl_regular() { - std::unique_lock lock(mutex); bool dl_ack[SRSLTE_MAX_CODEWORDS] = {}; mac_interface_phy_lte::tb_action_dl_t dl_action = {}; bool found_dl_grant = false; + if (!cell_initiated) { + log_h->warning("Trying to access cc_worker=%d while cell not initialized (DL)\n", cc_idx); + return false; + } + sf_cfg_dl.sf_type = SRSLTE_SF_NORM; // Set default channel estimation @@ -266,7 +275,7 @@ bool cc_worker::work_dl_regular() // Generate PHY grant if (srslte_ue_dl_dci_to_pdsch_grant(&ue_dl, &sf_cfg_dl, &ue_dl_cfg, &dci_dl, &ue_dl_cfg.cfg.pdsch.grant)) { Error("Converting DCI message to DL dci\n"); - return -1; + return false; } // Save TB for next retx @@ -285,17 +294,13 @@ bool cc_worker::work_dl_regular() srslte_pdsch_ack_resource_t ack_resource = {dci_dl.dai, dci_dl.location.ncce, grant_cc_idx, dci_dl.tpc_pucch}; // Send grant to MAC and get action for this TB, then call tb_decoded to unlock MAC - mutex.unlock(); phy->stack->new_grant_dl(cc_idx, mac_grant, &dl_action); - mutex.lock(); // Decode PDSCH decode_pdsch(ack_resource, &dl_action, dl_ack); // Informs Stack about the decoding status - mutex.unlock(); phy->stack->tb_decoded(cc_idx, mac_grant, dl_ack); - mutex.lock(); } /* Decode PHICH */ @@ -306,9 +311,13 @@ bool cc_worker::work_dl_regular() bool cc_worker::work_dl_mbsfn(srslte_mbsfn_cfg_t mbsfn_cfg) { - std::unique_lock lock(mutex); mac_interface_phy_lte::tb_action_dl_t dl_action = {}; + if (!cell_initiated) { + log_h->warning("Trying to access cc_worker=%d while cell not initialized (MBSFN)\n", cc_idx); + return false; + } + // Configure MBSFN settings srslte_ue_dl_set_mbsfn_area_id(&ue_dl, mbsfn_cfg.mbsfn_area_id); srslte_ue_dl_set_non_mbsfn_region(&ue_dl, mbsfn_cfg.non_mbsfn_region_length); @@ -569,7 +578,6 @@ void cc_worker::update_measurements(std::vector lock(mutex); bool signal_ready; srslte_dci_ul_t dci_ul = {}; @@ -577,6 +585,11 @@ bool cc_worker::work_ul(srslte_uci_data_t* uci_data) mac_interface_phy_lte::tb_action_ul_t ul_action = {}; uint32_t pid = 0; + if (!cell_initiated) { + log_h->warning("Trying to access cc_worker=%d while cell not initialized (UL)\n", cc_idx); + return false; + } + bool ul_grant_available = phy->get_ul_pending_grant(&sf_cfg_ul, cc_idx, &pid, &dci_ul); ul_mac_grant.phich_available = phy->get_ul_received_ack(&sf_cfg_ul, cc_idx, &ul_mac_grant.hi_value, ul_grant_available ? nullptr : &dci_ul); @@ -618,9 +631,7 @@ bool cc_worker::work_ul(srslte_uci_data_t* uci_data) // Fill MAC dci ul_phy_to_mac_grant(&ue_ul_cfg.ul_cfg.pusch.grant, &dci_ul, pid, ul_grant_available, &ul_mac_grant); - mutex.unlock(); phy->stack->new_grant_ul(cc_idx, ul_mac_grant, &ul_action); - mutex.lock(); // Calculate PUSCH Hopping procedure ue_ul_cfg.ul_cfg.hopping.current_tx_nb = ul_action.current_tx_nb; @@ -810,7 +821,6 @@ uint32_t cc_worker::get_wideband_cqi() void cc_worker::set_uci_periodic_cqi(srslte_uci_data_t* uci_data) { - std::unique_lock lock(mutex); srslte_ue_dl_gen_cqi_periodic(&ue_dl, &ue_dl_cfg, get_wideband_cqi(), CURRENT_TTI_TX, uci_data); } @@ -862,10 +872,8 @@ void cc_worker::set_uci_ack(srslte_uci_data_t* uci_data, /* Translates RRC structs into PHY structs */ -void cc_worker::set_config(srslte::phy_cfg_t& phy_cfg) +void cc_worker::set_config_unlocked(srslte::phy_cfg_t& phy_cfg) { - std::unique_lock lock(mutex); - // Save configuration ue_dl_cfg.cfg = phy_cfg.dl_cfg; ue_ul_cfg.ul_cfg = phy_cfg.ul_cfg; @@ -880,9 +888,8 @@ void cc_worker::set_config(srslte::phy_cfg_t& phy_cfg) } } -void cc_worker::upd_config_dci(srslte_dci_cfg_t& dci_cfg) +void cc_worker::upd_config_dci_unlocked(srslte_dci_cfg_t& dci_cfg) { - std::unique_lock lock(mutex); ue_dl_cfg.cfg.dci = dci_cfg; } diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index e7eea09bf..b3c790077 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -225,6 +225,8 @@ bool phy::is_initiated() void phy::stop() { std::unique_lock lock(config_mutex); + cmd_worker.stop(); + cmd_worker_cell.stop(); if (is_configured) { sfsync.stop(); workers_pool.stop(); @@ -284,12 +286,10 @@ void phy::set_activation_deactivation_scell(uint32_t cmd) void phy::configure_prach_params() { Debug("Configuring PRACH parameters\n"); - srslte_cell_t cell; - sfsync.get_current_cell(&cell); prach_cfg.tdd_config = tdd_config; - if (!prach_buffer.set_cell(cell, prach_cfg)) { + if (!prach_buffer.set_cell(selected_cell, prach_cfg)) { Error("Configuring PRACH parameters\n"); } } @@ -304,16 +304,49 @@ void phy::meas_stop() sfsync.meas_stop(); } -bool phy::cell_select(const phy_cell_t* cell) +// This function executes one part of the procedure immediatly and returns to continue in the background. +// When it returns, the caller thread can expect the PHY to have switched to IDLE and have stopped all DL/UL/PRACH +// processing. +bool phy::cell_select(phy_cell_t cell) { sfsync.scell_sync_stop(); - return sfsync.cell_select(cell); + if (sfsync.cell_select_init(cell)) { + reset(); + // Update PCI before starting the background command to make sure PRACH gets the updated value + selected_cell.id = cell.pci; + cmd_worker_cell.add_cmd([this, cell]() { + bool ret = sfsync.cell_select_start(cell); + if (ret) { + srslte_cell_t sync_cell; + sfsync.get_current_cell(&sync_cell); + selected_cell = sync_cell; + } + stack->cell_select_complete(ret); + }); + return true; + } else { + log_h->warning("Could not start Cell Selection procedure\n"); + return false; + } } -phy_interface_rrc_lte::cell_search_ret_t phy::cell_search(phy_cell_t* cell) +// This function executes one part of the procedure immediatly and returns to continue in the background. +// When it returns, the caller thread can expect the PHY to have switched to IDLE and have stopped all DL/UL/PRACH +// processing. +bool phy::cell_search() { sfsync.scell_sync_stop(); - return sfsync.cell_search(cell); + if (sfsync.cell_search_init()) { + reset(); + cmd_worker_cell.add_cmd([this]() { + phy_cell_t found_cell = {}; + rrc_interface_phy_lte::cell_search_ret_t ret = sfsync.cell_search_start(&found_cell); + stack->cell_search_complete(ret, found_cell); + }); + } else { + log_h->warning("Could not start Cell Search procedure\n"); + } + return true; } bool phy::cell_is_camping() @@ -360,11 +393,8 @@ void phy::radio_failure() void phy::reset() { - Info("Resetting PHY\n"); + Info("Resetting PHY...\n"); common.ta.set_base_sec(0); - for (uint32_t i = 0; i < nof_workers; i++) { - workers[i]->reset(); - } common.reset(); } @@ -392,14 +422,19 @@ void phy::set_rar_grant(uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN], uint16_t rn void phy::set_crnti(uint16_t rnti) { - // set_crnti() is an operation that takes time, apply asynrhonously with processing - for (uint32_t i = 0; i < nof_workers; i++) { - sf_worker* w = (sf_worker*)workers_pool.wait_worker_id(i); - if (w) { - w->set_crnti(rnti); - w->release(); + // set_crnti() is an operation that takes time, run in background worker + cmd_worker.add_cmd([this, rnti]() { + log_h->info("Configuring sequences for C-RNTI=0x%x...\n", rnti); + for (uint32_t i = 0; i < nof_workers; i++) { + // set_crnti is not protected so run when worker is finished + sf_worker* w = (sf_worker*)workers_pool.wait_worker_id(i); + if (w) { + w->set_crnti_unlocked(rnti); + w->release(); + } } - } + log_h->info("Finished configuring sequences for C-RNTI=0x%x.\n", rnti); + }); } // Start GUI @@ -411,69 +446,124 @@ void phy::start_plot() void phy::enable_pregen_signals(bool enable) { for (uint32_t i = 0; i < nof_workers; i++) { - workers[i]->enable_pregen_signals(enable); + workers[i]->enable_pregen_signals_unlocked(enable); } } -void phy::set_config(srslte::phy_cfg_t& config_, uint32_t cc_idx, uint32_t earfcn, srslte_cell_t* cell_info) +bool phy::set_config(srslte::phy_cfg_t config_, uint32_t cc_idx) { if (!is_initiated()) { fprintf(stderr, "Error calling set_config(): PHY not initialized\n"); - return; + return false; } - // Disable cell_info if configuration has not been set - if (cell_info) { - if (!srslte_cell_isvalid(cell_info)) { - cell_info = nullptr; - } + // Check parameters are valid + if (cc_idx >= args.nof_carriers) { + log_h->console("Received SCell configuration for index %d but there are not enough CC workers available\n", cc_idx); + return false; } - // Component carrier index zero should be reserved for PCell - if (cc_idx < args.nof_carriers) { - // Send configuration to workers + Info("Setting configuration\n"); + + bool reconfigure_prach = !cc_idx && (prach_cfg != config_.prach_cfg); + + if (reconfigure_prach) { + prach_buffer.reset_cfg(); + } + + // Apply configuration after the worker is finished to avoid race conditions + cmd_worker.add_cmd([this, config_, cc_idx, reconfigure_prach]() { + log_h->info("Setting new PHY configuration...\n"); for (uint32_t i = 0; i < nof_workers; i++) { - if (cell_info) { - // set_cell() is an operation that takes time, apply asynrhonously with processing - sf_worker* w = (sf_worker*)workers_pool.wait_worker_id(i); - if (w) { - w->set_cell(cc_idx, *cell_info); - w->release(); - } + // set_cell is not protected so run when worker is finished + sf_worker* w = (sf_worker*)workers_pool.wait_worker_id(i); + if (w) { + w->set_config_unlocked(cc_idx, config_); + w->release(); } - // set_config() is just a memcpy - workers[i]->set_config(cc_idx, config_); } + log_h->info("Finished setting new PHY configuration.\n"); + if (reconfigure_prach) { + // Reconfigure PRACH parameters only if configuration is different + prach_cfg = config_.prach_cfg; + log_h->info("Setting new PRACH configuration...\n"); + configure_prach_params(); + log_h->info("Finished setting new PRACH configuration.\n"); + } + stack->set_config_complete(true); + }); + return true; +} + +bool phy::set_scell(srslte_cell_t cell_info, uint32_t cc_idx, uint32_t earfcn) +{ + if (!is_initiated()) { + fprintf(stderr, "Error calling set_config(): PHY not initialized\n"); + return false; + } - if (cell_info) { - // Set inter-frequency measurement - sfsync.set_inter_frequency_measurement(cc_idx, earfcn, *cell_info); + if (cc_idx == 0) { + log_h->error("Received SCell configuration for invalid cc_idx=0\n"); + return false; + } - // Set secondary serving cell synchronization - sfsync.scell_sync_set(cc_idx, *cell_info); - } + // Check parameters are valid + if (cc_idx >= args.nof_carriers) { + log_h->console("Received SCell configuration for index %d but there are not enough CC workers available\n", cc_idx); + return false; + } - if (cc_idx == 0) { - prach_cfg = config_.prach_cfg; - } else if (cell_info != nullptr) { - // Change frequency only if the earfcn was modified - if (common.scell_cfg[cc_idx].earfcn != earfcn) { - double dl_freq = srslte_band_fd(earfcn) * 1e6; - double ul_freq = srslte_band_fu(common.get_ul_earfcn(earfcn)) * 1e6; - radio->set_rx_freq(cc_idx, dl_freq); - radio->set_tx_freq(cc_idx, ul_freq); + // First of all check validity of parameters + if (!srslte_cell_isvalid(&cell_info)) { + log_h->error("Received SCell configuration for an invalid cell\n"); + return false; + } + + bool earfcn_is_different = common.scell_cfg[cc_idx].earfcn != earfcn; + + // Set inter-frequency measurement + sfsync.set_inter_frequency_measurement(cc_idx, earfcn, cell_info); + + // Store SCell earfcn and pci + common.scell_cfg[cc_idx].earfcn = earfcn; + common.scell_cfg[cc_idx].pci = cell_info.id; + common.scell_cfg[cc_idx].configured = true; + common.scell_cfg[cc_idx].enabled = false; + + // Reset cell configuration + for (uint32_t i = 0; i < nof_workers; i++) { + workers[i]->reset_cell_unlocked(cc_idx); + } + + // Component carrier index zero should be reserved for PCell + // Send configuration to workers + cmd_worker.add_cmd([this, cell_info, cc_idx, earfcn, earfcn_is_different]() { + log_h->info("Setting new SCell configuration cc_idx=%d, earfcn=%d...\n", cc_idx, earfcn); + for (uint32_t i = 0; i < nof_workers; i++) { + // set_cell is not protected so run when worker is finished + sf_worker* w = (sf_worker*)workers_pool.wait_worker_id(i); + if (w) { + w->set_cell_unlocked(cc_idx, cell_info); + w->release(); } + } - // Store SCell earfcn and pci - common.scell_cfg[cc_idx].earfcn = earfcn; - common.scell_cfg[cc_idx].pci = cell_info->id; - common.scell_cfg[cc_idx].configured = true; - common.scell_cfg[cc_idx].enabled = false; + // Change frequency only if the earfcn was modified + if (earfcn_is_different) { + double dl_freq = srslte_band_fd(earfcn) * 1e6; + double ul_freq = srslte_band_fu(common.get_ul_earfcn(earfcn)) * 1e6; + radio->set_rx_freq(cc_idx, dl_freq); + radio->set_tx_freq(cc_idx, ul_freq); } - } else { - log_h->console("Received SCell configuration for index %d but there are not enough CC workers available\n", cc_idx); - } + // Set secondary serving cell synchronization + sfsync.scell_sync_set(cc_idx, cell_info); + + log_h->info("Finished setting new SCell configuration cc_idx=%d, earfcn=%d\n", cc_idx, earfcn); + + stack->set_scell_complete(true); + }); + return true; } void phy::set_config_tdd(srslte_tdd_config_t& tdd_config_) @@ -485,9 +575,17 @@ void phy::set_config_tdd(srslte_tdd_config_t& tdd_config_) } tdd_config.configured = true; - for (uint32_t i = 0; i < nof_workers; i++) { - workers[i]->set_tdd_config(tdd_config); - } + // Apply config when worker is finished + cmd_worker.add_cmd([this]() { + for (uint32_t i = 0; i < nof_workers; i++) { + // set_tdd_config is not protected so run when worker is finished + sf_worker* w = (sf_worker*)workers_pool.wait_worker_id(i); + if (w) { + w->set_tdd_config_unlocked(tdd_config); + w->release(); + } + } + }); } void phy::set_config_mbsfn_sib2(srslte::mbsfn_sf_cfg_t* cfg_list, uint32_t nof_cfgs) diff --git a/srsue/src/phy/phy_common.cc b/srsue/src/phy/phy_common.cc index 0b75d77c6..649a8c105 100644 --- a/srsue/src/phy/phy_common.cc +++ b/srsue/src/phy/phy_common.cc @@ -878,19 +878,28 @@ void phy_common::reset() ZERO_OBJECT(scell_cfg); // Note: Using memset to reset these members is forbidden because they are real objects, not plain arrays. - for (auto& i : pending_dl_ack) { - i = {}; + { + std::lock_guard lock(pending_dl_ack_mutex); + for (auto& i : pending_dl_ack) { + i = {}; + } } for (auto& i : pending_dl_dai) { i = {}; } - for (auto& i : pending_ul_ack) { - for (auto& j : i) { - j = {}; + { + std::lock_guard lock(pending_ul_ack_mutex); + for (auto& i : pending_ul_ack) { + for (auto& j : i) { + j = {}; + } } } - for (auto& i : pending_ul_grant) { - i = {}; + { + std::lock_guard lock(pending_ul_grant_mutex); + for (auto& i : pending_ul_grant) { + i = {}; + } } // Release mapping of secondary cells diff --git a/srsue/src/phy/prach.cc b/srsue/src/phy/prach.cc index e7671b82a..bf8966364 100644 --- a/srsue/src/phy/prach.cc +++ b/srsue/src/phy/prach.cc @@ -92,6 +92,11 @@ void prach::stop() mem_initiated = false; } +void prach::reset_cfg() +{ + cell_initiated = false; +} + bool prach::set_cell(srslte_cell_t cell_, srslte_prach_cfg_t prach_cfg) { if (!mem_initiated) { @@ -106,7 +111,7 @@ bool prach::set_cell(srslte_cell_t cell_, srslte_prach_cfg_t prach_cfg) cell = cell_; cfg = prach_cfg; - preamble_idx = -1; + // We must not reset preamble_idx here, MAC might have already called prepare_to_send() if (6 + prach_cfg.freq_offset > cell.nof_prb) { log_h->console("Error no space for PRACH: frequency offset=%d, N_rb_ul=%d\n", prach_cfg.freq_offset, cell.nof_prb); @@ -156,21 +161,17 @@ bool prach::generate_buffer(uint32_t f_idx) bool prach::prepare_to_send(uint32_t preamble_idx_, int allowed_subframe_, float target_power_dbm_) { - if (cell_initiated && preamble_idx_ < max_preambles) { - preamble_idx = preamble_idx_; - target_power_dbm = target_power_dbm_; - allowed_subframe = allowed_subframe_; - transmitted_tti = -1; - Debug("PRACH: prepare to send preamble %d\n", preamble_idx); - return true; - } - - if (!cell_initiated) { - Error("PRACH: Cell not configured\n"); - } else { + if (preamble_idx_ >= max_preambles) { Error("PRACH: Invalid preamble %d\n", preamble_idx_); + return false; } - return false; + + preamble_idx = preamble_idx_; + target_power_dbm = target_power_dbm_; + allowed_subframe = allowed_subframe_; + transmitted_tti = -1; + Debug("PRACH: prepare to send preamble %d\n", preamble_idx); + return true; } bool prach::is_pending() const @@ -178,9 +179,10 @@ bool prach::is_pending() const return cell_initiated && preamble_idx >= 0 && unsigned(preamble_idx) < max_preambles; } -bool prach::is_ready_to_send(uint32_t current_tti_) +bool prach::is_ready_to_send(uint32_t current_tti_, uint32_t current_pci) { - if (is_pending()) { + // Make sure the curernt PCI is the one we configured the PRACH for + if (is_pending() && current_pci == cell.id) { // consider the number of subframes the transmission must be anticipated uint32_t tti_tx = TTI_TX(current_tti_); if (srslte_prach_tti_opportunity(&prach_obj, tti_tx, allowed_subframe)) { diff --git a/srsue/src/phy/sf_worker.cc b/srsue/src/phy/sf_worker.cc index 7c473838a..9a2b23228 100644 --- a/srsue/src/phy/sf_worker.cc +++ b/srsue/src/phy/sf_worker.cc @@ -74,19 +74,15 @@ sf_worker::~sf_worker() } } -void sf_worker::reset() +void sf_worker::reset_cell_unlocked(uint32_t cc_idx) { - for (auto& cc_worker : cc_workers) { - cc_worker->reset(); - } + cc_workers[cc_idx]->reset_cell_unlocked(); } -bool sf_worker::set_cell(uint32_t cc_idx, srslte_cell_t cell_) +bool sf_worker::set_cell_unlocked(uint32_t cc_idx, srslte_cell_t cell_) { - std::lock_guard lock(cell_mutex); - if (cc_idx < cc_workers.size()) { - if (!cc_workers[cc_idx]->set_cell(cell_)) { + if (!cc_workers[cc_idx]->set_cell_unlocked(cell_)) { Error("Setting cell for cc=%d\n", cc_idx); return false; } @@ -95,6 +91,7 @@ bool sf_worker::set_cell(uint32_t cc_idx, srslte_cell_t cell_) } if (cc_idx == 0) { + std::lock_guard lock(cell_mutex); cell = cell_; cell_initiated = true; cell_init_cond.notify_one(); @@ -142,41 +139,40 @@ void sf_worker::set_prach(cf_t* prach_ptr_, float prach_power_) prach_power = prach_power_; } -void sf_worker::set_cfo(const uint32_t& cc_idx, float cfo) +void sf_worker::set_cfo_unlocked(const uint32_t& cc_idx, float cfo) { - cc_workers[cc_idx]->set_cfo(cfo); + cc_workers[cc_idx]->set_cfo_unlocked(cfo); } -void sf_worker::set_crnti(uint16_t rnti) +void sf_worker::set_crnti_unlocked(uint16_t rnti) { for (auto& cc_worker : cc_workers) { - cc_worker->set_crnti(rnti); + cc_worker->set_crnti_unlocked(rnti); } } -void sf_worker::set_tdd_config(srslte_tdd_config_t config) +void sf_worker::set_tdd_config_unlocked(srslte_tdd_config_t config) { for (auto& cc_worker : cc_workers) { - cc_worker->set_tdd_config(config); + cc_worker->set_tdd_config_unlocked(config); } tdd_config = config; } -void sf_worker::enable_pregen_signals(bool enabled) +void sf_worker::enable_pregen_signals_unlocked(bool enabled) { for (auto& cc_worker : cc_workers) { - cc_worker->enable_pregen_signals(enabled); + cc_worker->enable_pregen_signals_unlocked(enabled); } } -void sf_worker::set_config(uint32_t cc_idx, srslte::phy_cfg_t& phy_cfg) +void sf_worker::set_config_unlocked(uint32_t cc_idx, srslte::phy_cfg_t phy_cfg) { if (cc_idx < cc_workers.size()) { - Info("Setting configuration for worker=%d, cc=%d\n", get_id(), cc_idx); - cc_workers[cc_idx]->set_config(phy_cfg); + cc_workers[cc_idx]->set_config_unlocked(phy_cfg); if (cc_idx > 0) { // Update DCI config for PCell - cc_workers[0]->upd_config_dci(phy_cfg.dl_cfg.dci); + cc_workers[0]->upd_config_dci_unlocked(phy_cfg.dl_cfg.dci); } } else { Error("Setting config for cc=%d; Invalid cc_idx\n", cc_idx); @@ -209,7 +205,7 @@ void sf_worker::work_imp() if (carrier_idx == 0 && phy->is_mbsfn_sf(&mbsfn_cfg, tti)) { cc_workers[0]->work_dl_mbsfn(mbsfn_cfg); // Don't do chest_ok in mbsfn since it trigger measurements } else { - if ((carrier_idx == 0) || phy->scell_cfg[carrier_idx].enabled) { + if ((carrier_idx == 0) || (phy->scell_cfg[carrier_idx].enabled && phy->scell_cfg[carrier_idx].configured)) { rx_signal_ok = cc_workers[carrier_idx]->work_dl_regular(); } } @@ -241,10 +237,12 @@ void sf_worker::work_imp() // Loop through all carriers for (uint32_t carrier_idx = 0; carrier_idx < phy->args->nof_carriers; carrier_idx++) { - tx_signal_ready |= cc_workers[carrier_idx]->work_ul(uci_cc_idx == carrier_idx ? &uci_data : nullptr); + if ((carrier_idx == 0) || (phy->scell_cfg[carrier_idx].enabled && phy->scell_cfg[carrier_idx].configured)) { + tx_signal_ready |= cc_workers[carrier_idx]->work_ul(uci_cc_idx == carrier_idx ? &uci_data : nullptr); - // Set signal pointer based on offset - tx_signal_ptr.set(carrier_idx, 0, phy->args->nof_rx_ant, cc_workers[carrier_idx]->get_tx_buffer(0)); + // Set signal pointer based on offset + tx_signal_ptr.set(carrier_idx, 0, phy->args->nof_rx_ant, cc_workers[carrier_idx]->get_tx_buffer(0)); + } } } } @@ -283,20 +281,18 @@ void sf_worker::reset_uci(srslte_uci_data_t* uci_data) void sf_worker::update_measurements() { - // Run measurements in all carriers, but only in one worker - if (get_id() == 0) { - std::vector serving_cells = {}; - for (uint32_t cc_idx = 0; cc_idx < cc_workers.size(); cc_idx++) { - cf_t* rssi_power_buffer = nullptr; - if (cc_idx == 0) { - rssi_power_buffer = cc_workers[0]->get_rx_buffer(0); - } - cc_workers[cc_idx]->update_measurements(serving_cells, rssi_power_buffer); - } - // Send report to stack - if (not serving_cells.empty()) { - phy->stack->new_cell_meas(serving_cells); + std::vector serving_cells = {}; + for (uint32_t cc_idx = 0; cc_idx < cc_workers.size(); cc_idx++) { + cf_t* rssi_power_buffer = nullptr; + // Setting rssi_power_buffer to nullptr disables RSSI update. Do it only by worker 0 + if (cc_idx == 0 && get_id() == 0) { + rssi_power_buffer = cc_workers[0]->get_rx_buffer(0); } + cc_workers[cc_idx]->update_measurements(serving_cells, rssi_power_buffer); + } + // Send report to stack + if (not serving_cells.empty()) { + phy->stack->new_cell_meas(serving_cells); } } diff --git a/srsue/src/phy/sync.cc b/srsue/src/phy/sync.cc index 40aeca48b..8486e4298 100644 --- a/srsue/src/phy/sync.cc +++ b/srsue/src/phy/sync.cc @@ -181,15 +181,18 @@ void sync::reset() * returns 1 and stores cell information and RSRP values in the pointers (if provided). If a cell is not found in the * current frequency it moves to the next one and the next call to cell_search() will look in the next EARFCN in the * set. If no cells are found in any frequency it returns 0. If error returns -1. + * + * The first part of the procedure (call to _init()) moves the PHY To IDLE, ensuring that no UL/DL/PRACH will happen + * */ - -phy_interface_rrc_lte::cell_search_ret_t sync::cell_search(phy_interface_rrc_lte::phy_cell_t* found_cell) +bool sync::cell_search_init() { std::unique_lock ul(rrc_mutex); - phy_interface_rrc_lte::cell_search_ret_t ret = {}; - ret.found = phy_interface_rrc_lte::cell_search_ret_t::ERROR; - ret.last_freq = phy_interface_rrc_lte::cell_search_ret_t::NO_MORE_FREQS; + if (rrc_proc_state != PROC_IDLE) { + Error("Cell Search: Can't start procedure. SYNC already running a procedure (%d)\n", (uint32_t)rrc_proc_state); + return false; + } // Move state to IDLE Info("Cell Search: Start EARFCN index=%u/%zd\n", cellsearch_earfcn_index, worker_com->args->dl_earfcn_list.size()); @@ -199,6 +202,26 @@ phy_interface_rrc_lte::cell_search_ret_t sync::cell_search(phy_interface_rrc_lte // Stop all intra-frequency measurement before changing frequency meas_stop(); + rrc_proc_state = PROC_SEARCH_START; + + return true; +} + +rrc_interface_phy_lte::cell_search_ret_t sync::cell_search_start(phy_cell_t* found_cell) +{ + std::unique_lock ul(rrc_mutex); + + rrc_interface_phy_lte::cell_search_ret_t ret = {}; + ret.found = rrc_interface_phy_lte::cell_search_ret_t::ERROR; + ret.last_freq = rrc_interface_phy_lte::cell_search_ret_t::NO_MORE_FREQS; + + if (rrc_proc_state != PROC_SEARCH_START) { + Error("Cell Search: Can't run procedure. Must call cell_search_init() first (%d)\n", (uint32_t)rrc_proc_state); + return ret; + } + + rrc_proc_state = PROC_SEARCH_RUNNING; + if (srate_mode != SRATE_FIND) { srate_mode = SRATE_FIND; radio_h->set_rx_srate(1.92e6); @@ -230,11 +253,11 @@ phy_interface_rrc_lte::cell_search_ret_t sync::cell_search(phy_interface_rrc_lte found_cell->pci = cell.id; found_cell->cfo_hz = search_p.get_last_cfo(); } - ret.found = phy_interface_rrc_lte::cell_search_ret_t::CELL_FOUND; + ret.found = rrc_interface_phy_lte::cell_search_ret_t::CELL_FOUND; break; case search::CELL_NOT_FOUND: Info("Cell Search: No cell found in this frequency\n"); - ret.found = phy_interface_rrc_lte::cell_search_ret_t::CELL_NOT_FOUND; + ret.found = rrc_interface_phy_lte::cell_search_ret_t::CELL_NOT_FOUND; break; default: Error("Cell Search: while receiving samples\n"); @@ -246,76 +269,90 @@ phy_interface_rrc_lte::cell_search_ret_t sync::cell_search(phy_interface_rrc_lte if (cellsearch_earfcn_index >= worker_com->args->dl_earfcn_list.size()) { Info("Cell Search: No more frequencies in the current EARFCN set\n"); cellsearch_earfcn_index = 0; - ret.last_freq = phy_interface_rrc_lte::cell_search_ret_t::NO_MORE_FREQS; + ret.last_freq = rrc_interface_phy_lte::cell_search_ret_t::NO_MORE_FREQS; } else { - ret.last_freq = phy_interface_rrc_lte::cell_search_ret_t::MORE_FREQS; + ret.last_freq = rrc_interface_phy_lte::cell_search_ret_t::MORE_FREQS; } + rrc_proc_state = PROC_IDLE; + return ret; } /* Cell select synchronizes to a new cell (e.g. during HO or during cell reselection on IDLE) or * re-synchronizes with the current cell if cell argument is NULL + * The first phase of the procedure verifies the validity of the input parameters and switches the + * PHY to IDLE. Once this function returns, the PHY will not process any DL/UL nor will PRACH + * + * See cell_select_start() */ -bool sync::cell_select(const phy_interface_rrc_lte::phy_cell_t* new_cell) +bool sync::cell_select_init(phy_cell_t new_cell) { std::unique_lock ul(rrc_mutex); - bool ret = false; - int cnt = 0; - - // Move state to IDLE - if (new_cell == nullptr) { - Info("Cell Select: Starting cell resynchronization\n"); - } else { - if (!srslte_cellid_isvalid(new_cell->pci)) { - log_h->error("Cell Select: Invalid cell_id=%d\n", new_cell->pci); - return ret; - } - Info("Cell Select: Starting cell selection for PCI=%d, EARFCN=%d\n", new_cell->pci, new_cell->earfcn); + if (rrc_proc_state != PROC_IDLE) { + Error("Cell Select: Can't start procedure. SYNC already running a procedure (%d)\n", (uint32_t)rrc_proc_state); + return false; } - // Wait for any pending PHICH - while (worker_com->is_any_ul_pending_ack() && cnt < 10) { - usleep(1000); - cnt++; - Info("Cell Select: waiting pending PHICH (cnt=%d)\n", cnt); + // Move state to IDLE + if (!srslte_cellid_isvalid(new_cell.pci)) { + Error("Cell Select: Invalid cell_id=%d\n", new_cell.pci); + return false; } Info("Cell Select: Going to IDLE\n"); phy_state.go_idle(); - worker_com->reset(); + + // Stop intra-frequency measurements if need to change frequency + if ((int)new_cell.earfcn != current_earfcn) { + meas_stop(); + } + + rrc_proc_state = PROC_SELECT_START; + + return true; +} + +bool sync::cell_select_start(phy_cell_t new_cell) +{ + std::unique_lock ul(rrc_mutex); + + if (rrc_proc_state != PROC_SELECT_START) { + Error("Cell Select: Can't run procedure. Must call cell_select_init() first (%d)\n", (uint32_t)rrc_proc_state); + return false; + } + + rrc_proc_state = PROC_SELECT_RUNNING; + + bool ret = false; + sfn_p.reset(); search_p.reset(); srslte_ue_sync_reset(&ue_sync); /* Reconfigure cell if necessary */ - if (new_cell != nullptr) { - cell.id = new_cell->pci; - if (not set_cell(new_cell->cfo_hz)) { - Error("Cell Select: Reconfiguring cell\n"); - return ret; - } - - /* Select new frequency if necessary */ - if ((int)new_cell->earfcn != current_earfcn) { - current_earfcn = new_cell->earfcn; + cell.id = new_cell.pci; + if (not set_cell(new_cell.cfo_hz)) { + Error("Cell Select: Reconfiguring cell\n"); + return false; + } - // Stop all intra-frequency measurement before changing frequency - meas_stop(); + /* Select new frequency if necessary */ + if ((int)new_cell.earfcn != current_earfcn) { + current_earfcn = new_cell.earfcn; - Info("Cell Select: Setting new frequency EARFCN=%d\n", new_cell->earfcn); - if (!set_frequency()) { - Error("Cell Select: Setting new frequency EARFCN=%d\n", new_cell->earfcn); - return ret; - } + Info("Cell Select: Setting new frequency EARFCN=%d\n", new_cell.earfcn); + if (!set_frequency()) { + Error("Cell Select: Setting new frequency EARFCN=%d\n", new_cell.earfcn); + return false; } - - // Reconfigure first intra-frequency measurement - intra_freq_meas[0]->set_primary_cell(current_earfcn, cell); } + // Reconfigure first intra-frequency measurement + intra_freq_meas[0]->set_primary_cell(current_earfcn, cell); + // Change sampling rate if necessary if (srate_mode != SRATE_CAMP) { log_h->info("Cell Select: Setting CAMPING sampling rate\n"); @@ -332,6 +369,8 @@ bool sync::cell_select(const phy_interface_rrc_lte::phy_cell_t* new_cell) Info("Cell Select: Could not synchronize SFN\n"); } + rrc_proc_state = PROC_IDLE; + return ret; } @@ -433,7 +472,7 @@ void sync::run_camping_in_sync_state(sf_worker* worker, srslte::rf_buffer_t& syn } // Check if we need to TX a PRACH - if (prach_buffer->is_ready_to_send(tti)) { + if (prach_buffer->is_ready_to_send(tti, cell.id)) { prach_ptr = prach_buffer->generate(get_tx_cfo(), &prach_nof_sf, &prach_power); if (prach_ptr == nullptr) { Error("Generating PRACH\n"); @@ -444,7 +483,7 @@ void sync::run_camping_in_sync_state(sf_worker* worker, srslte::rf_buffer_t& syn // Set CFO for all Carriers for (uint32_t cc = 0; cc < worker_com->args->nof_carriers; cc++) { - worker->set_cfo(cc, get_tx_cfo()); + worker->set_cfo_unlocked(cc, get_tx_cfo()); worker_com->update_cfo_measurement(cc, srslte_ue_sync_get_cfo(&ue_sync)); } @@ -508,6 +547,7 @@ void sync::run_camping_state() } // Run stack + Debug("run_stack_tti: from main\n"); run_stack_tti(); } @@ -712,8 +752,15 @@ void sync::set_ue_sync_opts(srslte_ue_sync_t* q, float cfo) bool sync::set_cell(float cfo) { + // Wait the SYNC thread to transition to IDLE + uint32_t cnt = 0; + while (!phy_state.is_idle() && cnt <= 20) { + Info("SYNC: PHY state is_idle=%d, cnt=%d\n", phy_state.is_idle(), cnt); + usleep(500); + cnt++; + } if (!phy_state.is_idle()) { - Warning("Can not change Cell while not in IDLE\n"); + Error("Can not change Cell while not in IDLE\n"); return false; } @@ -730,11 +777,16 @@ bool sync::set_cell(float cfo) sfn_p.set_cell(cell); worker_com->set_cell(cell); + // Reset cell configuration + for (uint32_t i = 0; i < nof_workers; i++) { + ((sf_worker*)workers_pool->get_worker(i))->reset_cell_unlocked(0); + } + bool success = true; for (uint32_t i = 0; i < workers_pool->get_nof_workers(); i++) { sf_worker* w = (sf_worker*)workers_pool->wait_worker_id(i); if (w) { - success &= w->set_cell(0, cell); + success &= w->set_cell_unlocked(0, cell); w->release(); } } @@ -855,6 +907,7 @@ int sync::radio_recv_fnc(srslte::rf_buffer_t& data, srslte_timestamp_t* rx_time) // Run stack if the sync state is not in camping if (not phy_state.is_camping()) { + Debug("run_stack_tti: from recv\n"); run_stack_tti(); } @@ -910,7 +963,9 @@ void sync::run_stack_tti() } // Run stack + Debug("run_stack_tti: calling stack\n"); stack->run_tti(tti, tti_jump); + Debug("run_stack_tti: stack called\n"); } // update timestamp diff --git a/srsue/src/stack/mac/dl_harq.cc b/srsue/src/stack/mac/dl_harq.cc index 7d489d3d2..2f3a40cd1 100644 --- a/srsue/src/stack/mac/dl_harq.cc +++ b/srsue/src/stack/mac/dl_harq.cc @@ -225,10 +225,6 @@ void dl_harq_entity::dl_harq_process::dl_tb_process::reset(bool lock) payload_buffer_ptr = NULL; } - if (is_initiated && lock) { - srslte_softbuffer_rx_reset(&softbuffer); - } - if (lock) { mutex.unlock(); } diff --git a/srsue/src/stack/mac/mac.cc b/srsue/src/stack/mac/mac.cc index a09c338a9..7832bce0f 100644 --- a/srsue/src/stack/mac/mac.cc +++ b/srsue/src/stack/mac/mac.cc @@ -152,16 +152,6 @@ void mac::reconfiguration(const uint32_t& cc_idx, const bool& enable) } } -void mac::wait_uplink() -{ - int cnt = 0; - Info("Waiting to uplink...\n"); - while (mux_unit.is_pending_any_sdu() && cnt < 20) { - usleep(1000); - cnt++; - } -} - // Implement Section 5.9 void mac::reset() { @@ -601,14 +591,9 @@ void mac::set_contention_id(uint64_t uecri) uernti.contention_id = uecri; } -void mac::start_noncont_ho(uint32_t preamble_index, uint32_t prach_mask) -{ - ra_procedure.start_noncont(preamble_index, prach_mask); -} - -void mac::start_cont_ho() +void mac::set_rach_ded_cfg(uint32_t preamble_index, uint32_t prach_mask) { - ra_procedure.start_mac_order(56, true); + ra_procedure.set_config_ded(preamble_index, prach_mask); } void mac::set_mbsfn_config(uint32_t nof_mbsfn_services) @@ -619,6 +604,7 @@ void mac::set_mbsfn_config(uint32_t nof_mbsfn_services) void mac::set_config(mac_cfg_t& mac_cfg) { + Info("Setting configuration\n"); // Set configuration for each module in MAC bsr_procedure.set_config(mac_cfg.bsr_cfg); phr_procedure.set_config(mac_cfg.phr_cfg); diff --git a/srsue/src/stack/mac/proc_ra.cc b/srsue/src/stack/mac/proc_ra.cc index 42fe0db24..628563b7a 100644 --- a/srsue/src/stack/mac/proc_ra.cc +++ b/srsue/src/stack/mac/proc_ra.cc @@ -31,7 +31,6 @@ namespace srsue { const char* state_str[] = {"RA: INIT: ", - "RA: INIT: ", "RA: PDCCH: ", "RA: Rx: ", "RA: Backoff: ", @@ -97,6 +96,14 @@ void ra_proc::set_config(srslte::rach_cfg_t& rach_cfg_) new_cfg = rach_cfg_; } +void ra_proc::set_config_ded(uint32_t preamble_index, uint32_t prach_mask) +{ + std::unique_lock ul(mutex); + next_preamble_idx = preamble_index; + next_prach_mask = prach_mask; + noncontention_enabled = true; +} + /* Reads the configuration and configures internal variables */ void ra_proc::read_params() { @@ -148,7 +155,6 @@ void ra_proc::step(uint32_t tti_) case START_WAIT_COMPLETION: state_completition(); break; - case WAITING_PHY_CONFIG: case WAITING_COMPLETION: // do nothing, bc we are waiting for the phy to finish break; @@ -232,28 +238,11 @@ void ra_proc::state_completition() state = WAITING_COMPLETION; uint16_t rnti = rntis->crnti; uint32_t task_id = current_task_id; - task_sched->enqueue_background_task([this, rnti, task_id](uint32_t worker_id) { - phy_h->set_crnti(rnti); - // signal MAC RA proc to go back to idle - notify_ra_completed(task_id); - }); -} -void ra_proc::notify_phy_config_completed(uint32_t task_id) -{ - if (current_task_id == task_id) { - if (state != WAITING_PHY_CONFIG) { - rError("Received unexpected notification of PHY configuration completed\n"); - } else { - rDebug("RA waiting PHY configuration completed\n"); - } - // Jump directly to Resource selection - resource_selection(); - } else { - rError("Received old notification of PHY configuration (old task_id=%d, current_task_id=%d)\n", - task_id, - current_task_id); - } + phy_h->set_crnti(rnti); + + // signal MAC RA proc to go back to idle + notify_ra_completed(task_id); } void ra_proc::notify_ra_completed(uint32_t task_id) @@ -281,15 +270,7 @@ void ra_proc::initialization() preambleTransmissionCounter = 1; mux_unit->msg3_flush(); backoff_param_ms = 0; - - // Instruct phy to configure PRACH - state = WAITING_PHY_CONFIG; - uint32_t task_id = current_task_id; - task_sched->enqueue_background_task([this, task_id](uint32_t worker_id) { - phy_h->configure_prach_params(); - // notify back MAC - task_sched->notify_background_task_result([this, task_id]() { notify_phy_config_completed(task_id); }); - }); + resource_selection(); } /* Resource selection as defined in 5.1.2 */ @@ -538,27 +519,17 @@ void ra_proc::complete() mux_unit->msg3_flush(); - if (ra_is_ho) { - rrc->ho_ra_completed(); - } + rrc->ra_completed(); + log_h->console("Random Access Complete. c-rnti=0x%x, ta=%d\n", rntis->crnti, current_ta); rInfo("Random Access Complete. c-rnti=0x%x, ta=%d\n", rntis->crnti, current_ta); state = START_WAIT_COMPLETION; } -void ra_proc::start_noncont(uint32_t preamble_index, uint32_t prach_mask) -{ - next_preamble_idx = preamble_index; - next_prach_mask = prach_mask; - noncontention_enabled = true; - start_mac_order(56, true); -} - -void ra_proc::start_mac_order(uint32_t msg_len_bits, bool is_ho) +void ra_proc::start_mac_order(uint32_t msg_len_bits) { if (state == IDLE) { - ra_is_ho = is_ho; started_by_pdcch = false; new_ra_msg_len = msg_len_bits; rInfo("Starting PRACH by MAC order\n"); diff --git a/srsue/src/stack/mac/ul_harq.cc b/srsue/src/stack/mac/ul_harq.cc index 31a8a8ab5..8239c53fa 100644 --- a/srsue/src/stack/mac/ul_harq.cc +++ b/srsue/src/stack/mac/ul_harq.cc @@ -240,7 +240,7 @@ void ul_harq_entity::ul_harq_process::new_grant_ul(mac_interface_phy_lte::mac_gr // Uplink dci in a RAR and there is a PDU in the Msg3 buffer if (grant.is_rar) { if (harq_entity->mux_unit->msg3_is_pending()) { - Debug("Getting Msg3 buffer payload, dci size=%d bytes\n", grant.tb.tbs); + Debug("Getting Msg3 buffer payload, grant size=%d bytes\n", grant.tb.tbs); pdu_ptr = harq_entity->mux_unit->msg3_get(payload_buffer.get(), grant.tb.tbs); if (pdu_ptr) { generate_new_tx(grant, action); diff --git a/srsue/src/stack/rrc/phy_controller.cc b/srsue/src/stack/rrc/phy_controller.cc index 9da3aeeca..c9edb0dca 100644 --- a/srsue/src/stack/rrc/phy_controller.cc +++ b/srsue/src/stack/rrc/phy_controller.cc @@ -23,7 +23,7 @@ namespace srsue { -std::string to_string(const phy_interface_rrc_lte::phy_cell_t& cell) +std::string to_string(const phy_cell_t& cell) { char buffer[128]; snprintf(buffer, sizeof(buffer), "{pci=%d, dl_earfcn=%d}", cell.pci, cell.earfcn); @@ -79,12 +79,7 @@ void phy_controller::selecting_cell::enter(phy_controller* f, const cell_sel_cmd csel_res.result = false; fsmInfo("Starting for pci=%d, earfcn=%d\n", target_cell.pci, target_cell.earfcn); - phy_interface_rrc_lte::phy_cell_t cell_copy = target_cell; - f->task_sched.enqueue_background_task([f, cell_copy](uint32_t worker_id) { - bool ret = f->phy->cell_select(&cell_copy); - // notify back RRC - f->task_sched.notify_background_task_result([f, ret]() { f->cell_selection_completed(ret); }); - }); + f->phy->cell_select(target_cell); } void phy_controller::selecting_cell::exit(phy_controller* f) @@ -139,12 +134,7 @@ void phy_controller::cell_search_completed(cell_search_ret_t cs_ret, phy_cell_t void phy_controller::searching_cell::enter(phy_controller* f) { otherfsmInfo(f, "Initiating Cell search\n"); - f->task_sched.enqueue_background_task([f](uint32_t worker_id) { - phy_interface_rrc_lte::phy_cell_t found_cell; - phy_interface_rrc_lte::cell_search_ret_t ret = f->phy->cell_search(&found_cell); - // notify back RRC - f->task_sched.notify_background_task_result([f, found_cell, ret]() { f->cell_search_completed(ret, found_cell); }); - }); + f->phy->cell_search(); } void phy_controller::handle_cell_search_res(searching_cell& s, const cell_srch_res& result) diff --git a/srsue/src/stack/rrc/rrc.cc b/srsue/src/stack/rrc/rrc.cc index 3b41d8837..db0f1f184 100644 --- a/srsue/src/stack/rrc/rrc.cc +++ b/srsue/src/stack/rrc/rrc.cc @@ -247,8 +247,10 @@ void rrc::run_tti() case cmd_msg_t::RLF: radio_link_failure_process(); break; - case cmd_msg_t::HO_COMPLETE: - ho_handler.trigger(ho_proc::ra_completed_ev{msg.lcid > 0}); + case cmd_msg_t::RA_COMPLETE: + if (ho_handler.is_busy()) { + ho_handler.trigger(ho_proc::ra_completed_ev{msg.lcid > 0}); + } break; case cmd_msg_t::STOP: return; @@ -348,6 +350,20 @@ void rrc::set_ue_identity(srslte::s_tmsi_t s_tmsi) * *******************************************************************************/ +void rrc::cell_search_complete(rrc_interface_phy_lte::cell_search_ret_t cs_ret, phy_cell_t found_cell) +{ + phy_ctrl->cell_search_completed(cs_ret, found_cell); +} + +void rrc::cell_select_complete(bool cs_ret) +{ + phy_ctrl->cell_selection_completed(cs_ret); +} + +void rrc::set_config_complete(bool status) {} + +void rrc::set_scell_complete(bool status) {} + /* This function is called from a PHY worker thus must return very quickly. * Queue the values of the measurements and process them from the RRC thread */ @@ -478,8 +494,8 @@ void rrc::cell_reselection(float rsrp, float rsrq) // TODO: Inter-frequency cell reselection } -// Set serving cell -void rrc::set_serving_cell(phy_interface_rrc_lte::phy_cell_t phy_cell, bool discard_serving) +// Set new serving cell +void rrc::set_serving_cell(phy_cell_t phy_cell, bool discard_serving) { meas_cells.set_serving_cell(phy_cell, discard_serving); } @@ -499,6 +515,11 @@ bool rrc::has_neighbour_cell(uint32_t earfcn, uint32_t pci) const return meas_cells.has_neighbour_cell(earfcn, pci); } +bool rrc::is_serving_cell(uint32_t earfcn, uint32_t pci) const +{ + return meas_cells.serving_cell().phy_cell.earfcn == earfcn and meas_cells.serving_cell().phy_cell.pci == pci; +} + /******************************************************************************* * * @@ -854,10 +875,10 @@ void rrc::send_rrc_con_reconfig_complete() send_ul_dcch_msg(RB_ID_SRB1, ul_dcch_msg); } -void rrc::ho_ra_completed() +void rrc::ra_completed() { cmd_msg_t msg; - msg.command = cmd_msg_t::HO_COMPLETE; + msg.command = cmd_msg_t::RA_COMPLETE; msg.lcid = 1; cmd_q.push(std::move(msg)); } @@ -915,36 +936,31 @@ bool rrc::con_reconfig(const rrc_conn_recfg_s& reconfig) } } + // Apply Scell RR configurations (call is non-blocking). Make a copy since can be changed inside apply_scell_config() + // Note that apply_scell_config() calls set_scell() and set_config() which run in the background. rrc_conn_recfg_r8_ies_s reconfig_r8_ = *reconfig_r8; - task_sched.enqueue_background_task([this, reconfig_r8_](uint32_t worker_id) mutable { - // Apply configurations without blocking stack - apply_scell_config(&reconfig_r8_); - - // notify back RRC - task_sched.notify_background_task_result([this, reconfig_r8_]() { - const rrc_conn_recfg_r8_ies_s* reconfig_r8 = &reconfig_r8_; + apply_scell_config(&reconfig_r8_); - if (!measurements->parse_meas_config( - reconfig_r8, reestablishment_successful, connection_reest.get()->get_source_earfcn())) { - return; - } + if (!measurements->parse_meas_config( + reconfig_r8, reestablishment_successful, connection_reest.get()->get_source_earfcn())) { + return false; + } - send_rrc_con_reconfig_complete(); + // FIXME-@frankist: From here to the end need to be processed when set_config_complete() is called + send_rrc_con_reconfig_complete(); - unique_byte_buffer_t nas_sdu; - for (uint32_t i = 0; i < reconfig_r8->ded_info_nas_list.size(); i++) { - nas_sdu = srslte::allocate_unique_buffer(*pool); - if (nas_sdu.get()) { - memcpy(nas_sdu->msg, reconfig_r8->ded_info_nas_list[i].data(), reconfig_r8->ded_info_nas_list[i].size()); - nas_sdu->N_bytes = reconfig_r8->ded_info_nas_list[i].size(); - nas->write_pdu(RB_ID_SRB1, std::move(nas_sdu)); - } else { - rrc_log->error("Fatal Error: Couldn't allocate PDU in %s.\n", __FUNCTION__); - return; - } - } - }); - }); + unique_byte_buffer_t nas_sdu; + for (uint32_t i = 0; i < reconfig_r8->ded_info_nas_list.size(); i++) { + nas_sdu = srslte::allocate_unique_buffer(*pool); + if (nas_sdu.get()) { + memcpy(nas_sdu->msg, reconfig_r8->ded_info_nas_list[i].data(), reconfig_r8->ded_info_nas_list[i].size()); + nas_sdu->N_bytes = reconfig_r8->ded_info_nas_list[i].size(); + nas->write_pdu(RB_ID_SRB1, std::move(nas_sdu)); + } else { + rrc_log->error("Fatal Error: Couldn't allocate PDU in %s.\n", __FUNCTION__); + return false; + } + } return true; } @@ -1011,7 +1027,6 @@ void rrc::leave_connected() pdcp->reset(); rlc->reset(); mac->reset(); - phy->reset(); set_phy_default(); set_mac_default(); stop_timers(); @@ -1051,17 +1066,6 @@ void rrc::start_con_restablishment(reest_cause_e cause) callback_list.add_proc(connection_reest); } -void rrc::cell_search_completed(const phy_interface_rrc_lte::cell_search_ret_t& cs_ret, - const phy_interface_rrc_lte::phy_cell_t& found_cell) -{ - phy_ctrl->cell_search_completed(cs_ret, found_cell); -} - -void rrc::cell_select_completed(bool cs_ret) -{ - phy_ctrl->cell_selection_completed(cs_ret); -} - /** * Check whether data on SRB1 or SRB2 still needs to be sent. * If the bearer is suspended it will not be considered. @@ -1947,6 +1951,8 @@ void rrc::log_rr_config_common() void rrc::apply_rr_config_common(rr_cfg_common_s* config, bool send_lower_layers) { + rrc_log->info("Applying MAC/PHY config common\n"); + if (config->rach_cfg_common_present) { set_mac_cfg_t_rach_cfg_common(¤t_mac_cfg, config->rach_cfg_common); } @@ -2023,6 +2029,8 @@ void rrc::log_phy_config_dedicated() // Apply default physical common and dedicated configuration void rrc::set_phy_default() { + rrc_log->info("Setting default PHY config (common and dedicated)\n"); + current_phy_cfg.set_defaults(); if (phy != nullptr) { @@ -2040,6 +2048,8 @@ void rrc::set_phy_default() // Apply default physical channel configs (9.2.4) void rrc::set_phy_config_dedicated_default() { + rrc_log->info("Setting default PHY config dedicated\n"); + current_phy_cfg.set_defaults_dedicated(); if (phy != nullptr) { @@ -2057,6 +2067,8 @@ void rrc::set_phy_config_dedicated_default() // Apply provided PHY config void rrc::apply_phy_config_dedicated(const phys_cfg_ded_s& phy_cnfg, bool is_handover) { + rrc_log->info("Applying PHY config dedicated\n"); + set_phy_cfg_t_dedicated_cfg(¤t_phy_cfg, phy_cnfg); if (is_handover) { current_phy_cfg.ul_cfg.pucch.sr_configured = false; @@ -2083,6 +2095,8 @@ void rrc::apply_phy_scell_config(const scell_to_add_mod_r10_s& scell_config) return; } + rrc_log->info("Applying PHY config to scell\n"); + // Initialise default parameters from primary cell earfcn = meas_cells.serving_cell().get_earfcn(); @@ -2122,10 +2136,14 @@ void rrc::apply_phy_scell_config(const scell_to_add_mod_r10_s& scell_config) } // Initialize scell config with pcell cfg - srslte::phy_cfg_t scell_phy_cfg = current_phy_cfg; - set_phy_cfg_t_scell_config(&scell_phy_cfg, scell_config); + set_phy_cfg_t_scell_config(¤t_phy_cfg, scell_config); + + if (!phy->set_scell(scell, scell_config.scell_idx_r10, earfcn)) { + rrc_log->error("Adding SCell cc_idx=%d\n", scell_config.scell_idx_r10); + } else if (!phy->set_config(current_phy_cfg, scell_config.scell_idx_r10)) { + rrc_log->error("Setting SCell configuration for cc_idx=%d\n", scell_config.scell_idx_r10); + } - phy->set_config(scell_phy_cfg, scell_config.scell_idx_r10, earfcn, &scell); current_scell_configured[scell_config.scell_idx_r10] = true; } @@ -2146,7 +2164,7 @@ void rrc::log_mac_config_dedicated() // 3GPP 36.331 v10 9.2.2 Default MAC main configuration void rrc::apply_mac_config_dedicated_default() { - rrc_log->info("Set MAC default configuration\n"); + rrc_log->info("Setting MAC default configuration\n"); current_mac_cfg.set_mac_main_cfg_default(); mac->set_config(current_mac_cfg); log_mac_config_dedicated(); @@ -2169,6 +2187,8 @@ bool rrc::apply_rr_config_dedicated(const rr_cfg_ded_s* cnfg, bool is_handover) } } + rrc_log->info("Applying MAC config dedicated\n"); + if (cnfg->mac_main_cfg_present) { if (cnfg->mac_main_cfg.type() == rr_cfg_ded_s::mac_main_cfg_c_::types::default_value) { current_mac_cfg.set_mac_main_cfg_default(); @@ -2217,6 +2237,8 @@ bool rrc::apply_rr_config_dedicated(const rr_cfg_ded_s* cnfg, bool is_handover) bool rrc::apply_rr_config_dedicated_on_ho_complete(const rr_cfg_ded_s& cnfg) { + rrc_log->info("Applying MAC/PHY config dedicated on HO complete\n"); + // Apply SR+CQI configuration to PHY if (cnfg.phys_cfg_ded_present) { current_phy_cfg.ul_cfg.pucch.sr_configured = cnfg.phys_cfg_ded.sched_request_cfg_present; @@ -2246,9 +2268,9 @@ void rrc::apply_scell_config(rrc_conn_recfg_r8_ies_s* reconfig_r8) if (reconfig_r8->non_crit_ext_present) { auto reconfig_r890 = &reconfig_r8->non_crit_ext; if (reconfig_r890->non_crit_ext_present) { - rrc_conn_recfg_v920_ies_s* reconfig_r920 = &reconfig_r890->non_crit_ext; + auto* reconfig_r920 = &reconfig_r890->non_crit_ext; if (reconfig_r920->non_crit_ext_present) { - rrc_conn_recfg_v1020_ies_s* reconfig_r1020 = &reconfig_r920->non_crit_ext; + auto* reconfig_r1020 = &reconfig_r920->non_crit_ext; // Handle Add/Modify SCell list if (reconfig_r1020->scell_to_add_mod_list_r10_present) { @@ -2486,7 +2508,6 @@ void rrc::add_mrb(uint32_t lcid, uint32_t port) // PHY CONFIG DEDICATED Defaults (3GPP 36.331 v10 9.2.4) void rrc::set_phy_default_pucch_srs() { - rrc_log->info("Setting default PHY config dedicated\n"); set_phy_config_dedicated_default(); // SR configuration affects to MAC SR too diff --git a/srsue/src/stack/rrc/rrc_cell.cc b/srsue/src/stack/rrc/rrc_cell.cc index f347bc244..40334be20 100644 --- a/srsue/src/stack/rrc/rrc_cell.cc +++ b/srsue/src/stack/rrc/rrc_cell.cc @@ -171,7 +171,7 @@ const cell_t* meas_cell_list::get_neighbour_cell_handle(uint32_t earfcn, uint32_ // If only neighbour PCI is provided, copy full cell from serving cell bool meas_cell_list::add_meas_cell(const rrc_interface_phy_lte::phy_meas_t& meas) { - phy_interface_rrc_lte::phy_cell_t phy_cell = {}; + phy_cell_t phy_cell = {}; phy_cell.earfcn = meas.earfcn; phy_cell.pci = meas.pci; unique_cell_t c = unique_cell_t(new cell_t(phy_cell)); @@ -337,7 +337,7 @@ cell_t* meas_cell_list::find_cell(uint32_t earfcn, uint32_t pci) return get_neighbour_cell_handle(earfcn, pci); } -int meas_cell_list::set_serving_cell(phy_interface_rrc_lte::phy_cell_t phy_cell, bool discard_serving) +int meas_cell_list::set_serving_cell(phy_cell_t phy_cell, bool discard_serving) { // don't update neighbor cell list unless serving cell changes if (phy_cell.pci == serving_cell().get_pci() && phy_cell.earfcn == serving_cell().get_earfcn()) { diff --git a/srsue/src/stack/rrc/rrc_meas.cc b/srsue/src/stack/rrc/rrc_meas.cc index d9f28526b..de3fc9341 100644 --- a/srsue/src/stack/rrc/rrc_meas.cc +++ b/srsue/src/stack/rrc/rrc_meas.cc @@ -208,11 +208,10 @@ void rrc::rrc_meas::var_meas_report_list::generate_report(const uint32_t measId) var_meas_report& var_meas = varMeasReportList.at(measId); // sort cells by RSRP - std::sort(var_meas.cell_triggered_list.begin(), - var_meas.cell_triggered_list.end(), - [this](phy_interface_rrc_lte::phy_cell_t a, phy_interface_rrc_lte::phy_cell_t b) { - return rrc_ptr->get_cell_rsrp(a.earfcn, a.pci) > rrc_ptr->get_cell_rsrp(b.earfcn, b.pci); - }); + std::sort( + var_meas.cell_triggered_list.begin(), var_meas.cell_triggered_list.end(), [this](phy_cell_t a, phy_cell_t b) { + return rrc_ptr->get_cell_rsrp(a.earfcn, a.pci) > rrc_ptr->get_cell_rsrp(b.earfcn, b.pci); + }); // set the measResultNeighCells to include the best neighbouring cells up to maxReportCells in accordance with // the following @@ -382,10 +381,9 @@ void rrc::rrc_meas::var_meas_cfg::report_triggers() for (auto& cell : trigger_state[m.first]) { if (cell.second.is_enter_equal(report_cfg.trigger_type.event().time_to_trigger.to_number())) { // Do not add if already exists - if (std::find_if(cells_triggered_list.begin(), - cells_triggered_list.end(), - [&cell](const phy_interface_rrc_lte::phy_cell_t& c) { return cell.first == c.pci; }) == - cells_triggered_list.end()) { + if (std::find_if(cells_triggered_list.begin(), cells_triggered_list.end(), [&cell](const phy_cell_t& c) { + return cell.first == c.pci; + }) == cells_triggered_list.end()) { cells_triggered_list.push_back({cell.first, meas_obj.carrier_freq}); new_cell_trigger = true; } diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index e6c17bfb7..2ffd869f9 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -99,8 +99,7 @@ void rrc_nr::write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu) {} void rrc_nr::max_retx_attempted() {} // STACK interface -void rrc_nr::cell_search_completed(const phy_interface_rrc_lte::cell_search_ret_t& cs_ret, - const phy_interface_rrc_lte::phy_cell_t& found_cell) +void rrc_nr::cell_search_completed(const rrc_interface_phy_lte::cell_search_ret_t& cs_ret, const phy_cell_t& found_cell) {} } // namespace srsue \ No newline at end of file diff --git a/srsue/src/stack/rrc/rrc_procedures.cc b/srsue/src/stack/rrc/rrc_procedures.cc index dca7a15f3..9da8c7d5e 100644 --- a/srsue/src/stack/rrc/rrc_procedures.cc +++ b/srsue/src/stack/rrc/rrc_procedures.cc @@ -77,14 +77,14 @@ proc_outcome_t rrc::cell_search_proc::step_si_acquire() // SI Acquire has completed if (si_acquire_fut.is_error()) { Error("Failed SI acquire for SIB0\n"); - search_result.cs_ret.found = phy_interface_rrc_lte::cell_search_ret_t::CELL_NOT_FOUND; + search_result.cs_ret.found = cell_search_ret_t::CELL_NOT_FOUND; return proc_outcome_t::success; } Info("Completed successfully\n"); return proc_outcome_t::success; } -proc_outcome_t rrc::cell_search_proc::handle_cell_found(const phy_interface_rrc_lte::phy_cell_t& new_cell) +proc_outcome_t rrc::cell_search_proc::handle_cell_found(const phy_cell_t& new_cell) { Info("Cell found in this frequency. Setting new serving cell EARFCN=%d PCI=%d ...\n", new_cell.earfcn, new_cell.pci); @@ -135,13 +135,13 @@ proc_outcome_t rrc::cell_search_proc::react(const bool& cs_ret) if (not cs_ret) { Error("Couldn't select new serving cell\n"); - search_result.cs_ret.found = phy_interface_rrc_lte::cell_search_ret_t::CELL_NOT_FOUND; + search_result.cs_ret.found = cell_search_ret_t::CELL_NOT_FOUND; return proc_outcome_t::success; } if (not rrc_ptr->phy->cell_is_camping()) { Warning("Could not camp on found cell.\n"); - search_result.cs_ret.found = phy_interface_rrc_lte::cell_search_ret_t::CELL_NOT_FOUND; + search_result.cs_ret.found = cell_search_ret_t::CELL_NOT_FOUND; return proc_outcome_t::success; } @@ -161,9 +161,9 @@ proc_outcome_t rrc::cell_search_proc::react(const phy_controller::cell_srch_res& search_result = event; // Transition to SI Acquire or finish - if (search_result.cs_ret.found == phy_interface_rrc_lte::cell_search_ret_t::CELL_FOUND) { + if (search_result.cs_ret.found == cell_search_ret_t::CELL_FOUND) { return handle_cell_found(search_result.found_cell); - } else if (search_result.cs_ret.found == phy_interface_rrc_lte::cell_search_ret_t::CELL_NOT_FOUND) { + } else if (search_result.cs_ret.found == cell_search_ret_t::CELL_NOT_FOUND) { // No cells found. Do nothing return proc_outcome_t::success; } @@ -618,9 +618,8 @@ proc_outcome_t rrc::cell_selection_proc::step_cell_search() cs_result = cs_result_t::no_cell; return proc_outcome_t::error; } - cs_result = (cell_search_fut.value()->found == phy_interface_rrc_lte::cell_search_ret_t::CELL_FOUND) - ? cs_result_t::changed_cell - : cs_result_t::no_cell; + cs_result = (cell_search_fut.value()->found == cell_search_ret_t::CELL_FOUND) ? cs_result_t::changed_cell + : cs_result_t::no_cell; Info("Cell Search of cell selection run successfully\n"); return proc_outcome_t::success; } @@ -697,14 +696,14 @@ proc_outcome_t rrc::plmn_search_proc::step() // wait for new TTI return proc_outcome_t::yield; } - if (cell_search_fut.is_error() or cell_search_fut.value()->found == phy_interface_rrc_lte::cell_search_ret_t::ERROR) { + if (cell_search_fut.is_error() or cell_search_fut.value()->found == cell_search_ret_t::ERROR) { // stop search nof_plmns = -1; Error("Failed due to failed cell search sub-procedure\n"); return proc_outcome_t::error; } - if (cell_search_fut.value()->found == phy_interface_rrc_lte::cell_search_ret_t::CELL_FOUND) { + if (cell_search_fut.value()->found == cell_search_ret_t::CELL_FOUND) { if (rrc_ptr->meas_cells.serving_cell().has_sib1()) { // Save PLMN and TAC to NAS for (uint32_t i = 0; i < rrc_ptr->meas_cells.serving_cell().nof_plmns(); i++) { @@ -721,7 +720,7 @@ proc_outcome_t rrc::plmn_search_proc::step() } } - if (cell_search_fut.value()->last_freq == phy_interface_rrc_lte::cell_search_ret_t::NO_MORE_FREQS) { + if (cell_search_fut.value()->last_freq == cell_search_ret_t::NO_MORE_FREQS) { Info("completed PLMN search\n"); return proc_outcome_t::success; } @@ -1175,8 +1174,11 @@ proc_outcome_t rrc::connection_reest_proc::init(asn1::rrc::reest_cause_e cause) // reset MAC; rrc_ptr->mac->reset(); + // configure lower layers to consider the SCell(s), if configured, to be in deactivated state; + rrc_ptr->phy->set_activation_deactivation_scell(0); + // apply the default physical channel configuration as specified in 9.2.4; - rrc_ptr->set_phy_default_pucch_srs(); + // Note: this is done by the MAC Reset procedure // apply the default semi-persistent scheduling configuration as specified in 9.2.3; // N.A. @@ -1290,6 +1292,11 @@ srslte::proc_outcome_t rrc::connection_reest_proc::cell_criteria() Info("Cell Selection criteria passed after %dms. Sending RRC Connection Reestablishment Request\n", rrc_ptr->t311.time_elapsed()); + // Note: Not explicitly defined in the specs, but UE should apply SIB1 and SIB2 configuration in order to attempt + // a PRACH to a different cell + Info("Applying SIB2 configuration\n"); + rrc_ptr->handle_sib2(); + // stop timer T311; rrc_ptr->t311.stop(); @@ -1343,6 +1350,19 @@ proc_outcome_t rrc::connection_reest_proc::step() rrc::ho_proc::ho_proc(srsue::rrc* rrc_) : rrc_ptr(rrc_) {} +/** + * This function implements the core of the HO procedure defined in 5.3.5.4 + * + * Right after the PHY is instructed to synchronize with the new cell, DL and UL will be suspended by the PHY until in + * sync again with the new cell. + * + * Note that this function is executed by the main stack thread and needs to terminate in less than 1 ms. Any sub-task + * requiring more time shall use background workers. + * + * It is important that the whole 5.3.5.4 section is executed in a single procedure step. This guarantees that the stack + * will not run other functions between the steps, like SR, PRACH, etc. + * + */ srslte::proc_outcome_t rrc::ho_proc::init(const asn1::rrc::rrc_conn_recfg_s& rrc_reconf) { Info("Starting...\n"); @@ -1376,12 +1396,103 @@ srslte::proc_outcome_t rrc::ho_proc::init(const asn1::rrc::rrc_conn_recfg_s& rrc rrc_ptr->mac->get_rntis(&uernti); ho_src_rnti = uernti.crnti; - // Section 5.3.5.4. The implementation of the procedure follows in function step() + // Section 5.3.5.4 rrc_ptr->t310.stop(); rrc_ptr->t304.set(mob_ctrl_info->t304.to_number(), [this](uint32_t tid) { rrc_ptr->timer_expired(tid); }); rrc_ptr->t304.run(); - state = launch_phy_cell_select; + // starting at start synchronising to the DL of the target PCell + Info("Starting cell selection of target cell PCI=%d EARFCN=%d\n", target_cell.pci, target_cell.earfcn); + if (not rrc_ptr->phy_ctrl->start_cell_select(target_cell, rrc_ptr->ho_handler)) { + Error("Failed to launch the selection of target cell PCI=%d EARFCN=%d\n", target_cell.pci, target_cell.earfcn); + return proc_outcome_t::error; + } + + // reset MAC + rrc_ptr->mac->reset(); + + // Reestablish PDCP/RLC + rrc_ptr->pdcp->reestablish(); + rrc_ptr->rlc->reestablish(); + + // configure lower layers to consider the SCell(s), if configured, to be in deactivated state; + rrc_ptr->phy->set_activation_deactivation_scell(0); + + // apply the value of the newUE-Identity as the C-RNTI; + rrc_ptr->mac->set_ho_rnti(recfg_r8.mob_ctrl_info.new_ue_id.to_number(), recfg_r8.mob_ctrl_info.target_pci); + + // perform radio configuration when fullConfig is enabled + if (recfg_r8.non_crit_ext.non_crit_ext.full_cfg_r9_present) { + Error("fullConfig section was present but is not supported. Ignoring it.\n"); + } + + // configure lower layers in accordance with the received radioResourceConfigCommon + // Apply common config, but do not send to lower layers if Dedicated is present (to avoid sending twice) + rrc_ptr->apply_rr_config_common(&recfg_r8.mob_ctrl_info.rr_cfg_common, !recfg_r8.rr_cfg_ded_present); + + // configure lower layers in accordance with any additional fields, not covered in the previous, if included in the + // received mobilityControlInfo + if (recfg_r8.mob_ctrl_info.rach_cfg_ded_present) { + Info("Configuring RACH dedicated configuration with preamble_idx=%d, mask_idx=%d\n", + recfg_r8.mob_ctrl_info.rach_cfg_ded.ra_preamb_idx, + recfg_r8.mob_ctrl_info.rach_cfg_ded.ra_prach_mask_idx); + rrc_ptr->mac->set_rach_ded_cfg(recfg_r8.mob_ctrl_info.rach_cfg_ded.ra_preamb_idx, + recfg_r8.mob_ctrl_info.rach_cfg_ded.ra_prach_mask_idx); + } + + // if the RRCConnectionReconfiguration message includes the radioResourceConfigDedicated + if (recfg_r8.rr_cfg_ded_present) { + // Note: Disable SR config until RA completion + rrc_ptr->apply_rr_config_dedicated(&recfg_r8.rr_cfg_ded, true); + } + + // Security procedure + int ncc = -1; + if (recfg_r8.security_cfg_ho_present) { + auto& sec_intralte = recfg_r8.security_cfg_ho.handov_type.intra_lte(); + ncc = sec_intralte.next_hop_chaining_count; + if (sec_intralte.key_change_ind) { + // update Kenb based on fresh Kasme taken from previous successful NAS SMC + rrc_ptr->generate_as_keys(); + } + if (sec_intralte.security_algorithm_cfg_present) { + rrc_ptr->sec_cfg.cipher_algo = + (srslte::CIPHERING_ALGORITHM_ID_ENUM)sec_intralte.security_algorithm_cfg.ciphering_algorithm.to_number(); + rrc_ptr->sec_cfg.integ_algo = + (srslte::INTEGRITY_ALGORITHM_ID_ENUM)sec_intralte.security_algorithm_cfg.integrity_prot_algorithm.to_number(); + Info("Changed Ciphering to %s and Integrity to %s\n", + srslte::ciphering_algorithm_id_text[rrc_ptr->sec_cfg.cipher_algo], + srslte::integrity_algorithm_id_text[rrc_ptr->sec_cfg.integ_algo]); + } + } + + rrc_ptr->usim->generate_as_keys_ho(recfg_r8.mob_ctrl_info.target_pci, target_earfcn, ncc, &rrc_ptr->sec_cfg); + + rrc_ptr->pdcp->config_security_all(rrc_ptr->sec_cfg); + + // perform the measurement related actions as specified in 5.5.6.1; + rrc_ptr->measurements->ho_reest_actions(ho_src_cell.get_earfcn(), target_earfcn); + + // if the RRCConnectionReconfiguration message includes the measConfig: + if (not rrc_ptr->measurements->parse_meas_config(&recfg_r8, true, ho_src_cell.get_earfcn())) { + Error("Parsing measurementConfig. TODO: Send ReconfigurationReject\n"); + return proc_outcome_t::error; + } + + // Have RRCReconfComplete message ready when Msg3 is sent + rrc_ptr->send_rrc_con_reconfig_complete(); + + // SCell addition/removal can take some time to compute. Enqueue in a background task and do it in the end. + rrc_ptr->apply_scell_config(&recfg_r8); + + Info("Finished HO configuration. Waiting PHY to synchronize with target cell\n"); + + state = wait_phy_cell_select_complete; + return proc_outcome_t::yield; +} + +srslte::proc_outcome_t rrc::ho_proc::step() +{ return proc_outcome_t::yield; } @@ -1400,107 +1511,14 @@ srslte::proc_outcome_t rrc::ho_proc::react(const bool& cs_ret) return proc_outcome_t::error; } - rrc_ptr->set_serving_cell(target_cell, false); - - // Extract and apply scell config if any - rrc_ptr->task_sched.enqueue_background_task([this](uint32_t wid) { - rrc_ptr->apply_scell_config(&recfg_r8); - - rrc_ptr->task_sched.notify_background_task_result([this]() { - if (recfg_r8.mob_ctrl_info.rach_cfg_ded_present) { - Info("Starting non-contention based RA with preamble_idx=%d, mask_idx=%d\n", - recfg_r8.mob_ctrl_info.rach_cfg_ded.ra_preamb_idx, - recfg_r8.mob_ctrl_info.rach_cfg_ded.ra_prach_mask_idx); - rrc_ptr->mac->start_noncont_ho(recfg_r8.mob_ctrl_info.rach_cfg_ded.ra_preamb_idx, - recfg_r8.mob_ctrl_info.rach_cfg_ded.ra_prach_mask_idx); - } else { - Info("Starting contention-based RA\n"); - rrc_ptr->mac->start_cont_ho(); - } - - int ncc = -1; - if (recfg_r8.security_cfg_ho_present) { - auto& sec_intralte = recfg_r8.security_cfg_ho.handov_type.intra_lte(); - ncc = sec_intralte.next_hop_chaining_count; - if (sec_intralte.key_change_ind) { - // update Kenb based on fresh Kasme taken from previous successful NAS SMC - rrc_ptr->generate_as_keys(); - } - if (sec_intralte.security_algorithm_cfg_present) { - rrc_ptr->sec_cfg.cipher_algo = - (srslte::CIPHERING_ALGORITHM_ID_ENUM)sec_intralte.security_algorithm_cfg.ciphering_algorithm.to_number(); - rrc_ptr->sec_cfg.integ_algo = (srslte::INTEGRITY_ALGORITHM_ID_ENUM) - sec_intralte.security_algorithm_cfg.integrity_prot_algorithm.to_number(); - Info("Changed Ciphering to %s and Integrity to %s\n", - srslte::ciphering_algorithm_id_text[rrc_ptr->sec_cfg.cipher_algo], - srslte::integrity_algorithm_id_text[rrc_ptr->sec_cfg.integ_algo]); - } - } - - rrc_ptr->usim->generate_as_keys_ho( - recfg_r8.mob_ctrl_info.target_pci, rrc_ptr->meas_cells.serving_cell().get_earfcn(), ncc, &rrc_ptr->sec_cfg); + Info("PHY has synchronized with target cell. Waiting Random Access to complete\n"); - rrc_ptr->pdcp->config_security_all(rrc_ptr->sec_cfg); + rrc_ptr->set_serving_cell(target_cell, false); - // Have RRCReconfComplete message ready when Msg3 is sent - rrc_ptr->send_rrc_con_reconfig_complete(); - }); - }); state = wait_ra_completion; return proc_outcome_t::yield; } -srslte::proc_outcome_t rrc::ho_proc::step() -{ - if (rrc_ptr->state != RRC_STATE_CONNECTED) { - Info("HO interrupted, since RRC is no longer in connected state\n"); - return srslte::proc_outcome_t::error; - } - if (state == launch_phy_cell_select) { - // Reset/Reestablish stack - rrc_ptr->pdcp->reestablish(); - rrc_ptr->rlc->reestablish(); - rrc_ptr->mac->wait_uplink(); - rrc_ptr->mac->clear_rntis(); - rrc_ptr->mac->reset(); - rrc_ptr->phy->reset(); - - // configure lower layers to consider the SCell(s), if configured, to be in deactivated state; - rrc_ptr->phy->set_activation_deactivation_scell(0); - - // Todo: perform radio configuration when fullConfig is enabled - - // apply the value of the newUE-Identity as the C-RNTI; - rrc_ptr->mac->set_ho_rnti(recfg_r8.mob_ctrl_info.new_ue_id.to_number(), recfg_r8.mob_ctrl_info.target_pci); - - // Apply common config, but do not send to lower layers if Dedicated is present (to avoid sending twice) - rrc_ptr->apply_rr_config_common(&recfg_r8.mob_ctrl_info.rr_cfg_common, !recfg_r8.rr_cfg_ded_present); - - if (recfg_r8.rr_cfg_ded_present) { - // Note: Disable SR config until RA completion - rrc_ptr->apply_rr_config_dedicated(&recfg_r8.rr_cfg_ded, true); - } - - // if the RRCConnectionReconfiguration message includes the measConfig: - if (not rrc_ptr->measurements->parse_meas_config(&recfg_r8, true, ho_src_cell.get_earfcn())) { - Error("Parsing measurementConfig. TODO: Send ReconfigurationReject\n"); - return proc_outcome_t::error; - } - - // perform the measurement related actions as specified in 5.5.6.1; - rrc_ptr->measurements->ho_reest_actions(ho_src_cell.get_earfcn(), rrc_ptr->get_serving_cell()->get_earfcn()); - - Info("Starting cell selection of target cell PCI=%d on EARFCN=%d\n", target_cell.pci, target_cell.earfcn); - - if (not rrc_ptr->phy_ctrl->start_cell_select(target_cell, rrc_ptr->ho_handler)) { - Error("Failed to launch the selection of target cell PCI=%d on EARFCN=%d\n", target_cell.pci, target_cell.earfcn); - return proc_outcome_t::error; - } - state = wait_phy_cell_select_complete; - } - return proc_outcome_t::yield; -} - srslte::proc_outcome_t rrc::ho_proc::react(t304_expiry ev) { Info("HO preparation timed out. Reverting RRC security config from source cell.\n"); @@ -1521,6 +1539,8 @@ srslte::proc_outcome_t rrc::ho_proc::react(ra_completed_ev ev) } if (ev.success) { + Info("Random Access completed. Applying final configuration and finishing procedure\n"); + // TS 36.331, sec. 5.3.5.4, last "1>" rrc_ptr->t304.stop(); rrc_ptr->apply_rr_config_dedicated_on_ho_complete(recfg_r8.rr_cfg_ded); diff --git a/srsue/src/stack/ue_stack_lte.cc b/srsue/src/stack/ue_stack_lte.cc index b1ecaf826..acaa7dea1 100644 --- a/srsue/src/stack/ue_stack_lte.cc +++ b/srsue/src/stack/ue_stack_lte.cc @@ -46,8 +46,9 @@ ue_stack_lte::ue_stack_lte() : task_sched(512, 2, 64), tti_tprof("tti_tprof", "STCK", TTI_STAT_PERIOD) { - ue_task_queue = task_sched.make_task_queue(); - gw_queue_id = task_sched.make_task_queue(); + ue_task_queue = task_sched.make_task_queue(); + gw_queue_id = task_sched.make_task_queue(); + cfg_task_queue = task_sched.make_task_queue(); // sync_queue is added in init() } @@ -250,6 +251,30 @@ void ue_stack_lte::write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu) } } +/******************** + * PHY Interface + *******************/ + +void ue_stack_lte::cell_search_complete(cell_search_ret_t ret, phy_cell_t found_cell) +{ + cfg_task_queue.push([this, ret, found_cell]() { rrc.cell_search_complete(ret, found_cell); }); +} + +void ue_stack_lte::cell_select_complete(bool status) +{ + cfg_task_queue.push([this, status]() { rrc.cell_select_complete(status); }); +} + +void ue_stack_lte::set_config_complete(bool status) +{ + cfg_task_queue.push([this, status]() { rrc.set_config_complete(status); }); +} + +void ue_stack_lte::set_scell_complete(bool status) +{ + cfg_task_queue.push([this, status]() { rrc.set_scell_complete(status); }); +} + /******************** * SYNC Interface *******************/ diff --git a/srsue/test/mac_test.cc b/srsue/test/mac_test.cc index 494aaba50..6541ab8d9 100644 --- a/srsue/test/mac_test.cc +++ b/srsue/test/mac_test.cc @@ -75,6 +75,12 @@ public: uint32_t get_received_bytes() { return received_bytes; } void disable_read() { read_enable = false; } + void reset_queues() + { + for (auto& q : ul_queues) { + q.second = 0; + } + } private: bool read_enable = true; @@ -321,7 +327,7 @@ private: class rrc_dummy : public rrc_interface_mac { public: - void ho_ra_completed() { ho_finish_successful = true; } + void ra_completed() { ho_finish_successful = true; } void release_pucch_srs() { printf("%s\n", __FUNCTION__); } void run_tti(uint32_t tti) { printf("%s\n", __FUNCTION__); } void ra_problem() { rach_problem++; } @@ -1274,11 +1280,12 @@ int run_mac_ra_test(struct ra_test test, mac* mac, phy_dummy* phy, uint32_t* tti break; } // Request Msg3 (re)-transmission + for (uint32_t i = 0; i < test.nof_msg3_retx + 1; i++) { // Step to contention resolution. Make sure timer does not start until Msg3 is transmitted // and restarts on every retx - for (int j = 0; j < test.rach_cfg.ra_supervision_info.mac_contention_resolution_timer.to_number() - 1; j++) { + for (int k = 0; k < test.rach_cfg.ra_supervision_info.mac_contention_resolution_timer.to_number() - 1; k++) { stack->run_tti(tti); TESTASSERT(mac->get_dl_sched_rnti(tti) == (test.crnti ? test.crnti : test.temp_rnti)); tti++; @@ -1300,7 +1307,7 @@ int run_mac_ra_test(struct ra_test test, mac* mac, phy_dummy* phy, uint32_t* tti break; } - for (int i = 0; i < test.rach_cfg.ra_supervision_info.mac_contention_resolution_timer.to_number() - 1; i++) { + for (int k = 0; k < test.rach_cfg.ra_supervision_info.mac_contention_resolution_timer.to_number() - 1; k++) { stack->run_tti(tti); TESTASSERT(mac->get_dl_sched_rnti(tti) == (test.crnti ? test.crnti : test.temp_rnti)); tti++; @@ -1319,7 +1326,7 @@ int run_mac_ra_test(struct ra_test test, mac* mac, phy_dummy* phy, uint32_t* tti return -1; } break; - } else if ((int)i == test.rach_cfg.ra_supervision_info.mac_contention_resolution_timer.to_number() - 2) { + } else if ((int)k == test.rach_cfg.ra_supervision_info.mac_contention_resolution_timer.to_number() - 2) { new_prach = true; } } else { @@ -1507,9 +1514,10 @@ int mac_random_access_test() // In this case we will let the procedure expire the Contention Resolution window and make sure // and RRC HO fail signal is sent to RRC. mac_log->info("\n=========== Test %d =============\n", test_id++); + rrc.ho_finish_successful = false; phy.set_prach_tti(tti + phy.prach_delay); phy.set_crnti(0); - mac.start_cont_ho(); + rlc.write_sdu(0, 6); // Add new UL-CCCH with Msg3 (DRB SDU still buffered) stack.run_tti(tti++); my_test.nof_prachs = rach_cfg.ra_supervision_info.preamb_trans_max.to_number(); my_test.temp_rnti++; // Temporal C-RNTI has to change to avoid duplicate @@ -1519,15 +1527,22 @@ int mac_random_access_test() my_test.send_valid_ul_grant = false; TESTASSERT(!run_mac_ra_test(my_test, &mac, &phy, &tti, &stack)); TESTASSERT(!rrc.ho_finish_successful); + TESTASSERT(rrc.rach_problem == 2); // Test 8: Test Contention based Random Access. Same as above but we let the procedure finish successfully. mac_log->info("\n=========== Test %d =============\n", test_id++); + rrc.ho_finish_successful = false; + // Reset queue to make sure BSR retriggers a SR + rlc.reset_queues(); + stack.run_tti(tti++); + rlc.write_sdu(0, 6); // Add new UL-CCCH with Msg3 (DRB SDU still buffered) phy.set_prach_tti(tti + phy.prach_delay); - phy.set_crnti(0); - mac.start_cont_ho(); stack.run_tti(tti++); my_test.nof_prachs = 1; - my_test.temp_rnti++; // Temporal C-RNTI has to change to avoid duplicate + my_test.nof_msg3_retx = 0; + my_test.temp_rnti++; + my_test.msg4_valid_conres = true; + my_test.msg4_enable = true; my_test.send_valid_ul_grant = true; TESTASSERT(!run_mac_ra_test(my_test, &mac, &phy, &tti, &stack)); TESTASSERT(rrc.ho_finish_successful); @@ -1537,12 +1552,16 @@ int mac_random_access_test() // In this first test, no RAR is received and RA procedure fails mac_log->info("\n=========== Test %d =============\n", test_id++); rrc.ho_finish_successful = false; + // Reset queue to make sure BSR retriggers a SR + my_test.preamble_idx = 3; + mac.set_rach_ded_cfg(my_test.preamble_idx, 0); + stack.run_pending_tasks(); + rlc.reset_queues(); + stack.run_tti(tti++); + rlc.write_sdu(0, 6); // Add new UL-CCCH with Msg3 (DRB SDU still buffered) phy.set_prach_tti(tti + phy.prach_delay); stack.run_tti(tti++); phy.set_crnti(0); - my_test.preamble_idx = 3; - mac.start_noncont_ho(my_test.preamble_idx, 0); - stack.run_pending_tasks(); my_test.nof_prachs = rach_cfg.ra_supervision_info.preamb_trans_max.to_number(); my_test.rar_nof_invalid_rapid = rach_cfg.ra_supervision_info.ra_resp_win_size.to_number(); my_test.temp_rnti++; // Temporal C-RNTI has to change to avoid duplicate @@ -1553,12 +1572,15 @@ int mac_random_access_test() // Test 10: Test non-Contention based HO. Used in HO but preamble is given by the network. We check that // the procedure is considered successful without waiting for contention mac_log->info("\n=========== Test %d =============\n", test_id++); + my_test.preamble_idx = 3; + mac.set_rach_ded_cfg(my_test.preamble_idx, 0); + stack.run_pending_tasks(); + rlc.reset_queues(); + stack.run_tti(tti++); + rlc.write_sdu(0, 6); // Add new UL-CCCH with Msg3 (DRB SDU still buffered) phy.set_prach_tti(tti + phy.prach_delay); stack.run_tti(tti++); phy.set_crnti(0); - my_test.preamble_idx = 3; - mac.start_noncont_ho(my_test.preamble_idx, 0); - stack.run_pending_tasks(); my_test.nof_prachs = 1; my_test.rar_nof_invalid_rapid = 0; my_test.check_ra_successful = true; diff --git a/srsue/test/phy/scell_search_test.cc b/srsue/test/phy/scell_search_test.cc index 16a7f9082..fdd0badee 100644 --- a/srsue/test/phy/scell_search_test.cc +++ b/srsue/test/phy/scell_search_test.cc @@ -269,6 +269,11 @@ public: } } + void cell_search_complete(cell_search_ret_t ret, srsue::phy_cell_t found_cell) override {} + void cell_select_complete(bool status) override {} + void set_config_complete(bool status) override {} + void set_scell_complete(bool status) override {} + bool print_stats() { printf("\n-- Statistics:\n"); diff --git a/srsue/test/phy/ue_phy_test.cc b/srsue/test/phy/ue_phy_test.cc index 00090e93c..22ee27aa8 100644 --- a/srsue/test/phy/ue_phy_test.cc +++ b/srsue/test/phy/ue_phy_test.cc @@ -79,6 +79,10 @@ private: CALLBACK(new_grant_ul) CALLBACK(new_grant_dl) CALLBACK(run_tti) + CALLBACK(cell_search) + CALLBACK(cell_select) + CALLBACK(config) + CALLBACK(scell) public: // Local test access methods @@ -116,6 +120,32 @@ private: notify_run_tti(); log_h.debug("Run TTI %d\n", tti); } + + void cell_search_complete(cell_search_ret_t ret, srsue::phy_cell_t found_cell) override + { + cell_search_ret = ret; + last_found_cell = found_cell; + notify_cell_search(); + } + void cell_select_complete(bool status) override + { + notify_cell_select(); + last_cell_select = status; + } + void set_config_complete(bool status) override + { + notify_config(); + last_config = status; + } + void set_scell_complete(bool status) override + { + notify_scell(); + last_scell = status; + } + + cell_search_ret_t cell_search_ret = {}; + srsue::phy_cell_t last_found_cell = {}; + bool last_cell_select = false, last_config = false, last_scell = false; }; class dummy_radio : public srslte::radio_interface_phy @@ -399,7 +429,7 @@ public: phy->set_crnti(rnti); // Set PHY configuration - phy->set_config(phy_cfg, 0, 0, nullptr); + phy->set_config(phy_cfg, 0); } void run_thread() override @@ -506,23 +536,30 @@ int main(int argc, char** argv) phy_test->start(); // 1. Cell search - srsue::phy_interface_rrc_lte::phy_cell_t phy_cell; - auto cell_search_res = phy_test->get_phy_interface_rrc()->cell_search(&phy_cell); - TESTASSERT(cell_search_res.found == srsue::phy_interface_rrc_lte::cell_search_ret_t::CELL_FOUND); + TESTASSERT(phy_test->get_phy_interface_rrc()->cell_search()); + TESTASSERT(phy_test->get_stack()->wait_cell_search(default_timeout)); + TESTASSERT(phy_test->get_stack()->cell_search_ret.found == + srsue::rrc_interface_phy_lte::cell_search_ret_t::CELL_FOUND); // 2. Cell select - phy_test->get_phy_interface_rrc()->cell_select(&phy_cell); + srsue::phy_cell_t phy_cell = phy_test->get_stack()->last_found_cell; + TESTASSERT(phy_test->get_phy_interface_rrc()->cell_select(phy_cell)); + TESTASSERT(phy_test->get_stack()->wait_cell_select(default_timeout)); TESTASSERT(phy_test->get_stack()->wait_in_sync(default_timeout)); TESTASSERT(phy_test->get_stack()->wait_new_phy_meas(default_timeout)); // 3. Transmit PRACH - phy_test->get_phy_interface_mac()->configure_prach_params(); + srslte::phy_cfg_t phy_cfg = {}; + phy_cfg.set_defaults(); + phy_test->get_phy_interface_rrc()->set_config(phy_cfg, 0); + TESTASSERT(phy_test->get_stack()->wait_config(default_timeout)); + // phy_test->get_phy_interface_mac()->configure_prach_params(); phy_test->get_phy_interface_mac()->prach_send(0, -1, 0.0f); TESTASSERT(phy_test->get_radio()->wait_tx(default_timeout, false)); // 4. Configure RNTI with PUCCH and check transmission - uint16_t rnti = 0x3c; - srslte::phy_cfg_t phy_cfg = {}; + uint16_t rnti = 0x3c; + phy_cfg = {}; phy_cfg.set_defaults(); phy_cfg.dl_cfg.cqi_report.periodic_mode = SRSLTE_CQI_MODE_12; phy_cfg.dl_cfg.cqi_report.periodic_configured = true; diff --git a/srsue/test/ttcn3/hdr/lte_ttcn3_phy.h b/srsue/test/ttcn3/hdr/lte_ttcn3_phy.h index d2595ae95..389a207ce 100644 --- a/srsue/test/ttcn3/hdr/lte_ttcn3_phy.h +++ b/srsue/test/ttcn3/hdr/lte_ttcn3_phy.h @@ -65,10 +65,8 @@ public: // phy_interface_rrc_lte void enable_pregen_signals(bool enable) override; void set_activation_deactivation_scell(uint32_t cmd) override; - void set_config(srslte::phy_cfg_t& config, - uint32_t cc_idx = 0, - uint32_t earfcn = 0, - srslte_cell_t* cell_info = nullptr) override; + bool set_config(srslte::phy_cfg_t config, uint32_t cc_idx = 0) override; + bool set_scell(srslte_cell_t cell_info, uint32_t cc_idx, uint32_t earfcn) override; void set_config_tdd(srslte_tdd_config_t& tdd_config) override; void set_config_mbsfn_sib2(srslte::mbsfn_sf_cfg_t* cfg_list, uint32_t nof_cfgs) override{}; void set_config_mbsfn_sib13(const srslte::sib13_t& sib13) override{}; @@ -81,13 +79,11 @@ public: void set_mch_period_stop(uint32_t stop) override{}; // Cell search and selection procedures - cell_search_ret_t cell_search(phy_cell_t* found_cell) override; - bool cell_select(const phy_cell_t* cell) override; - bool cell_is_camping() override; - void reset() override; + bool cell_search() override; + bool cell_select(phy_cell_t cell) override; + bool cell_is_camping() override; // phy_interface_mac_lte - void configure_prach_params() override; void prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm, float ta_base_sec) override; prach_info_t prach_get_info() override; void sr_send() override; @@ -128,8 +124,8 @@ private: srslte::phy_cfg_t phy_cfg = {}; - uint32_t current_tti = 0; - uint32_t cc_idx = 0; + uint32_t current_tti = 0; + uint32_t cc_idx = 0; int prach_tti_tx = -1; @@ -146,4 +142,4 @@ private: } // namespace srsue -#endif \ No newline at end of file +#endif diff --git a/srsue/test/ttcn3/src/lte_ttcn3_phy.cc b/srsue/test/ttcn3/src/lte_ttcn3_phy.cc index 91957be7c..aa46513a1 100644 --- a/srsue/test/ttcn3/src/lte_ttcn3_phy.cc +++ b/srsue/test/ttcn3/src/lte_ttcn3_phy.cc @@ -80,27 +80,35 @@ void lte_ttcn3_phy::set_activation_deactivation_scell(uint32_t cmd) log.debug("%s not implemented.\n", __FUNCTION__); } -void lte_ttcn3_phy::set_config(srslte::phy_cfg_t& config, uint32_t cc_idx, uint32_t earfcn, srslte_cell_t* cell_info) +bool lte_ttcn3_phy::set_config(srslte::phy_cfg_t config, uint32_t cc_idx_) { log.debug("%s not implemented.\n", __FUNCTION__); + return true; +} + +bool lte_ttcn3_phy::set_scell(srslte_cell_t cell_info, uint32_t cc_idx, uint32_t earfcn) +{ + log.debug("%s not implemented.\n", __FUNCTION__); + return true; } // Measurements interface -void lte_ttcn3_phy::meas_stop(){}; +void lte_ttcn3_phy::meas_stop() {} // Cell search and selection procedures // Note that in contrast to a real PHY, we have visibility of all existing cells // configured by the SS, including the ones that we should not even detect because // their power is too weak. The cell search should only report the cells that // are actually visible though. -phy_interface_rrc_lte::cell_search_ret_t lte_ttcn3_phy::cell_search(phy_cell_t* found_cell) +bool lte_ttcn3_phy::cell_search() { std::lock_guard lock(mutex); log.info("Running cell search in PHY\n"); - cell_search_ret_t ret = {}; - ret.found = cell_search_ret_t::CELL_NOT_FOUND; + rrc_interface_phy_lte::cell_search_ret_t ret = {}; + ret.found = rrc_interface_phy_lte::cell_search_ret_t::CELL_NOT_FOUND; + phy_cell_t found_cell = {}; if (not cells.empty() && cell_idx < cells.size()) { // only find suitable cells @@ -109,11 +117,9 @@ phy_interface_rrc_lte::cell_search_ret_t lte_ttcn3_phy::cell_search(phy_cell_t* cells[cell_idx].earfcn, cells[cell_idx].info.id, cells[cell_idx].power); - if (found_cell) { - found_cell->earfcn = cells[cell_idx].earfcn; - found_cell->pci = cells[cell_idx].info.id; - } - ret.found = cell_search_ret_t::CELL_FOUND; + found_cell.earfcn = cells[cell_idx].earfcn; + found_cell.pci = cells[cell_idx].info.id; + ret.found = rrc_interface_phy_lte::cell_search_ret_t::CELL_FOUND; } // advance index @@ -121,41 +127,44 @@ phy_interface_rrc_lte::cell_search_ret_t lte_ttcn3_phy::cell_search(phy_cell_t* if (cell_idx < cells.size()) { // more cells will be reported - ret.last_freq = cell_search_ret_t::MORE_FREQS; + ret.last_freq = rrc_interface_phy_lte::cell_search_ret_t::MORE_FREQS; } else { // all available cells have been reported, reset cell index - ret.last_freq = cell_search_ret_t::NO_MORE_FREQS; + ret.last_freq = rrc_interface_phy_lte::cell_search_ret_t::NO_MORE_FREQS; cell_idx = 0; } } else { log.warning("No cells configured yet.\n"); } - return ret; -}; + stack->cell_search_complete(ret, found_cell); + + return true; +} -bool lte_ttcn3_phy::cell_select(const phy_cell_t* rrc_cell) +bool lte_ttcn3_phy::cell_select(phy_cell_t rrc_cell) { // try to find RRC cell in current cell map for (auto& cell : cells) { - if (cell.info.id == rrc_cell->pci && cell.earfcn == rrc_cell->earfcn) { + if (cell.info.id == rrc_cell.pci && cell.earfcn == rrc_cell.earfcn) { if (cell.power >= SUITABLE_CELL_RS_EPRE) { pcell = cell; pcell_set = true; syssim->select_cell(pcell.info); - log.info("Select PCell with %.2f on PCI=%d on EARFCN=%d.\n", cell.power, rrc_cell->pci, rrc_cell->earfcn); + log.info("Select PCell with %.2f on PCI=%d on EARFCN=%d.\n", cell.power, rrc_cell.pci, rrc_cell.earfcn); } else { pcell_set = false; log.error("Power of selected cell too low (%.2f < %.2f)\n", cell.power, SUITABLE_CELL_RS_EPRE); } - return pcell_set; + stack->cell_select_complete(pcell_set); + return true; } } - log.error("Couldn't find RRC cell with PCI=%d on EARFCN=%d in cell map.\n", rrc_cell->pci, rrc_cell->earfcn); + log.error("Couldn't find RRC cell with PCI=%d on EARFCN=%d in cell map.\n", rrc_cell.pci, rrc_cell.earfcn); return false; -}; +} bool lte_ttcn3_phy::cell_is_camping() { @@ -164,18 +173,9 @@ bool lte_ttcn3_phy::cell_is_camping() return (pcell.power >= SUITABLE_CELL_RS_EPRE); } return false; -}; - -void lte_ttcn3_phy::reset() -{ - log.debug("%s not implemented.\n", __FUNCTION__); -}; +} // The interface for MAC (called from Stack thread context) -void lte_ttcn3_phy::configure_prach_params() -{ - log.debug("%s not implemented.\n", __FUNCTION__); -}; void lte_ttcn3_phy::prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm, float ta_base_sec) { diff --git a/srsue/test/ttcn3/src/ttcn3_syssim.cc b/srsue/test/ttcn3/src/ttcn3_syssim.cc index e53319d62..955df62e2 100644 --- a/srsue/test/ttcn3/src/ttcn3_syssim.cc +++ b/srsue/test/ttcn3/src/ttcn3_syssim.cc @@ -605,7 +605,7 @@ void ttcn3_syssim::send_rar(uint32_t preamble_index) // Internal function called from main thread void ttcn3_syssim::send_msg3_grant() { - log->info("Sending Msg3 grant for C-RNTI=%d\n", cells[pcell_idx]->config.crnti); + log->info("Sending Msg3 grant for C-RNTI=0x%x\n", cells[pcell_idx]->config.crnti); mac_interface_phy_lte::mac_grant_ul_t ul_grant = {}; ul_grant.tti_tx = (tti + 3) % 10240; diff --git a/srsue/test/upper/rrc_meas_test.cc b/srsue/test/upper/rrc_meas_test.cc index aaec45f30..249cd8b5b 100644 --- a/srsue/test/upper/rrc_meas_test.cc +++ b/srsue/test/upper/rrc_meas_test.cc @@ -43,43 +43,20 @@ public: } // Not implemented methods - void set_config(srslte::phy_cfg_t& config, - uint32_t cc_idx = 0, - uint32_t earfcn = 0, - srslte_cell_t* cell_info = nullptr) override - {} - void set_config_tdd(srslte_tdd_config_t& tdd_config) override {} - void set_config_mbsfn_sib2(srslte::mbsfn_sf_cfg_t* cfg_list, uint32_t nof_cfgs) override {} - void set_config_mbsfn_sib13(const srslte::sib13_t& sib13) override {} - void set_config_mbsfn_mcch(const srslte::mcch_msg_t& mcch) override {} - cell_search_ret_t cell_search(phy_cell_t* cell) override + bool set_config(srslte::phy_cfg_t config, uint32_t cc_idx) override { return true; } + bool set_scell(srslte_cell_t cell_info, uint32_t cc_idx, uint32_t earfcn) override { return true; } + void set_config_tdd(srslte_tdd_config_t& tdd_config) override {} + void set_config_mbsfn_sib2(srslte::mbsfn_sf_cfg_t* cfg_list, uint32_t nof_cfgs) override {} + void set_config_mbsfn_sib13(const srslte::sib13_t& sib13) override {} + void set_config_mbsfn_mcch(const srslte::mcch_msg_t& mcch) override {} + bool cell_search() override { return true; } + bool cell_is_camping() override { return false; } + void set_activation_deactivation_scell(uint32_t cmd) override {} + bool cell_select(phy_cell_t cell) override { - *cell = cell_search_res_cell; - cell_select_ret = true; - return cell_search_res_ret; + last_selected_cell = cell; + return true; } - bool cell_is_camping() override { return false; } - void set_activation_deactivation_scell(uint32_t cmd) override {} - bool cell_select(const phy_cell_t* cell = nullptr) override - { - last_selected_cell = *cell; - bool ret = cell_select_ret; - if (return_to_true) { - cell_select_ret = true; - } - return ret; - } - void set_cell_select_ret(bool cell_select_ret_, bool return_to_true_) - { - cell_select_ret = cell_select_ret_; - return_to_true = return_to_true_; - } - void set_cell_search_result(phy_cell_t cell, cell_search_ret_t ret) - { - cell_search_res_cell = cell; - cell_search_res_ret = ret; - } - void reset() override {} void enable_pregen_signals(bool enable) override {} void set_cells_to_meas(uint32_t earfcn, const std::set& pci) override @@ -120,17 +97,14 @@ public: } } - phy_interface_rrc_lte::phy_cell_t last_selected_cell = {}; + phy_cell_t last_selected_cell = {}; + private: bool meas_reset_called = false; std::set freqs_started; std::map > cells_started; uint32_t serving_pci = 0; uint32_t serving_earfcn = 0; - bool cell_select_ret = true; - bool return_to_true = true; - cell_search_ret_t cell_search_res_ret = {}; - phy_cell_t cell_search_res_cell = {}; }; class nas_test : public srsue::nas @@ -195,7 +169,7 @@ private: class rrc_test : public rrc { - srsue::stack_test_dummy* stack = nullptr; + stack_test_dummy* stack = nullptr; public: rrc_test(srslte::log_ref log_, stack_test_dummy* stack_) : rrc(stack_, &stack_->task_sched), stack(stack_) @@ -203,16 +177,8 @@ public: pool = srslte::byte_buffer_pool::get_instance(); nastest = std::unique_ptr(new nas_test(&stack->task_sched)); pdcptest = std::unique_ptr(new pdcp_test(log_->get_service_name().c_str(), &stack->task_sched)); - }; - void init() - { - rrc::init(&phytest, nullptr, nullptr, pdcptest.get(), nastest.get(), nullptr, nullptr, {}); - phy_interface_rrc_lte::phy_cell_t cell_search_cell = {}; - phy_interface_rrc_lte::cell_search_ret_t cell_search_ret = {}; - cell_search_ret.found = srsue::phy_interface_rrc_lte::cell_search_ret_t::CELL_NOT_FOUND; - cell_search_ret.last_freq = srsue::phy_interface_rrc_lte::cell_search_ret_t::NO_MORE_FREQS; - phytest.set_cell_search_result(cell_search_cell, cell_search_ret); } + void init() { rrc::init(&phytest, nullptr, nullptr, pdcptest.get(), nastest.get(), nullptr, nullptr, {}); } void run_tti(uint32_t tti_) { @@ -296,6 +262,7 @@ public: } using rrc::has_neighbour_cell; + using rrc::is_serving_cell; using rrc::start_cell_select; bool get_meas_res(meas_results_s& meas_res) { return pdcptest->get_meas_res(meas_res); } @@ -362,7 +329,7 @@ int cell_select_test() rrctest.connect(); rrctest.add_neighbour_cell(1, 1, 2.0); - rrctest.add_neighbour_cell(2, 2, 1.0); + rrctest.add_neighbour_cell(2, 2, 1.1); rrctest.add_neighbour_cell(3, 2, 1.0); rrctest.set_serving_cell(1, 1); TESTASSERT(not rrctest.has_neighbour_cell(1, 1)); @@ -371,29 +338,40 @@ int cell_select_test() // Start cell selection procedure. The RRC will start with strongest cell TESTASSERT(rrctest.start_cell_select() == SRSLTE_SUCCESS); - rrctest.phytest.set_cell_select_ret(false, true); // failed to set serving cell + TESTASSERT(rrctest.phytest.last_selected_cell.earfcn == 1); + TESTASSERT(rrctest.phytest.last_selected_cell.pci == 1); + stack.run_pending_tasks(); + rrctest.cell_select_complete(false); // it will fail to select pci=1 stack.run_pending_tasks(); + rrctest.cell_select_complete(true); // it will select pci=2 + rrctest.in_sync(); + stack.run_pending_tasks(); // it will select pci=2 TESTASSERT(rrctest.phytest.last_selected_cell.earfcn == 2); TESTASSERT(rrctest.phytest.last_selected_cell.pci == 2); TESTASSERT(rrctest.has_neighbour_cell(1, 1)); TESTASSERT(rrctest.has_neighbour_cell(2, 3)); - TESTASSERT(!rrctest.has_neighbour_cell(2, 2)); - rrctest.in_sync(); - stack.run_pending_tasks(); + TESTASSERT(not rrctest.has_neighbour_cell(2, 2)); // Cell Selection fails, make sure it goes to Cell Search - TESTASSERT(rrctest.start_cell_select() == SRSLTE_SUCCESS); - phy_interface_rrc_lte::phy_cell_t cell_search_cell = {}; - phy_interface_rrc_lte::cell_search_ret_t cell_search_ret = {}; + phy_cell_t cell_search_cell = {}; + rrc_interface_phy_lte::cell_search_ret_t cell_search_ret = {}; cell_search_cell.pci = 5; cell_search_cell.earfcn = 5; - cell_search_ret.found = srsue::phy_interface_rrc_lte::cell_search_ret_t::CELL_FOUND; - rrctest.phytest.set_cell_search_result(cell_search_cell, cell_search_ret); - rrctest.phytest.set_cell_select_ret(false, false); // failed to set serving cell + cell_search_ret.found = srsue::rrc_interface_phy_lte::cell_search_ret_t::CELL_FOUND; + TESTASSERT(rrctest.start_cell_select() == SRSLTE_SUCCESS); + rrctest.cell_select_complete(false); // it will fail to select pci=2 + stack.run_pending_tasks(); + rrctest.cell_select_complete(false); // it will fail to select pci=3 + stack.run_pending_tasks(); + rrctest.cell_search_complete(cell_search_ret, cell_search_cell); stack.run_pending_tasks(); - rrctest.in_sync(); TESTASSERT(rrctest.phytest.last_selected_cell.earfcn == 5); TESTASSERT(rrctest.phytest.last_selected_cell.pci == 5); + rrctest.cell_select_complete(true); + rrctest.in_sync(); + stack.run_pending_tasks(); + TESTASSERT(not rrctest.has_neighbour_cell(5, 5)); + TESTASSERT(rrctest.is_serving_cell(5, 5)); } return SRSLTE_SUCCESS; diff --git a/srsue/test/upper/rrc_phy_ctrl_test.cc b/srsue/test/upper/rrc_phy_ctrl_test.cc index 329fcdf65..6369d9217 100644 --- a/srsue/test/upper/rrc_phy_ctrl_test.cc +++ b/srsue/test/upper/rrc_phy_ctrl_test.cc @@ -59,7 +59,7 @@ struct cell_select_result_test { // start a new cell selection right away if (counter++ < 1) { - phy_interface_rrc_lte::phy_cell_t new_cell; + phy_cell_t new_cell; new_cell.pci = 3; new_cell.earfcn = 3400; phy_ctrl->start_cell_select(new_cell, *this); @@ -100,9 +100,9 @@ int test_phy_ctrl_fsm() phy_ctrl.out_sync(); TESTASSERT(not phy_ctrl.is_in_sync()); TESTASSERT(phy_ctrl.current_state_name() == "searching_cell"); - phy_interface_rrc_lte::cell_search_ret_t cs_ret; - cs_ret.found = phy_interface_rrc_lte::cell_search_ret_t::CELL_FOUND; - phy_interface_rrc_lte::phy_cell_t found_cell; + rrc_interface_phy_lte::cell_search_ret_t cs_ret; + cs_ret.found = rrc_interface_phy_lte::cell_search_ret_t::CELL_FOUND; + phy_cell_t found_cell; found_cell.pci = 1; found_cell.earfcn = 2; phy_ctrl.cell_search_completed(cs_ret, found_cell);