made cell select non-blocking using background threads

master
Francisco Paisana 5 years ago committed by Andre Puschmann
parent 21f01f6140
commit 22f51bb30b

@ -28,8 +28,8 @@
#ifndef SRSLTE_UE_INTERFACES_H #ifndef SRSLTE_UE_INTERFACES_H
#define SRSLTE_UE_INTERFACES_H #define SRSLTE_UE_INTERFACES_H
#include <string>
#include <set> #include <set>
#include <string>
#include "rrc_interface_types.h" #include "rrc_interface_types.h"
#include "srslte/asn1/liblte_mme.h" #include "srslte/asn1/liblte_mme.h"
@ -611,7 +611,7 @@ public:
/* Cell search and selection procedures */ /* Cell search and selection procedures */
virtual cell_search_ret_t cell_search(phy_cell_t* cell) = 0; virtual cell_search_ret_t cell_search(phy_cell_t* cell) = 0;
virtual bool cell_select(phy_cell_t* cell = NULL) = 0; virtual bool cell_select(const phy_cell_t* cell = NULL) = 0;
virtual bool cell_is_camping() = 0; virtual bool cell_is_camping() = 0;
virtual void reset() = 0; virtual void reset() = 0;
@ -644,6 +644,7 @@ class stack_interface_rrc
{ {
public: public:
virtual void start_cell_search() = 0; virtual void start_cell_search() = 0;
virtual void start_cell_select(const phy_interface_rrc_lte::phy_cell_t* cell) = 0;
}; };
// Combined interface for PHY to access stack (MAC and RRC) // Combined interface for PHY to access stack (MAC and RRC)

@ -70,7 +70,7 @@ public:
/********** RRC INTERFACE ********************/ /********** RRC INTERFACE ********************/
void reset() final; void reset() final;
cell_search_ret_t cell_search(phy_cell_t* cell) final; cell_search_ret_t cell_search(phy_cell_t* cell) final;
bool cell_select(phy_cell_t* cell) final; bool cell_select(const phy_cell_t* cell) final;
void set_cells_to_meas(uint32_t earfcn, const std::set<uint32_t>& pci) final; void set_cells_to_meas(uint32_t earfcn, const std::set<uint32_t>& pci) final;
void meas_stop() final; void meas_stop() final;

@ -66,7 +66,7 @@ public:
// RRC interface for controling the SYNC state // 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); phy_interface_rrc_lte::cell_search_ret_t cell_search(phy_interface_rrc_lte::phy_cell_t* cell);
bool cell_select(phy_interface_rrc_lte::phy_cell_t* cell); bool cell_select(const phy_interface_rrc_lte::phy_cell_t* cell);
bool cell_is_camping(); bool cell_is_camping();
// RRC interface for controlling the neighbour cell measurement // RRC interface for controlling the neighbour cell measurement

@ -356,6 +356,7 @@ public:
// STACK interface // STACK interface
void cell_search_completed(const phy_interface_rrc_lte::cell_search_ret_t& cs_ret, 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); const phy_interface_rrc_lte::phy_cell_t& found_cell);
void cell_select_completed(bool cs_ret);
protected: protected:
// Moved to protected to be accessible by unit tests // Moved to protected to be accessible by unit tests

@ -29,6 +29,20 @@
namespace srsue { namespace srsue {
/********************************
* Events
*******************************/
// background workers use this event to signal the result of a cell select phy procedure
struct cell_select_event_t {
cell_select_event_t(bool c_) : cs_ret(c_) {}
bool cs_ret;
};
/********************************
* Procedures
*******************************/
class rrc::cell_search_proc class rrc::cell_search_proc
{ {
public: public:
@ -36,13 +50,15 @@ public:
phy_interface_rrc_lte::cell_search_ret_t cs_ret; phy_interface_rrc_lte::cell_search_ret_t cs_ret;
phy_interface_rrc_lte::phy_cell_t found_cell; phy_interface_rrc_lte::phy_cell_t found_cell;
}; };
enum class state_t { phy_cell_search, si_acquire, wait_measurement }; enum class state_t { phy_cell_search, si_acquire, wait_measurement, phy_cell_select };
explicit cell_search_proc(rrc* parent_); explicit cell_search_proc(rrc* parent_);
srslte::proc_outcome_t init(); srslte::proc_outcome_t init();
srslte::proc_outcome_t step(); srslte::proc_outcome_t step();
srslte::proc_outcome_t step_si_acquire();
srslte::proc_outcome_t react(const cell_search_event_t& event); srslte::proc_outcome_t react(const cell_search_event_t& event);
srslte::proc_outcome_t check_sib(); srslte::proc_outcome_t react(const cell_select_event_t& event);
srslte::proc_outcome_t step_wait_measurement();
phy_interface_rrc_lte::cell_search_ret_t get_result() const { return search_result.cs_ret; } phy_interface_rrc_lte::cell_search_ret_t get_result() const { return search_result.cs_ret; }
static const char* name() { return "Cell Search"; } static const char* name() { return "Cell Search"; }
@ -116,9 +132,12 @@ public:
void then(const srslte::proc_result_t<cs_result_t>& proc_result) const; void then(const srslte::proc_result_t<cs_result_t>& proc_result) const;
cs_result_t get_result() const { return cs_result; } cs_result_t get_result() const { return cs_result; }
static const char* name() { return "Cell Selection"; } static const char* name() { return "Cell Selection"; }
srslte::proc_outcome_t react(const cell_select_event_t& event);
private: private:
srslte::proc_outcome_t step_cell_selection(); srslte::proc_outcome_t start_cell_selection();
srslte::proc_outcome_t step_cell_selection(const cell_select_event_t& event);
srslte::proc_outcome_t step_serv_cell_camp(const cell_select_event_t& event);
srslte::proc_outcome_t step_wait_in_sync(); srslte::proc_outcome_t step_wait_in_sync();
srslte::proc_outcome_t step_cell_search(); srslte::proc_outcome_t step_cell_search();
srslte::proc_outcome_t step_cell_config(); srslte::proc_outcome_t step_cell_config();
@ -127,7 +146,7 @@ private:
rrc* rrc_ptr; rrc* rrc_ptr;
// state variables // state variables
enum class search_state_t { cell_selection, wait_in_sync, cell_config, cell_search }; enum class search_state_t { cell_selection, serv_cell_camp, wait_in_sync, cell_config, cell_search };
cs_result_t cs_result; cs_result_t cs_result;
search_state_t state; search_state_t state;
uint32_t neigh_index; uint32_t neigh_index;

@ -120,6 +120,7 @@ public:
// Interface for RRC // Interface for RRC
void start_cell_search() final; void start_cell_search() final;
void start_cell_select(const phy_interface_rrc_lte::phy_cell_t* cell) final;
private: private:
void run_thread() final; void run_thread() final;

@ -325,7 +325,7 @@ void phy::meas_stop()
sfsync.meas_stop(); sfsync.meas_stop();
} }
bool phy::cell_select(phy_cell_t* cell) bool phy::cell_select(const phy_cell_t* cell)
{ {
return sfsync.cell_select(cell); return sfsync.cell_select(cell);
} }

@ -264,7 +264,7 @@ phy_interface_rrc_lte::cell_search_ret_t sync::cell_search(phy_interface_rrc_lte
/* Cell select synchronizes to a new cell (e.g. during HO or during cell reselection on IDLE) or /* 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 * re-synchronizes with the current cell if cell argument is NULL
*/ */
bool sync::cell_select(phy_interface_rrc_lte::phy_cell_t* new_cell) bool sync::cell_select(const phy_interface_rrc_lte::phy_cell_t* new_cell)
{ {
std::unique_lock<std::mutex> ul(rrc_mutex); std::unique_lock<std::mutex> ul(rrc_mutex);
@ -272,7 +272,7 @@ bool sync::cell_select(phy_interface_rrc_lte::phy_cell_t* new_cell)
int cnt = 0; int cnt = 0;
// Move state to IDLE // Move state to IDLE
if (!new_cell) { if (new_cell == nullptr) {
Info("Cell Select: Starting cell resynchronization\n"); Info("Cell Select: Starting cell resynchronization\n");
} else { } else {
if (!srslte_cellid_isvalid(new_cell->pci)) { if (!srslte_cellid_isvalid(new_cell->pci)) {
@ -298,7 +298,7 @@ bool sync::cell_select(phy_interface_rrc_lte::phy_cell_t* new_cell)
srslte_ue_sync_reset(&ue_sync); srslte_ue_sync_reset(&ue_sync);
/* Reconfigure cell if necessary */ /* Reconfigure cell if necessary */
if (new_cell) { if (new_cell != nullptr) {
cell.id = new_cell->pci; cell.id = new_cell->pci;
if (!set_cell()) { if (!set_cell()) {
Error("Cell Select: Reconfiguring cell\n"); Error("Cell Select: Reconfiguring cell\n");

@ -1385,6 +1385,13 @@ void rrc::cell_search_completed(const phy_interface_rrc_lte::cell_search_ret_t&
cell_searcher.trigger(cell_search_proc::cell_search_event_t{cs_ret, found_cell}); cell_searcher.trigger(cell_search_proc::cell_search_event_t{cs_ret, found_cell});
} }
void rrc::cell_select_completed(bool cs_ret)
{
cell_select_event_t ev{cs_ret};
cell_searcher.trigger(ev);
cell_selector.trigger(ev);
}
/******************************************************************************* /*******************************************************************************
* *
* Interface from RRC measurements class * Interface from RRC measurements class

@ -49,10 +49,21 @@ proc_outcome_t rrc::cell_search_proc::init()
/* Implements the SI acquisition procedure. Configures MAC/PHY scheduling to retrieve SI messages.*/ /* Implements the SI acquisition procedure. Configures MAC/PHY scheduling to retrieve SI messages.*/
proc_outcome_t rrc::cell_search_proc::step() proc_outcome_t rrc::cell_search_proc::step()
{ {
if (state == state_t::phy_cell_search) { switch (state) {
// Waits for cell search to complete case state_t::phy_cell_search:
case state_t::phy_cell_select:
// Waits for cell select/search to complete
return proc_outcome_t::yield;
case state_t::si_acquire:
return step_si_acquire();
case state_t::wait_measurement:
return step_wait_measurement();
}
return proc_outcome_t::yield; return proc_outcome_t::yield;
} else if (state == state_t::si_acquire) { }
proc_outcome_t rrc::cell_search_proc::step_si_acquire()
{
if (rrc_ptr->si_acquirer.run()) { if (rrc_ptr->si_acquirer.run()) {
return proc_outcome_t::yield; return proc_outcome_t::yield;
} }
@ -63,10 +74,6 @@ proc_outcome_t rrc::cell_search_proc::step()
} }
Info("Completed successfully\n"); Info("Completed successfully\n");
return proc_outcome_t::success; return proc_outcome_t::success;
} else if (state == state_t::wait_measurement && std::isnormal(rrc_ptr->serving_cell->get_rsrp())) {
return check_sib();
}
return proc_outcome_t::yield;
} }
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_interface_rrc_lte::phy_cell_t& new_cell)
@ -82,27 +89,17 @@ proc_outcome_t rrc::cell_search_proc::handle_cell_found(const phy_interface_rrc_
rrc_ptr->set_serving_cell(new_cell, false); rrc_ptr->set_serving_cell(new_cell, false);
// set new serving cell in PHY // set new serving cell in PHY
if (not rrc_ptr->phy->cell_select(&rrc_ptr->serving_cell->phy_cell)) { state = state_t::phy_cell_select;
Error("Couldn't select new serving cell\n"); rrc_ptr->stack->start_cell_select(&rrc_ptr->serving_cell->phy_cell);
return proc_outcome_t::error; return proc_outcome_t::yield;
}
if (not rrc_ptr->phy->cell_is_camping()) {
Warning("Could not camp on found cell.\n");
return proc_outcome_t::error;
} }
proc_outcome_t rrc::cell_search_proc::step_wait_measurement()
{
if (not std::isnormal(rrc_ptr->serving_cell->get_rsrp())) { if (not std::isnormal(rrc_ptr->serving_cell->get_rsrp())) {
Info("No valid measurement found for the serving cell. Wait for valid measurement...\n");
state = state_t::wait_measurement;
return proc_outcome_t::yield; return proc_outcome_t::yield;
} }
return check_sib();
}
proc_outcome_t rrc::cell_search_proc::check_sib()
{
if (rrc_ptr->serving_cell->has_sib1()) { if (rrc_ptr->serving_cell->has_sib1()) {
Info("Cell has SIB1\n"); Info("Cell has SIB1\n");
// What do we do???? // What do we do????
@ -119,6 +116,30 @@ proc_outcome_t rrc::cell_search_proc::check_sib()
return step(); return step();
} }
proc_outcome_t rrc::cell_search_proc::react(const cell_select_event_t& event)
{
if (state != state_t::phy_cell_select) {
Warning("Received unexpected cell search result\n");
return proc_outcome_t::yield;
}
if (not event.cs_ret) {
Error("Couldn't select new serving cell\n");
return proc_outcome_t::error;
}
if (not rrc_ptr->phy->cell_is_camping()) {
Warning("Could not camp on found cell.\n");
return proc_outcome_t::error;
}
if (not std::isnormal(rrc_ptr->serving_cell->get_rsrp())) {
Info("No valid measurement found for the serving cell. Wait for valid measurement...\n");
}
state = state_t::wait_measurement;
return proc_outcome_t::yield;
}
proc_outcome_t rrc::cell_search_proc::react(const cell_search_event_t& event) proc_outcome_t rrc::cell_search_proc::react(const cell_search_event_t& event)
{ {
if (state != state_t::phy_cell_search) { if (state != state_t::phy_cell_search) {
@ -357,7 +378,25 @@ proc_outcome_t rrc::cell_selection_proc::init()
return step(); return step();
} }
proc_outcome_t rrc::cell_selection_proc::step_cell_selection() proc_outcome_t rrc::cell_selection_proc::react(const cell_select_event_t& event)
{
switch (state) {
case search_state_t::cell_selection: {
return step_cell_selection(event);
}
case search_state_t::serv_cell_camp: {
return step_serv_cell_camp(event);
}
case search_state_t::cell_search:
// cell search may call cell_select
break;
default:
Warning("Unexpected cell selection event received\n");
}
return proc_outcome_t::yield;
}
proc_outcome_t rrc::cell_selection_proc::start_cell_selection()
{ {
Info("Current serving cell: %s\n", rrc_ptr->serving_cell->to_string().c_str()); Info("Current serving cell: %s\n", rrc_ptr->serving_cell->to_string().c_str());
@ -377,32 +416,20 @@ proc_outcome_t rrc::cell_selection_proc::step_cell_selection()
Info("Selected cell: %s\n", rrc_ptr->serving_cell->to_string().c_str()); Info("Selected cell: %s\n", rrc_ptr->serving_cell->to_string().c_str());
/* BLOCKING CALL */ /* BLOCKING CALL */
if (rrc_ptr->phy->cell_select(&rrc_ptr->serving_cell->phy_cell)) { state = search_state_t::cell_selection;
Info("Wait PHY to be in-synch\n"); rrc_ptr->stack->start_cell_select(&rrc_ptr->serving_cell->phy_cell);
state = search_state_t::wait_in_sync; return proc_outcome_t::yield;
rrc_ptr->phy_sync_state = phy_unknown_sync;
return step();
} else {
rrc_ptr->phy_sync_state = phy_unknown_sync;
Error("Could not camp on serving cell.\n");
discard_serving = true;
// Continue to next neighbour cell
}
} }
} }
// Iteration over neighbor cells is over.
if (rrc_ptr->phy_sync_state == phy_in_sync && rrc_ptr->cell_selection_criteria(rrc_ptr->serving_cell->get_rsrp())) { if (rrc_ptr->phy_sync_state == phy_in_sync && rrc_ptr->cell_selection_criteria(rrc_ptr->serving_cell->get_rsrp())) {
if (not rrc_ptr->phy->cell_is_camping()) { if (not rrc_ptr->phy->cell_is_camping()) {
Info("Serving cell %s is in-sync but not camping. Selecting it...\n", rrc_ptr->serving_cell->to_string().c_str()); Info("Serving cell %s is in-sync but not camping. Selecting it...\n", rrc_ptr->serving_cell->to_string().c_str());
/* BLOCKING CALL */ state = search_state_t::serv_cell_camp;
if (rrc_ptr->phy->cell_select(&rrc_ptr->serving_cell->phy_cell)) { rrc_ptr->stack->start_cell_select(&rrc_ptr->serving_cell->phy_cell);
Info("Selected serving cell OK.\n"); return proc_outcome_t::yield;
} else {
rrc_ptr->phy_sync_state = phy_unknown_sync;
rrc_ptr->serving_cell->set_rsrp(-INFINITY);
Error("Could not camp on serving cell.\n");
return proc_outcome_t::error;
}
} }
cs_result = cs_result_t::same_cell; cs_result = cs_result_t::same_cell;
return proc_outcome_t::success; return proc_outcome_t::success;
@ -417,22 +444,54 @@ proc_outcome_t rrc::cell_selection_proc::step_cell_selection()
return step(); return step();
} }
proc_outcome_t rrc::cell_selection_proc::step_cell_selection(const cell_select_event_t& event)
{
rrc_ptr->phy_sync_state = phy_unknown_sync;
if (event.cs_ret) {
// successful selection
Info("Wait PHY to be in-synch\n");
state = search_state_t::wait_in_sync;
return step();
}
Error("Could not camp on serving cell.\n");
discard_serving = true;
// Continue to next neighbour cell
++neigh_index;
return start_cell_selection();
}
srslte::proc_outcome_t rrc::cell_selection_proc::step_serv_cell_camp(const cell_select_event_t& event)
{
// if we are now camping, the proc was successful
if (event.cs_ret) {
Info("Selected serving cell OK.\n");
cs_result = cs_result_t::same_cell;
} else {
rrc_ptr->phy_sync_state = phy_unknown_sync;
rrc_ptr->serving_cell->set_rsrp(-INFINITY);
Error("Could not camp on serving cell.\n");
}
return event.cs_ret ? proc_outcome_t::success : proc_outcome_t::error;
}
proc_outcome_t rrc::cell_selection_proc::step_wait_in_sync() proc_outcome_t rrc::cell_selection_proc::step_wait_in_sync()
{ {
if (rrc_ptr->phy_sync_state == phy_in_sync) { if (rrc_ptr->phy_sync_state == phy_in_sync) {
if (rrc_ptr->cell_selection_criteria(rrc_ptr->serving_cell->get_rsrp())) { if (rrc_ptr->cell_selection_criteria(rrc_ptr->serving_cell->get_rsrp())) {
Info("PHY is in SYNC and cell selection passed\n"); Info("PHY is in SYNC and cell selection passed\n");
serv_cell_cfg_fut = rrc_ptr->serv_cell_cfg.get_future();
if (not rrc_ptr->serv_cell_cfg.launch(&serv_cell_cfg_fut, rrc_ptr->ue_required_sibs)) { if (not rrc_ptr->serv_cell_cfg.launch(&serv_cell_cfg_fut, rrc_ptr->ue_required_sibs)) {
return proc_outcome_t::error; return proc_outcome_t::error;
} }
state = search_state_t::cell_config; state = search_state_t::cell_config;
} else { } else {
Info("PHY is in SYNC but cell selection did not pass. Go back to select step.\n"); Info("PHY is in SYNC but cell selection did not pass. Go back to select step.\n");
neigh_index = 0;
cs_result = cs_result_t::no_cell; cs_result = cs_result_t::no_cell;
state = search_state_t::cell_selection; neigh_index = 0; // TODO: go back to the start?
discard_serving = true; // Discard this cell discard_serving = true; // Discard this cell
return start_cell_selection();
} }
} }
return proc_outcome_t::yield; return proc_outcome_t::yield;
@ -467,16 +526,19 @@ proc_outcome_t rrc::cell_selection_proc::step_cell_config()
} }
Error("While configuring serving cell\n"); Error("While configuring serving cell\n");
// resume cell selection // resume cell selection
state = search_state_t::cell_selection;
++neigh_index; ++neigh_index;
return step(); return start_cell_selection();
} }
proc_outcome_t rrc::cell_selection_proc::step() proc_outcome_t rrc::cell_selection_proc::step()
{ {
switch (state) { switch (state) {
case search_state_t::cell_selection: case search_state_t::cell_selection:
return step_cell_selection(); // this state waits for phy event
return proc_outcome_t::yield;
case search_state_t::serv_cell_camp:
// this state waits for phy event
return proc_outcome_t::yield;
case search_state_t::wait_in_sync: case search_state_t::wait_in_sync:
return step_wait_in_sync(); return step_wait_in_sync();
case search_state_t::cell_config: case search_state_t::cell_config:

@ -319,7 +319,6 @@ void ue_stack_lte::start_prach_configuration()
}); });
} }
/******************** /********************
* RRC Interface * RRC Interface
*******************/ *******************/
@ -334,4 +333,13 @@ void ue_stack_lte::start_cell_search()
}); });
} }
void ue_stack_lte::start_cell_select(const phy_interface_rrc_lte::phy_cell_t* phy_cell)
{
background_tasks.push_task([this, phy_cell](uint32_t worker_id) {
bool ret = phy->cell_select(phy_cell);
// notify back RRC
pending_tasks.push(background_queue_id, [this, ret]() { rrc.cell_select_completed(ret); });
});
}
} // namespace srsue } // namespace srsue

@ -87,7 +87,7 @@ public:
// Cell search and selection procedures // Cell search and selection procedures
cell_search_ret_t cell_search(phy_cell_t* found_cell); cell_search_ret_t cell_search(phy_cell_t* found_cell);
bool cell_select(phy_cell_t* cell); bool cell_select(const phy_cell_t* cell) override;
bool cell_is_camping(); bool cell_is_camping();
void reset(); void reset();

@ -153,7 +153,7 @@ phy_interface_rrc_lte::cell_search_ret_t lte_ttcn3_phy::cell_search(phy_cell_t*
return ret; return ret;
}; };
bool lte_ttcn3_phy::cell_select(phy_cell_t* rrc_cell) bool lte_ttcn3_phy::cell_select(const phy_cell_t* rrc_cell)
{ {
// try to find RRC cell in current cell map // try to find RRC cell in current cell map
for (auto& cell : cells) { for (auto& cell : cells) {

@ -54,7 +54,7 @@ public:
void set_config_mbsfn_mcch(const srslte::mcch_msg_t& mcch) override {} void set_config_mbsfn_mcch(const srslte::mcch_msg_t& mcch) override {}
cell_search_ret_t cell_search(phy_cell_t* cell) override { return {}; } cell_search_ret_t cell_search(phy_cell_t* cell) override { return {}; }
bool cell_is_camping() override { return false; } bool cell_is_camping() override { return false; }
bool cell_select(phy_cell_t* cell = nullptr) override { return false; } bool cell_select(const phy_cell_t* cell = nullptr) override { return false; }
void reset() override {} void reset() override {}
void enable_pregen_signals(bool enable) override {} void enable_pregen_signals(bool enable) override {}

Loading…
Cancel
Save