made cell select non-blocking using background threads

This commit is contained in:
Francisco Paisana 2020-02-17 15:29:06 +00:00 committed by Andre Puschmann
parent 21f01f6140
commit 22f51bb30b
14 changed files with 190 additions and 91 deletions

View File

@ -28,8 +28,8 @@
#ifndef SRSLTE_UE_INTERFACES_H
#define SRSLTE_UE_INTERFACES_H
#include <string>
#include <set>
#include <string>
#include "rrc_interface_types.h"
#include "srslte/asn1/liblte_mme.h"
@ -527,10 +527,10 @@ typedef struct {
bool pregenerate_signals = false;
float force_ul_amplitude = 0.0f;
float in_sync_rsrp_dbm_th = -130.0f;
float in_sync_snr_db_th = 1.0f;
uint32_t nof_in_sync_events = 10;
uint32_t nof_out_of_sync_events = 20;
float in_sync_rsrp_dbm_th = -130.0f;
float in_sync_snr_db_th = 1.0f;
uint32_t nof_in_sync_events = 10;
uint32_t nof_out_of_sync_events = 20;
srslte::channel::args_t dl_channel_args;
srslte::channel::args_t ul_channel_args;
@ -610,9 +610,9 @@ public:
} phy_cell_t;
/* Cell search and selection procedures */
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_is_camping() = 0;
virtual cell_search_ret_t cell_search(phy_cell_t* cell) = 0;
virtual bool cell_select(const phy_cell_t* cell = NULL) = 0;
virtual bool cell_is_camping() = 0;
virtual void reset() = 0;
@ -643,7 +643,8 @@ public:
class stack_interface_rrc
{
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)

View File

@ -70,7 +70,7 @@ public:
/********** RRC INTERFACE ********************/
void reset() 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 meas_stop() final;

View File

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

View File

@ -356,6 +356,7 @@ public:
// 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);
protected:
// Moved to protected to be accessible by unit tests

View File

@ -29,6 +29,20 @@
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
{
public:
@ -36,13 +50,15 @@ public:
phy_interface_rrc_lte::cell_search_ret_t cs_ret;
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_);
srslte::proc_outcome_t init();
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 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; }
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;
cs_result_t get_result() const { return cs_result; }
static const char* name() { return "Cell Selection"; }
srslte::proc_outcome_t react(const cell_select_event_t& event);
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_cell_search();
srslte::proc_outcome_t step_cell_config();
@ -127,7 +146,7 @@ private:
rrc* rrc_ptr;
// 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;
search_state_t state;
uint32_t neigh_index;
@ -247,10 +266,10 @@ public:
private:
enum class state_t { cell_reselection, cell_configuration } state;
rrc* rrc_ptr = nullptr;
asn1::rrc::reest_cause_e reest_cause = asn1::rrc::reest_cause_e::nulltype;
uint16_t reest_rnti = 0;
uint16_t reest_source_pci = 0;
rrc* rrc_ptr = nullptr;
asn1::rrc::reest_cause_e reest_cause = asn1::rrc::reest_cause_e::nulltype;
uint16_t reest_rnti = 0;
uint16_t reest_source_pci = 0;
uint32_t reest_source_freq = 0;
srslte::proc_outcome_t step_cell_reselection();

View File

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

View File

@ -325,7 +325,7 @@ void phy::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);
}

View File

@ -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
* 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);
@ -272,7 +272,7 @@ bool sync::cell_select(phy_interface_rrc_lte::phy_cell_t* new_cell)
int cnt = 0;
// Move state to IDLE
if (!new_cell) {
if (new_cell == nullptr) {
Info("Cell Select: Starting cell resynchronization\n");
} else {
if (!srslte_cellid_isvalid(new_cell->pci)) {
@ -298,12 +298,12 @@ bool sync::cell_select(phy_interface_rrc_lte::phy_cell_t* new_cell)
srslte_ue_sync_reset(&ue_sync);
/* Reconfigure cell if necessary */
if (new_cell) {
cell.id = new_cell->pci;
if (!set_cell()) {
Error("Cell Select: Reconfiguring cell\n");
return ret;
}
if (new_cell != nullptr) {
cell.id = new_cell->pci;
if (!set_cell()) {
Error("Cell Select: Reconfiguring cell\n");
return ret;
}
/* Select new frequency if necessary */
if ((int)new_cell->earfcn != current_earfcn) {

View File

@ -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});
}
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

View File

@ -49,26 +49,33 @@ proc_outcome_t rrc::cell_search_proc::init()
/* Implements the SI acquisition procedure. Configures MAC/PHY scheduling to retrieve SI messages.*/
proc_outcome_t rrc::cell_search_proc::step()
{
if (state == state_t::phy_cell_search) {
// Waits for cell search to complete
return proc_outcome_t::yield;
} else if (state == state_t::si_acquire) {
if (rrc_ptr->si_acquirer.run()) {
switch (state) {
case state_t::phy_cell_search:
case state_t::phy_cell_select:
// Waits for cell select/search to complete
return proc_outcome_t::yield;
}
// SI Acquire has completed
if (si_acquire_fut.is_error()) {
Error("Failed to trigger SI acquire for SIB0\n");
return proc_outcome_t::error;
}
Info("Completed successfully\n");
return proc_outcome_t::success;
} else if (state == state_t::wait_measurement && std::isnormal(rrc_ptr->serving_cell->get_rsrp())) {
return check_sib();
case state_t::si_acquire:
return step_si_acquire();
case state_t::wait_measurement:
return step_wait_measurement();
}
return proc_outcome_t::yield;
}
proc_outcome_t rrc::cell_search_proc::step_si_acquire()
{
if (rrc_ptr->si_acquirer.run()) {
return proc_outcome_t::yield;
}
// SI Acquire has completed
if (si_acquire_fut.is_error()) {
Error("Failed to trigger SI acquire for SIB0\n");
return proc_outcome_t::error;
}
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)
{
Info("Cell found in this frequency. Setting new serving cell...\n");
@ -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);
// set new serving cell in PHY
if (not rrc_ptr->phy->cell_select(&rrc_ptr->serving_cell->phy_cell)) {
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;
}
state = state_t::phy_cell_select;
rrc_ptr->stack->start_cell_select(&rrc_ptr->serving_cell->phy_cell);
return proc_outcome_t::yield;
}
proc_outcome_t rrc::cell_search_proc::step_wait_measurement()
{
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 check_sib();
}
proc_outcome_t rrc::cell_search_proc::check_sib()
{
if (rrc_ptr->serving_cell->has_sib1()) {
Info("Cell has SIB1\n");
// What do we do????
@ -119,6 +116,30 @@ proc_outcome_t rrc::cell_search_proc::check_sib()
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)
{
if (state != state_t::phy_cell_search) {
@ -357,7 +378,25 @@ proc_outcome_t rrc::cell_selection_proc::init()
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());
@ -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());
/* BLOCKING CALL */
if (rrc_ptr->phy->cell_select(&rrc_ptr->serving_cell->phy_cell)) {
Info("Wait PHY to be in-synch\n");
state = search_state_t::wait_in_sync;
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
}
state = search_state_t::cell_selection;
rrc_ptr->stack->start_cell_select(&rrc_ptr->serving_cell->phy_cell);
return proc_outcome_t::yield;
}
}
// 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 (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());
/* BLOCKING CALL */
if (rrc_ptr->phy->cell_select(&rrc_ptr->serving_cell->phy_cell)) {
Info("Selected serving cell OK.\n");
} 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;
}
state = search_state_t::serv_cell_camp;
rrc_ptr->stack->start_cell_select(&rrc_ptr->serving_cell->phy_cell);
return proc_outcome_t::yield;
}
cs_result = cs_result_t::same_cell;
return proc_outcome_t::success;
@ -417,22 +444,54 @@ proc_outcome_t rrc::cell_selection_proc::step_cell_selection()
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()
{
if (rrc_ptr->phy_sync_state == phy_in_sync) {
if (rrc_ptr->cell_selection_criteria(rrc_ptr->serving_cell->get_rsrp())) {
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)) {
return proc_outcome_t::error;
}
state = search_state_t::cell_config;
} else {
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;
state = search_state_t::cell_selection;
neigh_index = 0; // TODO: go back to the start?
discard_serving = true; // Discard this cell
return start_cell_selection();
}
}
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");
// resume cell selection
state = search_state_t::cell_selection;
++neigh_index;
return step();
return start_cell_selection();
}
proc_outcome_t rrc::cell_selection_proc::step()
{
switch (state) {
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:
return step_wait_in_sync();
case search_state_t::cell_config:
@ -654,7 +716,7 @@ proc_outcome_t rrc::connection_request_proc::step()
}
Info("Waiting for RRCConnectionSetup/Reject or expiry\n");
state = state_t::wait_t300;
state = state_t::wait_t300;
return step();
} else if (state == state_t::wait_t300) {

View File

@ -319,7 +319,6 @@ void ue_stack_lte::start_prach_configuration()
});
}
/********************
* 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

View File

@ -87,7 +87,7 @@ public:
// Cell search and selection procedures
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();
void reset();

View File

@ -153,7 +153,7 @@ phy_interface_rrc_lte::cell_search_ret_t lte_ttcn3_phy::cell_search(phy_cell_t*
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
for (auto& cell : cells) {

View File

@ -54,7 +54,7 @@ public:
void set_config_mbsfn_mcch(const srslte::mcch_msg_t& mcch) override {}
cell_search_ret_t cell_search(phy_cell_t* cell) override { return {}; }
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 enable_pregen_signals(bool enable) override {}