From c1be118d1da1a88e40eb52b28fe47bd99ff6e5e6 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 1 Oct 2019 12:26:48 +0100 Subject: [PATCH] new wrapper-based design for stack procedures. Removes extra base class, gets rid of spurious copies/moves during the pop(), and allows the use of a non-default ctor() --- lib/include/srslte/common/stack_procedure.h | 261 ++++++++++++-------- lib/test/common/CMakeLists.txt | 1 + lib/test/common/stack_procedure_test.cc | 117 ++++++--- srsue/hdr/stack/rrc/rrc.h | 5 +- srsue/hdr/stack/rrc/rrc_procedures.h | 89 ++++--- srsue/hdr/stack/upper/nas.h | 21 +- srsue/src/stack/rrc/rrc.cc | 27 +- srsue/src/stack/rrc/rrc_procedures.cc | 131 +++++----- srsue/src/stack/upper/nas.cc | 43 ++-- 9 files changed, 410 insertions(+), 285 deletions(-) diff --git a/lib/include/srslte/common/stack_procedure.h b/lib/include/srslte/common/stack_procedure.h index 5e39ccd1f..b2a488f45 100644 --- a/lib/include/srslte/common/stack_procedure.h +++ b/lib/include/srslte/common/stack_procedure.h @@ -33,7 +33,34 @@ enum class proc_state_t { on_going, success, error, inactive }; enum class proc_outcome_t { repeat, yield, success, error }; /************************************************************************************** - * class: proc_impl_t + * helper functions for overloading + ************************************************************************************/ +namespace detail { +template +auto optional_stop(T* obj, int is_success) -> decltype(obj->stop()) +{ + obj->stop(is_success); +} + +inline auto optional_stop(...) -> void +{ + // do nothing +} + +template +auto optional_clear(T* obj) -> decltype(obj->clear()) +{ + obj->clear(); +} + +inline auto optional_clear(...) -> void +{ + // do nothing +} +} // namespace detail + +/************************************************************************************** + * class: proc_itf_t * Provides an polymorphic interface for resumable procedures. This base can then be used * by a task dispatch queue via the method "run()". * Every procedure starts in inactive state, and finishes with success or error. @@ -52,54 +79,25 @@ enum class proc_outcome_t { repeat, yield, success, error }; * upon procedure completion, like sending back a response. * - set_proc_state() / is_#() - setter and getters for current procedure state ************************************************************************************/ -class proc_impl_t +class proc_manager_itf_t { public: - proc_impl_t() : proc_state(proc_state_t::inactive) {} - virtual ~proc_impl_t() = default; - virtual proc_outcome_t step() = 0; - virtual void stop() {} // may be overloaded - - bool run() - { - proc_outcome_t outcome = proc_outcome_t::repeat; - while (is_running() and outcome == proc_outcome_t::repeat) { - outcome = step(); - if (outcome == proc_outcome_t::error) { - set_proc_state(proc_state_t::error); - } else if (outcome == proc_outcome_t::success) { - set_proc_state(proc_state_t::success); - } - } - return is_running(); - } - - void set_proc_state(proc_state_t new_state) - { - proc_state = new_state; - if (proc_state == proc_state_t::error or proc_state == proc_state_t::success) { - stop(); - } - } - bool is_error() const { return proc_state == proc_state_t::error; } - bool is_success() const { return proc_state == proc_state_t::success; } - bool is_running() const { return proc_state == proc_state_t::on_going; } - bool is_complete() const { return is_success() or is_error(); } - bool is_active() const { return proc_state != proc_state_t::inactive; } - -private: - proc_state_t proc_state; + virtual bool run() = 0; + virtual ~proc_manager_itf_t() = default; }; +template +struct proc_result_t; + /************************************************************************************** - * class: proc_t - * Handles the lifetime, of a procedure T that derives from proc_impl_t, including - * its alloc, initialization, and reset back to initial state once the procedure has been + * class: proc_manager_t + * Manages the lifetime, of a procedure T, including its alloc, launching, + * and reset back to initial, uninit state once the procedure has been * completed and the user has extracted its results. * Can only be re-launched when a procedure T becomes inactive. * It uses a unique_ptr to allow the use of procedures that are forward declared. * It provides the following methods: - * - run() - calls proc_impl_t::run(). See above. + * - run() - calls T::step() and update the procedure state * - launch() - initializes the procedure T by calling T::init(...). Handles the case * of failed initialization, and forbids the initialization of procedures * that are already active. @@ -110,43 +108,43 @@ private: * specifying how each event type should be handled. ************************************************************************************/ template -class proc_t +class proc_t final : public proc_manager_itf_t { public: - explicit proc_t() : proc_impl_ptr(new T()) {} - T* get() { return proc_impl_ptr.get(); } - bool is_active() const { return proc_impl_ptr->is_active(); } - bool is_complete() const { return proc_impl_ptr->is_complete(); } - T* release() { return proc_impl_ptr.release(); } - bool run() { return proc_impl_ptr->run(); } - void clear() + template + explicit proc_t(Args&&... args) : proc_impl_ptr(new T(std::forward(args)...)) { - // Destructs the current object, and calls default ctor (which sets proc back to inactive and ready for another run) - proc_impl_ptr->~T(); - new (proc_impl_ptr.get()) T(); } - template - void trigger_event(Event&& e) + bool run() override { - if (proc_impl_ptr->is_running()) { - proc_outcome_t outcome = proc_impl_ptr->trigger_event(std::forward(e)); - if (outcome == proc_outcome_t::error) { - proc_impl_ptr->set_proc_state(proc_state_t::error); - } else if (outcome == proc_outcome_t::success) { - proc_impl_ptr->set_proc_state(proc_state_t::success); - } + proc_outcome_t outcome = proc_outcome_t::repeat; + while (is_running() and outcome == proc_outcome_t::repeat) { + outcome = proc_impl_ptr->step(); + handle_outcome(outcome); } + return is_running(); + } + + void clear() + { + // resets procedure and sets proc_t back to inactive + detail::optional_clear(proc_impl_ptr.get()); + proc_state = proc_state_t::inactive; } - T pop() + const T* get() const { return proc_impl_ptr.get(); } + bool is_active() const { return proc_state != proc_state_t::inactive; } + bool is_complete() const { return proc_state == proc_state_t::success or proc_state == proc_state_t::error; } + T* release() { return proc_impl_ptr.release(); } + + template + void trigger_event(Event&& e) { - if (not proc_impl_ptr->is_complete()) { - return T(); + if (is_running()) { + proc_outcome_t outcome = proc_impl_ptr->trigger_event(std::forward(e)); + handle_outcome(outcome); } - T ret(std::move(*proc_impl_ptr)); - clear(); - return ret; } template @@ -156,15 +154,16 @@ public: // if already active return false; } - proc_impl_ptr->set_proc_state(proc_state_t::on_going); + proc_state = proc_state_t::on_going; proc_outcome_t init_ret = proc_impl_ptr->init(std::forward(args)...); switch (init_ret) { case proc_outcome_t::error: - proc_impl_ptr->set_proc_state(proc_state_t::error); // call stop as an error + handle_outcome(init_ret); clear(); return false; case proc_outcome_t::success: - proc_impl_ptr->set_proc_state(proc_state_t::success); + handle_outcome(init_ret); + // does not reset, and returns true break; case proc_outcome_t::repeat: run(); // call run right away @@ -175,41 +174,85 @@ public: return true; } -private: + proc_result_t pop(); + +protected: + friend proc_result_t; + bool is_running() const { return proc_state == proc_state_t::on_going; } + void handle_outcome(proc_outcome_t outcome) + { + switch (outcome) { + case proc_outcome_t::error: + proc_state = proc_state_t::error; + detail::optional_stop(proc_impl_ptr.get(), false); + break; + case proc_outcome_t::success: + proc_state = proc_state_t::success; + detail::optional_stop(proc_impl_ptr.get(), true); + break; + case proc_outcome_t::repeat: + run(); + break; + default: + break; + } + } + + proc_state_t proc_state = proc_state_t::inactive; std::unique_ptr proc_impl_ptr; }; +template +struct proc_result_t { + explicit proc_result_t(proc_t* parent_) : parent(parent_) {} + ~proc_result_t() + { + if (parent->is_complete()) { + parent->clear(); + } + } + const T* proc() const { return parent->is_complete() ? parent->proc_impl_ptr.get() : nullptr; } + bool is_success() const { return parent->proc_state == proc_state_t::success; } + bool is_error() const { return parent->proc_state == proc_state_t::error; } + bool is_complete() const { return parent->is_complete(); } + +private: + proc_t* parent; +}; + +template +proc_result_t proc_t::pop() +{ + return proc_result_t{this}; +} + /************************************************************************************** * class: func_proc_t - * A proc_impl_t used to store lambda functions and other function pointers as a step() + * A proc used to store lambda functions and other function pointers as a step() * method, avoiding this way, always having to create a new class per procedure. ************************************************************************************/ -class func_proc_t : public proc_impl_t +class func_proc_t { public: - proc_outcome_t init(std::function step_func_) - { - step_func = std::move(step_func_); - return proc_outcome_t::yield; - } - - proc_outcome_t step() final { return step_func(); } + explicit func_proc_t(std::function step_func_) : step_func(std::move(step_func_)) {} + proc_outcome_t init() { return proc_outcome_t::yield; } + proc_outcome_t step() { return step_func(); } private: std::function step_func; }; /************************************************************************************** - * class: func_proc_t + * class: query_proc_t * A helper proc_impl_t whose step()/stop() are no op, but has a trigger_event() that * signals that the method has finished and store a result of type OutcomeType. ************************************************************************************/ template -class query_proc_t : public proc_impl_t +class query_proc_t { public: proc_outcome_t init() { return proc_outcome_t::yield; } - proc_outcome_t step() final { return proc_outcome_t::yield; } + proc_outcome_t step() { return proc_outcome_t::yield; } proc_outcome_t trigger_event(const OutcomeType& outcome_) { @@ -224,15 +267,16 @@ private: }; /************************************************************************************** - * class: callback_list_t - * Stores procedures that derive from proc_impl_t. Its run() method calls sequentially - * all the stored procedures run() method, and removes the procedures if they have + * class: proc_manager_list_t + * Stores procedure managers and, when run() is called, calls sequentially all + * the stored procedures run() method, and removes the procedures if they have * completed. * There are different ways to add a procedure to the list: * - add_proc(...) - adds a proc_t, and once the procedure has completed, takes it * out of the container without resetting it back to its initial state * or deleting. This is useful, if the user wants to extract the - * procedure result via proc_t::pop() + * procedure result after it has been taken off the manager list. + * "proc" variable has to outlive its completion * - consume_proc(...) - receives a proc_t as a rvalue, and calls the proc_t * destructor once the procedure has ended. Useful, for procedures * for which the user is not interested in the result, or reusing @@ -242,31 +286,32 @@ private: * - defer_task(...) - same as consume_proc(...) but takes a function pointer that * specifies a proc_impl_t step() function ************************************************************************************/ -class callback_list_t +class proc_manager_list_t { -public: - typedef std::function proc_deleter_t; - typedef std::unique_ptr callback_obj_t; - template + using proc_deleter_t = std::function; + using proc_obj_t = std::unique_ptr; + + template struct recycle_deleter_t { - void operator()(proc_impl_t* p) + void operator()(proc_manager_itf_t* p) { if (p != nullptr) { T* Tp = static_cast(p); - Tp->~T(); - new (Tp) T(); + Tp->clear(); + // just resets back to inactive, and does not dealloc } } }; - template +public: + template void add_proc(proc_t& proc) { if (proc.is_complete()) { return; } - callback_obj_t ptr(proc.get(), [](proc_impl_t* p) { /* do nothing */ }); - callbacks.push_back(std::move(ptr)); + proc_obj_t ptr(&proc, [](proc_manager_itf_t* p) { /* do nothing */ }); + proc_list.push_back(std::move(ptr)); } template @@ -275,25 +320,25 @@ public: if (proc.is_complete()) { return; } - callback_obj_t ptr(proc.release(), std::default_delete()); - callbacks.push_back(std::move(ptr)); + proc_obj_t ptr(new proc_t(std::move(proc)), std::default_delete()); + proc_list.push_back(std::move(ptr)); } - template + template void defer_proc(proc_t& proc) { if (proc.is_complete()) { - proc.pop(); + proc.clear(); return; } - callback_obj_t ptr(proc.get(), recycle_deleter_t()); - callbacks.push_back(std::move(ptr)); + proc_obj_t ptr(&proc, recycle_deleter_t >()); + proc_list.push_back(std::move(ptr)); } bool defer_task(std::function step_func) { - proc_t proc; - if (not proc.launch(std::move(step_func))) { + proc_t proc(std::move(step_func)); + if (not proc.launch()) { return false; } consume_proc(std::move(proc)); @@ -303,13 +348,13 @@ public: void run() { // Calls run for all callbacks. Remove the ones that have finished. The proc dtor is called. - callbacks.remove_if([](callback_obj_t& elem) { return not elem->run(); }); + proc_list.remove_if([](proc_obj_t& elem) { return not elem->run(); }); } - size_t size() const { return callbacks.size(); } + size_t size() const { return proc_list.size(); } private: - std::list callbacks; + std::list proc_list; }; } // namespace srslte diff --git a/lib/test/common/CMakeLists.txt b/lib/test/common/CMakeLists.txt index 72da402aa..1a1798f98 100644 --- a/lib/test/common/CMakeLists.txt +++ b/lib/test/common/CMakeLists.txt @@ -70,6 +70,7 @@ target_link_libraries(mac_nr_pdu_test srslte_phy srslte_common ${CMAKE_THREAD_LI add_test(mac_nr_pdu_test mac_nr_pdu_test) add_executable(stack_procedure_test stack_procedure_test.cc) +add_test(stack_procedure_test stack_procedure_test) add_executable(queue_test queue_test.cc) target_link_libraries(queue_test srslte_common ${CMAKE_THREAD_LIBS_INIT}) diff --git a/lib/test/common/stack_procedure_test.cc b/lib/test/common/stack_procedure_test.cc index 15b0adc55..d15598424 100644 --- a/lib/test/common/stack_procedure_test.cc +++ b/lib/test/common/stack_procedure_test.cc @@ -121,29 +121,39 @@ void new_test() TestObj::dtor_counter = 0; } -class custom_proc : public srslte::proc_impl_t +class custom_proc { public: + custom_proc() : ctor_value(5) {} + proc_outcome_t init(int a_) { if (a_ < 0) { printf("Failed to initiate custom_proc\n"); return proc_outcome_t::error; } - obj.id = a_; + obj.id = a_; + reset_called = false; return proc_outcome_t::yield; } - proc_outcome_t step() final + proc_outcome_t step() { if (counter++ > 5) { return proc_outcome_t::success; } return proc_outcome_t::yield; } - void stop() final { printf("TestObj %d stop() was called\n", obj.id); } + void stop(bool is_success) { printf("TestObj %d stop() was called\n", obj.id); } const char* name() const { return "custom proc"; } + void clear() + { + reset_called = true; + printf("TestObj was reset\n"); + } - TestObj obj; + TestObj obj; + const int ctor_value = 5; + bool reset_called = false; private: int counter = 0; @@ -159,6 +169,7 @@ int test_local_1() proc.launch(1); TESTASSERT(proc.is_active()); TESTASSERT(not proc.is_complete()); + TESTASSERT(not proc.get()->reset_called); while (proc.run()) { } @@ -166,29 +177,36 @@ int test_local_1() TESTASSERT(proc.is_active()); TESTASSERT(proc.is_complete()); - printf("pop being called\n"); - custom_proc procobj = proc.pop(); + const custom_proc& procobj = *proc.get(); TESTASSERT(procobj.obj.id == 1); - TESTASSERT(procobj.is_success()); + TESTASSERT(proc.is_active()); + printf("clear() being called\n"); + proc.clear(); TESTASSERT(not proc.is_active()); - TESTASSERT(proc.get()->obj.id == 0); // Proc is ready to be reused + TESTASSERT(proc.get()->reset_called); // Proc is ready to be reused + TESTASSERT(proc.get()->ctor_value == 5); printf("EXIT\n"); TESTASSERT(TestObj::copy_counter == 0); - TESTASSERT(TestObj::move_counter == 2); // pop() makes a swap which causes 2 moves - TESTASSERT(TestObj::dtor_counter == 2); // 2 dtors inside pop() (handler and popped obj not yet destructed) + TESTASSERT(TestObj::move_counter == 0); + TESTASSERT(TestObj::dtor_counter == 0); // destructor not called yet return 0; } int test_callback_1() { + /* + * Description: Test a procedure inserted in a manager list via "proc_manager_list_t::add_proc(...)" + * - check if the proc is not cleared automatically after it finished (need to check the result) + * - check if pop() works as expected, and resets proc after proc_result_t goes out of scope + */ new_test(); printf("\n--- Test %s ---\n", __func__); - srslte::callback_list_t callbacks; + srslte::proc_manager_list_t callbacks; srslte::proc_t proc; TESTASSERT(not proc.is_active()); - proc.launch(2); + TESTASSERT(proc.launch(2)); callbacks.add_proc(proc); // We have to call pop() explicitly to take the result TESTASSERT(callbacks.size() == 1); @@ -200,29 +218,38 @@ int test_callback_1() TESTASSERT(proc.is_active()); TESTASSERT(proc.is_complete()); - printf("pop being called\n"); - custom_proc procobj = proc.pop(); - TESTASSERT(procobj.is_success()); - TESTASSERT(procobj.obj.id == 2); + TESTASSERT(proc.get()->obj.id == 2); + TESTASSERT(proc.is_active()); + { + printf("pop being called\n"); + srslte::proc_result_t ret = proc.pop(); + TESTASSERT(proc.is_active()); + TESTASSERT(ret.is_success()); + // proc::reset() is finally called + } TESTASSERT(not proc.is_active()); + TESTASSERT(proc.get()->reset_called); // Proc is ready to be reused - TESTASSERT(proc.get()->obj.id == 0); // Proc is ready to be reused printf("EXIT\n"); TESTASSERT(TestObj::copy_counter == 0); - TESTASSERT(TestObj::move_counter == 2); // pop makes two moves - TESTASSERT(TestObj::dtor_counter == 2); // handler not yet destructed + TESTASSERT(TestObj::move_counter == 0); + TESTASSERT(TestObj::dtor_counter == 0); // handler not yet destructed return 0; } int test_callback_2() { + /* + * Description: Test a procedure inserted in a manager list via "proc_manager_list_t::consume_proc(...)" + * - check if the proc disappears automatically after it finished + */ new_test(); printf("\n--- Test %s ---\n", __func__); - srslte::callback_list_t callbacks; + srslte::proc_manager_list_t callbacks; srslte::proc_t proc; TESTASSERT(not proc.is_active()); - proc.launch(3); + TESTASSERT(proc.launch(3)); TESTASSERT(proc.is_active()); TESTASSERT(not proc.is_complete()); callbacks.consume_proc(std::move(proc)); @@ -235,16 +262,20 @@ int test_callback_2() printf("EXIT\n"); TESTASSERT(TestObj::copy_counter == 0); - TESTASSERT(TestObj::move_counter == 0); // no pop() - TESTASSERT(TestObj::dtor_counter == 1); // handler not yet destructed + TESTASSERT(TestObj::move_counter == 0); // it does not move proc itself, but its pointer + TESTASSERT(TestObj::dtor_counter == 1); // handler not yet destructed, but we called proc move return 0; } int test_callback_3() { + /* + * Description: Test a procedure inserted in a manager list via "proc_manager_list_t::defer_proc(...)" + * - check if the proc is cleared automatically after it finished + */ new_test(); printf("\n--- Test %s ---\n", __func__); - srslte::callback_list_t callbacks; + srslte::proc_manager_list_t callbacks; srslte::proc_t proc; TESTASSERT(not proc.is_active()); @@ -263,21 +294,26 @@ int test_callback_3() } TESTASSERT(not proc.is_active()); TESTASSERT(not proc.is_complete()); - TESTASSERT(proc.get()->obj.id == 0); // Proc is ready to be reused + TESTASSERT(proc.get()->reset_called); // Proc is ready to be reused printf("EXIT\n"); TESTASSERT(TestObj::copy_counter == 0); TESTASSERT(TestObj::move_counter == 0); - TESTASSERT(TestObj::dtor_counter == 1); // handler not yet destructed + TESTASSERT(TestObj::dtor_counter == 0); // handler not yet destructed return 0; } int test_callback_4() { + /* + * Description: Test for Lambda procedure types + * - test if a lambda that we passed decrements a counter correctly + * - test if when the lambda goes out of scope, procedure still works fine + */ new_test(); printf("\n--- Test %s ---\n", __func__); - srslte::callback_list_t callbacks; - int* counter = new int(5); + srslte::proc_manager_list_t callbacks; + int* counter = new int(5); { callbacks.defer_task([counter]() { @@ -300,6 +336,28 @@ int test_callback_4() return 0; } +int test_callback_5() +{ + /* + * Description: Test if finished procedure does not get added to the dispatch list + */ + new_test(); + printf("\n--- Test %s ---\n", __func__); + srslte::proc_manager_list_t callbacks; + srslte::proc_t proc; + TESTASSERT(proc.launch(5)); + while (proc.run()) { + TESTASSERT(proc.is_active()); + } + TESTASSERT(proc.is_active()); + TESTASSERT(not proc.get()->reset_called); + TESTASSERT(proc.is_complete()); + callbacks.defer_proc(proc); + TESTASSERT(callbacks.size() == 0); // do not add finished callbacks + + return 0; +} + int main() { TESTASSERT(test_local_1() == 0); @@ -307,6 +365,7 @@ int main() TESTASSERT(test_callback_2() == 0); TESTASSERT(test_callback_3() == 0); TESTASSERT(test_callback_4() == 0); + TESTASSERT(test_callback_5() == 0); return 0; } diff --git a/srsue/hdr/stack/rrc/rrc.h b/srsue/hdr/stack/rrc/rrc.h index bd5665542..dc53874fb 100644 --- a/srsue/hdr/stack/rrc/rrc.h +++ b/srsue/hdr/stack/rrc/rrc.h @@ -481,7 +481,8 @@ private: bool reestablishment_successful = false; // Measurements sub-class - class rrc_meas { + class rrc_meas + { public: void init(rrc *parent); void reset(); @@ -633,7 +634,7 @@ private: srslte::proc_t plmn_searcher; srslte::proc_t cell_reselector; - srslte::callback_list_t callback_list; + srslte::proc_manager_list_t callback_list; bool cell_selection_criteria(float rsrp, float rsrq = 0); void cell_reselection(float rsrp, float rsrq); diff --git a/srsue/hdr/stack/rrc/rrc_procedures.h b/srsue/hdr/stack/rrc/rrc_procedures.h index 6b4a0445a..627de5ce8 100644 --- a/srsue/hdr/stack/rrc/rrc_procedures.h +++ b/srsue/hdr/stack/rrc/rrc_procedures.h @@ -29,7 +29,7 @@ namespace srsue { -class rrc::cell_search_proc : public srslte::proc_impl_t +class rrc::cell_search_proc { public: struct cell_search_event_t { @@ -38,11 +38,12 @@ public: }; enum class state_t { phy_cell_search, si_acquire }; - srslte::proc_outcome_t init(rrc* parent_); - srslte::proc_outcome_t step() final; + explicit cell_search_proc(rrc* parent_); + srslte::proc_outcome_t init(); + srslte::proc_outcome_t step(); srslte::proc_outcome_t trigger_event(const cell_search_event_t& event); - phy_interface_rrc_lte::cell_search_ret_t get_cs_ret() { return search_result.cs_ret; } + phy_interface_rrc_lte::cell_search_ret_t get_cs_ret() const { return search_result.cs_ret; } static const char* name() { return "Cell Search"; } private: @@ -57,13 +58,14 @@ private: state_t state; }; -class rrc::si_acquire_proc : public srslte::proc_impl_t +class rrc::si_acquire_proc { public: const static int SIB_SEARCH_TIMEOUT_MS = 1000; - srslte::proc_outcome_t init(rrc* parent_, uint32_t sib_index_); - srslte::proc_outcome_t step() final; + explicit si_acquire_proc(rrc* parent_); + srslte::proc_outcome_t init(uint32_t sib_index_); + srslte::proc_outcome_t step(); static const char* name() { return "SI Acquire"; } private: @@ -74,37 +76,40 @@ private: srslte::log* log_h; // state - uint32_t period, sched_index; + uint32_t period = 0, sched_index = 0; uint32_t start_tti = 0; uint32_t sib_index = 0; uint32_t last_win_start = 0; }; -class rrc::serving_cell_config_proc : public srslte::proc_impl_t +class rrc::serving_cell_config_proc { public: - srslte::proc_outcome_t init(rrc* parent_, const std::vector& required_sibs_); - srslte::proc_outcome_t step() final; + explicit serving_cell_config_proc(rrc* parent_); + srslte::proc_outcome_t init(const std::vector& required_sibs_); + srslte::proc_outcome_t step(); static const char* name() { return "Serving Cell Configuration"; } private: - // consts + rrc* rrc_ptr; + srslte::log* log_h; + + // proc args std::vector required_sibs; - rrc* rrc_ptr; - srslte::log* log_h; // state variables enum class search_state_t { next_sib, si_acquire } search_state; uint32_t req_idx = 0; }; -class rrc::cell_selection_proc : public srslte::proc_impl_t +class rrc::cell_selection_proc { public: - srslte::proc_outcome_t init(rrc* parent_); - srslte::proc_outcome_t step() final; - void stop() final; - cs_result_t get_cs_result() { return cs_result; } + explicit cell_selection_proc(rrc* parent_); + srslte::proc_outcome_t init(); + srslte::proc_outcome_t step(); + void stop(bool is_success); + cs_result_t get_cs_result() const { return cs_result; } static const char* name() { return "Cell Selection"; } private: @@ -123,12 +128,13 @@ private: uint32_t neigh_index; }; -class rrc::plmn_search_proc : public srslte::proc_impl_t +class rrc::plmn_search_proc { public: - srslte::proc_outcome_t init(rrc* parent_); - srslte::proc_outcome_t step() final; - void stop() final; + explicit plmn_search_proc(rrc* parent_); + srslte::proc_outcome_t init(); + srslte::proc_outcome_t step(); + void stop(bool is_success); static const char* name() { return "PLMN Search"; } private: @@ -138,10 +144,10 @@ private: // state variables found_plmn_t found_plmns[MAX_FOUND_PLMNS]; - int nof_plmns; + int nof_plmns = 0; }; -class rrc::connection_request_proc : public srslte::proc_impl_t +class rrc::connection_request_proc { public: struct cell_selection_complete { @@ -149,17 +155,19 @@ public: cs_result_t cs_result; }; + explicit connection_request_proc(rrc* parent_); srslte::proc_outcome_t - init(rrc* parent_, srslte::establishment_cause_t cause_, srslte::unique_byte_buffer_t dedicated_info_nas_); - srslte::proc_outcome_t step() final; - void stop() final; + init(srslte::establishment_cause_t cause_, srslte::unique_byte_buffer_t dedicated_info_nas_); + srslte::proc_outcome_t step(); + void stop(bool is_success); srslte::proc_outcome_t trigger_event(const cell_selection_complete& e); static const char* name() { return "Connection Request"; } private: + // const + rrc* rrc_ptr; + srslte::log* log_h; // args - rrc* rrc_ptr; - srslte::log* log_h; srslte::establishment_cause_t cause; srslte::unique_byte_buffer_t dedicated_info_nas; @@ -168,15 +176,16 @@ private: cs_result_t cs_ret; }; -class rrc::process_pcch_proc : public srslte::proc_impl_t +class rrc::process_pcch_proc { public: struct paging_complete { bool outcome; }; - srslte::proc_outcome_t init(rrc* parent_, const asn1::rrc::paging_s& paging_); - srslte::proc_outcome_t step() final; + explicit process_pcch_proc(rrc* parent_); + srslte::proc_outcome_t init(const asn1::rrc::paging_s& paging_); + srslte::proc_outcome_t step(); srslte::proc_outcome_t trigger_event(paging_complete e); static const char* name() { return "Process PCCH"; } @@ -191,11 +200,12 @@ private: enum class state_t { next_record, nas_paging, serv_cell_cfg } state; }; -class rrc::go_idle_proc : public srslte::proc_impl_t +class rrc::go_idle_proc { public: - srslte::proc_outcome_t init(rrc* rrc_); - srslte::proc_outcome_t step() final; + explicit go_idle_proc(rrc* rrc_); + srslte::proc_outcome_t init(); + srslte::proc_outcome_t step(); static const char* name() { return "Go Idle"; } private: @@ -205,11 +215,12 @@ private: uint32_t rlc_flush_counter; }; -class rrc::cell_reselection_proc : public srslte::proc_impl_t +class rrc::cell_reselection_proc { public: - srslte::proc_outcome_t init(rrc* rrc_); - srslte::proc_outcome_t step() final; + cell_reselection_proc(rrc* rrc_); + srslte::proc_outcome_t init(); + srslte::proc_outcome_t step(); static const char* name() { return "Cell Reselection"; } private: diff --git a/srsue/hdr/stack/upper/nas.h b/srsue/hdr/stack/upper/nas.h index bd42bee49..9bcd62911 100644 --- a/srsue/hdr/stack/upper/nas.h +++ b/srsue/hdr/stack/upper/nas.h @@ -258,23 +258,24 @@ private: return list; } - class rrc_connect_proc : public srslte::proc_impl_t + class rrc_connect_proc { public: struct connection_request_completed_t { bool outcome; }; - srslte::proc_outcome_t init(nas* nas_ptr_, srslte::establishment_cause_t cause_, srslte::unique_byte_buffer_t pdu); - srslte::proc_outcome_t step() final; - static const char* name() { return "RRC Connect"; } + rrc_connect_proc(nas* nas_ptr_) : nas_ptr(nas_ptr_) {} + srslte::proc_outcome_t init(srslte::establishment_cause_t cause_, srslte::unique_byte_buffer_t pdu); + srslte::proc_outcome_t step(); + static const char* name() { return "RRC Connect"; } private: nas* nas_ptr; enum class state_t { conn_req, wait_attach } state; uint32_t wait_timeout; }; - class plmn_search_proc : public srslte::proc_impl_t + class plmn_search_proc { public: struct plmn_search_complete_t { @@ -288,16 +289,17 @@ private: } }; - srslte::proc_outcome_t init(nas* nas_ptr_); - srslte::proc_outcome_t step() final; + plmn_search_proc(nas* nas_ptr_) : nas_ptr(nas_ptr_) {} + srslte::proc_outcome_t init(); + srslte::proc_outcome_t step(); srslte::proc_outcome_t trigger_event(const plmn_search_complete_t& t); - static const char* name() { return "PLMN Search"; } + static const char* name() { return "PLMN Search"; } private: nas* nas_ptr; enum class state_t { plmn_search, rrc_connect } state; }; - srslte::callback_list_t callbacks; + srslte::proc_manager_list_t callbacks; srslte::proc_t plmn_searcher; srslte::proc_t rrc_connector; srslte::proc_t > conn_req_proc; @@ -305,5 +307,4 @@ private: } // namespace srsue - #endif // SRSUE_NAS_H diff --git a/srsue/src/stack/rrc/rrc.cc b/srsue/src/stack/rrc/rrc.cc index b96fc1fbe..e33ca9ccc 100644 --- a/srsue/src/stack/rrc/rrc.cc +++ b/srsue/src/stack/rrc/rrc.cc @@ -53,6 +53,15 @@ rrc::rrc(srslte::log* rrc_log_) : last_state(RRC_STATE_CONNECTED), drb_up(false), rrc_log(rrc_log_), + cell_searcher(this), + si_acquirer(this), + serv_cell_cfg(this), + cell_selector(this), + idle_setter(this), + pcch_processor(this), + conn_req_proc(this), + plmn_searcher(this), + cell_reselector(this), serving_cell(unique_cell_t(new cell_t({}, 0.0))) { } @@ -171,11 +180,13 @@ void rrc::get_metrics(rrc_metrics_t& m) m.state = state; } -bool rrc::is_connected() { +bool rrc::is_connected() +{ return (RRC_STATE_CONNECTED == state); } -bool rrc::have_drb() { +bool rrc::have_drb() +{ return drb_up; } @@ -301,7 +312,7 @@ uint16_t rrc::get_mnc() { */ bool rrc::plmn_search() { - if (not plmn_searcher.launch(this)) { + if (not plmn_searcher.launch()) { rrc_log->error("Unable to initiate PLMN search\n"); return false; } @@ -330,7 +341,7 @@ void rrc::plmn_select(srslte::plmn_id_t plmn_id) */ bool rrc::connection_request(srslte::establishment_cause_t cause, srslte::unique_byte_buffer_t dedicated_info_nas_) { - if (not conn_req_proc.launch(this, cause, std::move(dedicated_info_nas_))) { + if (not conn_req_proc.launch(cause, std::move(dedicated_info_nas_))) { rrc_log->error("Failed to initiate connection request procedure\n"); return false; } @@ -1193,7 +1204,7 @@ void rrc::start_ho() void rrc::start_go_idle() { - if (not idle_setter.launch(this)) { + if (not idle_setter.launch()) { rrc_log->info("Failed to set RRC to IDLE\n"); return; } @@ -1472,10 +1483,10 @@ void rrc::start_cell_reselection() return; } - if (not cell_reselector.launch(this)) { + if (not cell_reselector.launch()) { rrc_log->error("Failed to initiate a Cell Reselection procedure...\n"); } - callback_list.defer_proc(cell_reselector); + callback_list.add_proc(cell_reselector); } void rrc::cell_search_completed(const phy_interface_rrc_lte::cell_search_ret_t& cs_ret, @@ -1743,7 +1754,7 @@ void rrc::process_pcch(unique_byte_buffer_t pdu) paging->paging_record_list.resize(ASN1_RRC_MAX_PAGE_REC); } - if (not pcch_processor.launch(this, *paging)) { + if (not pcch_processor.launch(*paging)) { rrc_log->error("Failed to launch process PCCH procedure\n"); return; } diff --git a/srsue/src/stack/rrc/rrc_procedures.cc b/srsue/src/stack/rrc/rrc_procedures.cc index ab9f6e5ca..883bb1a23 100644 --- a/srsue/src/stack/rrc/rrc_procedures.cc +++ b/srsue/src/stack/rrc/rrc_procedures.cc @@ -35,12 +35,11 @@ using srslte::proc_outcome_t; * Cell Search Procedure *************************************/ +rrc::cell_search_proc::cell_search_proc(rrc* parent_) : rrc_ptr(parent_), log_h(parent_->rrc_log) {} + /* Searches for a cell in the current frequency and retrieves SIB1 if not retrieved yet */ -proc_outcome_t rrc::cell_search_proc::init(srsue::rrc* parent_) +proc_outcome_t rrc::cell_search_proc::init() { - rrc_ptr = parent_; - log_h = parent_->rrc_log; - Info("Starting...\n"); state = state_t::phy_cell_search; rrc_ptr->stack->start_cell_search(); @@ -56,7 +55,7 @@ proc_outcome_t rrc::cell_search_proc::step() } else if (state == state_t::si_acquire) { if (not rrc_ptr->si_acquirer.run()) { // SI Acquire has completed - si_acquire_proc ret = rrc_ptr->si_acquirer.pop(); + srslte::proc_result_t ret = rrc_ptr->si_acquirer.pop(); if (ret.is_error()) { Error("Failed to trigger SI acquire for SIB0\n"); return proc_outcome_t::error; @@ -93,7 +92,7 @@ proc_outcome_t rrc::cell_search_proc::handle_cell_found(const phy_interface_rrc_ return proc_outcome_t::success; } - if (not rrc_ptr->si_acquirer.launch(rrc_ptr, 0)) { + if (not rrc_ptr->si_acquirer.launch(0)) { // disallow concurrent si_acquire Error("SI Acquire is already running...\n"); return proc_outcome_t::error; @@ -135,14 +134,16 @@ proc_outcome_t rrc::cell_search_proc::trigger_event(const cell_search_event_t& e * SI Acquire Procedure *************************************/ -proc_outcome_t rrc::si_acquire_proc::init(rrc* parent_, uint32_t sib_index_) -{ - rrc_ptr = parent_; - log_h = parent_->rrc_log; +rrc::si_acquire_proc::si_acquire_proc(rrc* parent_) : rrc_ptr(parent_), log_h(parent_->rrc_log) {} +proc_outcome_t rrc::si_acquire_proc::init(uint32_t sib_index_) +{ Info("Starting SI Acquire procedure for SIB%d\n", sib_index_ + 1); - sib_index = sib_index_; - start_tti = rrc_ptr->mac->get_current_tti(); + sib_index = sib_index_; + start_tti = rrc_ptr->mac->get_current_tti(); + period = 0; + sched_index = 0; + last_win_start = 0; // set period/sched_index if (sib_index == 0) { @@ -242,13 +243,13 @@ uint32_t rrc::si_acquire_proc::sib_start_tti(uint32_t tti, uint32_t period, uint * Serving Cell Config Procedure *************************************/ +rrc::serving_cell_config_proc::serving_cell_config_proc(rrc* parent_) : rrc_ptr(parent_), log_h(parent_->rrc_log) {} + /* * Retrieves all required SIB or configures them if already retrieved before */ -proc_outcome_t rrc::serving_cell_config_proc::init(srsue::rrc* parent_, const std::vector& required_sibs_) +proc_outcome_t rrc::serving_cell_config_proc::init(const std::vector& required_sibs_) { - rrc_ptr = parent_; - log_h = parent_->rrc_log; required_sibs = required_sibs_; Info("Starting a Serving Cell Configuration Procedure\n"); @@ -274,7 +275,7 @@ proc_outcome_t rrc::serving_cell_config_proc::step() if (not rrc_ptr->serving_cell->has_sib(required_sib)) { Info("Cell has no SIB%d. Obtaining SIB%d\n", required_sib + 1, required_sib + 1); - if (not rrc_ptr->si_acquirer.launch(rrc_ptr, required_sib)) { + if (not rrc_ptr->si_acquirer.launch(required_sib)) { Error("SI Acquire is already running...\n"); return proc_outcome_t::error; } @@ -302,7 +303,7 @@ proc_outcome_t rrc::serving_cell_config_proc::step() } else if (search_state == search_state_t::si_acquire) { uint32_t required_sib = required_sibs[req_idx]; if (not rrc_ptr->si_acquirer.run()) { - si_acquire_proc ret = rrc_ptr->si_acquirer.pop(); + srslte::proc_result_t ret = rrc_ptr->si_acquirer.pop(); if (ret.is_error() or not rrc_ptr->serving_cell->has_sib(required_sib)) { if (required_sib < 2) { log_h->warning("Serving Cell Configuration has failed\n"); @@ -322,15 +323,14 @@ proc_outcome_t rrc::serving_cell_config_proc::step() * Cell Selection Procedure *************************************/ +rrc::cell_selection_proc::cell_selection_proc(rrc* parent_) : rrc_ptr(parent_), log_h(parent_->rrc_log) {} + /* * Cell selection procedure 36.304 5.2.3 * Select the best cell to camp on among the list of known cells */ -proc_outcome_t rrc::cell_selection_proc::init(srsue::rrc* parent_) +proc_outcome_t rrc::cell_selection_proc::init() { - rrc_ptr = parent_; - log_h = parent_->rrc_log; - if (rrc_ptr->neighbour_cells.empty() and rrc_ptr->serving_cell->in_sync and rrc_ptr->phy->cell_is_camping()) { // don't bother with cell selection if there are no neighbours and we are already camping Debug("Skipping Cell Selection Procedure ..\n"); @@ -365,7 +365,7 @@ proc_outcome_t rrc::cell_selection_proc::step_cell_selection() /* BLOCKING CALL */ if (rrc_ptr->phy->cell_select(&rrc_ptr->serving_cell->phy_cell)) { - if (not rrc_ptr->serv_cell_cfg.launch(rrc_ptr, rrc_ptr->ue_required_sibs)) { + if (not rrc_ptr->serv_cell_cfg.launch(rrc_ptr->ue_required_sibs)) { return proc_outcome_t::error; } state = search_state_t::cell_config; @@ -397,7 +397,7 @@ proc_outcome_t rrc::cell_selection_proc::step_cell_selection() // If can not find any suitable cell, search again Info("Cell selection and reselection in IDLE did not find any suitable cell. Searching again\n"); - if (not rrc_ptr->cell_searcher.launch(rrc_ptr)) { + if (not rrc_ptr->cell_searcher.launch()) { return proc_outcome_t::error; } state = search_state_t::cell_search; @@ -410,12 +410,12 @@ proc_outcome_t rrc::cell_selection_proc::step_cell_search() if (rrc_ptr->cell_searcher.run()) { return proc_outcome_t::yield; } - cell_search_proc ret = rrc_ptr->cell_searcher.pop(); + srslte::proc_result_t ret = rrc_ptr->cell_searcher.pop(); if (ret.is_error()) { cs_result = cs_result_t::no_cell; return proc_outcome_t::error; } else { - cs_result = (ret.get_cs_ret().found == phy_interface_rrc_lte::cell_search_ret_t::CELL_FOUND) + cs_result = (ret.proc()->get_cs_ret().found == phy_interface_rrc_lte::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"); @@ -428,7 +428,7 @@ proc_outcome_t rrc::cell_selection_proc::step_cell_config() if (rrc_ptr->serv_cell_cfg.run()) { return proc_outcome_t::yield; } - serving_cell_config_proc ret = rrc_ptr->serv_cell_cfg.pop(); + srslte::proc_result_t ret = rrc_ptr->serv_cell_cfg.pop(); if (ret.is_success()) { Info("All SIBs of serving cell obtained successfully\n"); cs_result = cs_result_t::changed_cell; @@ -455,27 +455,26 @@ proc_outcome_t rrc::cell_selection_proc::step() return proc_outcome_t::error; } -void rrc::cell_selection_proc::stop() +void rrc::cell_selection_proc::stop(bool is_success) { // Inform Connection Request Procedure Info("Completed with %s. Informing proc %s\n", - is_success() ? "success" : "failure", + is_success ? "success" : "failure", rrc_ptr->conn_req_proc.get()->name()); - rrc_ptr->conn_req_proc.trigger_event(connection_request_proc::cell_selection_complete{is_success(), cs_result}); + rrc_ptr->conn_req_proc.trigger_event(connection_request_proc::cell_selection_complete{is_success, cs_result}); } /************************************** * PLMN search Procedure *************************************/ -proc_outcome_t rrc::plmn_search_proc::init(srsue::rrc* parent_) -{ - rrc_ptr = parent_; - log_h = parent_->rrc_log; +rrc::plmn_search_proc::plmn_search_proc(rrc* parent_) : rrc_ptr(parent_), log_h(parent_->rrc_log) {} +proc_outcome_t rrc::plmn_search_proc::init() +{ Info("Starting PLMN search\n"); nof_plmns = 0; - if (not rrc_ptr->cell_searcher.launch(rrc_ptr)) { + if (not rrc_ptr->cell_searcher.launch()) { Error("Failed due to fail to init cell search...\n"); return proc_outcome_t::error; } @@ -493,8 +492,8 @@ proc_outcome_t rrc::plmn_search_proc::step() // wait for new TTI return proc_outcome_t::yield; } - cell_search_proc ret = rrc_ptr->cell_searcher.pop(); - phy_interface_rrc_lte::cell_search_ret_t cs_ret = ret.get_cs_ret(); + srslte::proc_result_t ret = rrc_ptr->cell_searcher.pop(); + phy_interface_rrc_lte::cell_search_ret_t cs_ret = ret.proc()->get_cs_ret(); if (ret.is_error() or cs_ret.found == phy_interface_rrc_lte::cell_search_ret_t::ERROR) { // stop search nof_plmns = -1; @@ -524,7 +523,7 @@ proc_outcome_t rrc::plmn_search_proc::step() return proc_outcome_t::success; } - if (not rrc_ptr->cell_searcher.launch(rrc_ptr)) { + if (not rrc_ptr->cell_searcher.launch()) { Error("Failed due to fail to init cell search...\n"); return proc_outcome_t::error; } @@ -533,13 +532,13 @@ proc_outcome_t rrc::plmn_search_proc::step() return proc_outcome_t::repeat; } -void rrc::plmn_search_proc::stop() +void rrc::plmn_search_proc::stop(bool is_success) { // on cleanup, call plmn_search_completed - if (is_success()) { + if (is_success) { Info("completed with success\n"); rrc_ptr->nas->plmn_search_completed(found_plmns, nof_plmns); - } else if (is_error()) { + } else { Error("PLMN Search completed with an error\n"); rrc_ptr->nas->plmn_search_completed(nullptr, -1); } @@ -549,12 +548,11 @@ void rrc::plmn_search_proc::stop() * Connection Request Procedure *************************************/ -proc_outcome_t rrc::connection_request_proc::init(rrc* parent_, - srslte::establishment_cause_t cause_, +rrc::connection_request_proc::connection_request_proc(rrc* parent_) : rrc_ptr(parent_), log_h(parent_->rrc_log) {} + +proc_outcome_t rrc::connection_request_proc::init(srslte::establishment_cause_t cause_, srslte::unique_byte_buffer_t dedicated_info_nas_) { - rrc_ptr = parent_; - log_h = parent_->rrc_log; cause = cause_; dedicated_info_nas = std::move(dedicated_info_nas_); @@ -579,7 +577,7 @@ proc_outcome_t rrc::connection_request_proc::init(rrc* cs_ret = cs_result_t::no_cell; state = state_t::cell_selection; - if (not rrc_ptr->cell_selector.launch(rrc_ptr)) { + if (not rrc_ptr->cell_selector.launch()) { if (not rrc_ptr->cell_selector.is_active()) { // Launch failed but cell selection was not already running Error("Failed to initiate cell selection procedure...\n"); @@ -591,8 +589,8 @@ proc_outcome_t rrc::connection_request_proc::init(rrc* // It already completed with success. FIXME: Find more elegant solution Info("A cell selection procedure has just finished successfully. I am reusing its result\n"); cell_selection_complete e{}; - e.is_success = rrc_ptr->cell_selector.get()->is_success(); e.cs_result = rrc_ptr->cell_selector.get()->get_cs_result(); + e.is_success = e.cs_result == cs_result_t::same_cell or e.cs_result == cs_result_t::changed_cell; return trigger_event(e); } } else { @@ -611,7 +609,7 @@ proc_outcome_t rrc::connection_request_proc::step() if (rrc_ptr->serv_cell_cfg.run()) { return proc_outcome_t::yield; } - serving_cell_config_proc ret = rrc_ptr->serv_cell_cfg.pop(); + srslte::proc_result_t ret = rrc_ptr->serv_cell_cfg.pop(); if (ret.is_error()) { Error("Configuring serving cell\n"); @@ -660,13 +658,13 @@ proc_outcome_t rrc::connection_request_proc::step() return proc_outcome_t::error; } -void rrc::connection_request_proc::stop() +void rrc::connection_request_proc::stop(bool is_success) { - if (is_error()) { + if (not is_success) { log_h->warning("Could not establish connection. Deallocating dedicatedInfoNAS PDU\n"); this->dedicated_info_nas.reset(); rrc_ptr->nas->connection_request_completed(false); - } else if (is_success()) { + } else { Info("Finished connection request procedure successfully.\n"); rrc_ptr->nas->connection_request_completed(true); } @@ -693,7 +691,7 @@ srslte::proc_outcome_t rrc::connection_request_proc::trigger_event(const cell_se // timeAlignmentCommon applied in configure_serving_cell Info("Configuring serving cell...\n"); - if (not rrc_ptr->serv_cell_cfg.launch(rrc_ptr, rrc_ptr->ue_required_sibs)) { + if (not rrc_ptr->serv_cell_cfg.launch(rrc_ptr->ue_required_sibs)) { Error("Attach request failed to configure serving cell...\n"); return proc_outcome_t::error; } @@ -720,11 +718,11 @@ srslte::proc_outcome_t rrc::connection_request_proc::trigger_event(const cell_se * Process PCCH procedure *************************************/ -proc_outcome_t rrc::process_pcch_proc::init(rrc* parent_, const asn1::rrc::paging_s& paging_) +rrc::process_pcch_proc::process_pcch_proc(srsue::rrc* parent_) : rrc_ptr(parent_), log_h(parent_->rrc_log) {} + +proc_outcome_t rrc::process_pcch_proc::init(const asn1::rrc::paging_s& paging_) { - rrc_ptr = parent_; - log_h = parent_->rrc_log; - paging = paging_; + paging = paging_; paging_idx = 0; state = state_t::next_record; @@ -762,7 +760,7 @@ proc_outcome_t rrc::process_pcch_proc::step() rrc_ptr->serving_cell->reset_sibs(); // create a serving cell config procedure and push it to callback list - if (not rrc_ptr->serv_cell_cfg.launch(rrc_ptr, rrc_ptr->ue_required_sibs)) { + if (not rrc_ptr->serv_cell_cfg.launch(rrc_ptr->ue_required_sibs)) { Error("Failed to initiate a serving cell configuration procedure\n"); return proc_outcome_t::error; } @@ -779,7 +777,7 @@ proc_outcome_t rrc::process_pcch_proc::step() if (rrc_ptr->serv_cell_cfg.run()) { return proc_outcome_t::yield; } - serving_cell_config_proc ret = rrc_ptr->serv_cell_cfg.pop(); + srslte::proc_result_t ret = rrc_ptr->serv_cell_cfg.pop(); if (ret.is_success()) { Info("All SIBs of serving cell obtained successfully\n"); return proc_outcome_t::success; @@ -807,10 +805,10 @@ proc_outcome_t rrc::process_pcch_proc::trigger_event(paging_complete e) * Go Idle procedure *************************************/ -proc_outcome_t rrc::go_idle_proc::init(rrc* rrc_) -{ - rrc_ptr = rrc_; +rrc::go_idle_proc::go_idle_proc(srsue::rrc* rrc_) : rrc_ptr(rrc_) {} +proc_outcome_t rrc::go_idle_proc::init() +{ rlc_flush_counter = 0; Info("Starting...\n"); return proc_outcome_t::yield; @@ -838,12 +836,13 @@ proc_outcome_t rrc::go_idle_proc::step() * Cell Reselection procedure *************************************/ -proc_outcome_t rrc::cell_reselection_proc::init(srsue::rrc* rrc_) -{ - rrc_ptr = rrc_; +rrc::cell_reselection_proc::cell_reselection_proc(srsue::rrc* rrc_) + : rrc_ptr(rrc_) {} +proc_outcome_t rrc::cell_reselection_proc::init() +{ Info("Cell Reselection - Starting...\n"); - if (not rrc_ptr->cell_selector.launch(rrc_ptr)) { + if (not rrc_ptr->cell_selector.launch()) { Error("Failed to initiate a Cell Selection procedure...\n"); return proc_outcome_t::error; } @@ -856,13 +855,13 @@ proc_outcome_t rrc::cell_reselection_proc::step() if (rrc_ptr->cell_selector.run()) { return srslte::proc_outcome_t::yield; } - cell_selection_proc ret = rrc_ptr->cell_selector.pop(); + srslte::proc_result_t ret = rrc_ptr->cell_selector.pop(); if (ret.is_error()) { Error("Cell Reselection - Error while selecting a cell\n"); return srslte::proc_outcome_t::error; } - switch (ret.get_cs_result()) { + switch (ret.proc()->get_cs_result()) { case cs_result_t::changed_cell: // New cell has been selected, start receiving PCCH rrc_ptr->mac->pcch_start_rx(); diff --git a/srsue/src/stack/upper/nas.cc b/srsue/src/stack/upper/nas.cc index 0c952d7e2..f386a3d3d 100644 --- a/srsue/src/stack/upper/nas.cc +++ b/srsue/src/stack/upper/nas.cc @@ -44,10 +44,8 @@ namespace srsue { using srslte::proc_outcome_t; -proc_outcome_t nas::plmn_search_proc::init(nas* nas_ptr_) +proc_outcome_t nas::plmn_search_proc::init() { - nas_ptr = nas_ptr_; - // start RRC state = state_t::plmn_search; if (not nas_ptr->rrc->plmn_search()) { @@ -65,7 +63,7 @@ proc_outcome_t nas::plmn_search_proc::step() if (nas_ptr->rrc_connector.run()) { return proc_outcome_t::yield; } - rrc_connect_proc ret = nas_ptr->rrc_connector.pop(); + proc_result_t ret = nas_ptr->rrc_connector.pop(); if (ret.is_success()) { return proc_outcome_t::success; } @@ -116,7 +114,7 @@ proc_outcome_t nas::plmn_search_proc::trigger_event(const plmn_search_complete_t nas_ptr->rrc->plmn_select(nas_ptr->current_plmn); - if (not nas_ptr->rrc_connector.launch(nas_ptr, srslte::establishment_cause_t ::mo_data, nullptr)) { + if (not nas_ptr->rrc_connector.launch(srslte::establishment_cause_t::mo_data, nullptr)) { ProcError("Unable to initiate RRC connection.\n"); return proc_outcome_t::error; } @@ -125,11 +123,8 @@ proc_outcome_t nas::plmn_search_proc::trigger_event(const plmn_search_complete_t return proc_outcome_t::yield; } -proc_outcome_t -nas::rrc_connect_proc::init(nas* nas_ptr_, srslte::establishment_cause_t cause_, srslte::unique_byte_buffer_t pdu) +proc_outcome_t nas::rrc_connect_proc::init(srslte::establishment_cause_t cause_, srslte::unique_byte_buffer_t pdu) { - nas_ptr = nas_ptr_; - if (nas_ptr->rrc->is_connected()) { ProcInfo("Stopping. Reason: Already connected\n"); return proc_outcome_t::success; @@ -173,8 +168,8 @@ proc_outcome_t nas::rrc_connect_proc::step() if (nas_ptr->conn_req_proc.run()) { return proc_outcome_t::yield; } - query_proc_t ret = nas_ptr->conn_req_proc.pop(); - if (not ret.result()) { + proc_result_t> ret = nas_ptr->conn_req_proc.pop(); + if (ret.is_error()) { ProcError("Could not establish RRC connection\n"); return proc_outcome_t::error; } @@ -195,7 +190,7 @@ proc_outcome_t nas::rrc_connect_proc::step() } else if (nas_ptr->state == EMM_STATE_DEREGISTERED) { ProcError("Timeout or received attach reject while trying to attach\n"); nas_ptr->nas_log->console("Failed to Attach\n"); - } else if (!nas_ptr->rrc->is_connected()) { + } else if (!nas_ptr->rrc->is_connected()){ ProcError("Was disconnected while attaching\n"); } else { ProcError("Timed out while trying to attach\n"); @@ -213,15 +208,17 @@ proc_outcome_t nas::rrc_connect_proc::step() nas::nas(srslte::log* log_, srslte::timers* timers_) : nas_log(log_), pool(byte_buffer_pool::get_instance()), + plmn_searcher(this), + rrc_connector(this), timers(timers_) { } void nas::init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interface_nas* gw_, const nas_args_t& cfg_) { - usim = usim_; - rrc = rrc_; - gw = gw_; + usim = usim_; + rrc = rrc_; + gw = gw_; state = EMM_STATE_DEREGISTERED; if (!usim->get_home_plmn_id(&home_plmn)) { @@ -342,7 +339,7 @@ void nas::start_attach_request(srslte::proc_state_t* result, srslte::establishme // Search PLMN is not selected if (!plmn_is_selected) { nas_log->info("No PLMN selected. Starting PLMN Search...\n"); - if (not plmn_searcher.launch(this)) { + if (not plmn_searcher.launch()) { if (result != nullptr) { *result = proc_state_t::error; } @@ -352,7 +349,7 @@ void nas::start_attach_request(srslte::proc_state_t* result, srslte::establishme if (plmn_searcher.run()) { return proc_outcome_t::yield; } - plmn_search_proc p = plmn_searcher.pop(); + proc_result_t p = plmn_searcher.pop(); nas_log->info("Attach Request from PLMN Search %s\n", p.is_success() ? "finished successfully" : "failed"); if (result != nullptr) { *result = p.is_success() ? proc_state_t::success : proc_state_t::error; @@ -382,7 +379,7 @@ void nas::start_attach_request(srslte::proc_state_t* result, srslte::establishme } } else { nas_log->info("NAS is already registered but RRC disconnected. Connecting now...\n"); - if (not rrc_connector.launch(this, cause_, nullptr)) { + if (not rrc_connector.launch(cause_, nullptr)) { nas_log->error("Cannot initiate concurrent rrc connection procedures\n"); if (result != nullptr) { *result = proc_state_t::error; @@ -393,7 +390,7 @@ void nas::start_attach_request(srslte::proc_state_t* result, srslte::establishme if (rrc_connector.run()) { return proc_outcome_t::yield; } - rrc_connect_proc proc = rrc_connector.pop(); + proc_result_t proc = rrc_connector.pop(); if (proc.is_success()) { nas_log->info("NAS attached successfully.\n"); } else { @@ -465,7 +462,7 @@ void nas::paging(s_tmsi_t* ue_identity) nas_log->error("Cannot initiate concurrent RRC connection establishment procedures\n"); return; } - if (not rrc_connector.launch(this, srslte::establishment_cause_t ::mt_access, nullptr)) { + if (not rrc_connector.launch(srslte::establishment_cause_t::mt_access, nullptr)) { nas_log->error("Could not launch RRC Connect()\n"); return; } @@ -1335,8 +1332,8 @@ void nas::parse_service_reject(uint32_t lcid, unique_byte_buffer_t pdu) have_ctxt = false; have_guti = false; - // Send attach request after receiving service reject - pdu->clear(); + // Send attach request after receiving service reject + pdu->clear(); gen_attach_request(pdu.get()); rrc->write_sdu(std::move(pdu)); } @@ -1793,7 +1790,7 @@ void nas::send_detach_request(bool switch_off) if (rrc->is_connected()) { rrc->write_sdu(std::move(pdu)); } else { - if (not rrc_connector.launch(this, establishment_cause_t::mo_sig, std::move(pdu))) { + if (not rrc_connector.launch(establishment_cause_t::mo_sig, std::move(pdu))) { nas_log->error("Failed to initiate RRC Connection Request\n"); } callbacks.defer_proc(rrc_connector);