refactor reestablishment procedure to more closely follow TS.

master
Francisco Paisana 4 years ago
parent b2576b34b9
commit 73e21daeb2

@ -101,6 +101,7 @@ public:
explicit serving_cell_config_proc(rrc* parent_); explicit serving_cell_config_proc(rrc* parent_);
srslte::proc_outcome_t init(const std::vector<uint32_t>& required_sibs_); srslte::proc_outcome_t init(const std::vector<uint32_t>& required_sibs_);
srslte::proc_outcome_t step(); srslte::proc_outcome_t step();
void then(const srslte::proc_state_t& result);
static const char* name() { return "Serving Cell Configuration"; } static const char* name() { return "Serving Cell Configuration"; }
private: private:
@ -259,14 +260,20 @@ private:
class rrc::connection_reest_proc class rrc::connection_reest_proc
{ {
public: public:
struct t311_expiry {};
struct serv_cell_cfg_completed {};
explicit connection_reest_proc(rrc* rrc_); explicit connection_reest_proc(rrc* rrc_);
srslte::proc_outcome_t init(asn1::rrc::reest_cause_e cause); srslte::proc_outcome_t init(asn1::rrc::reest_cause_e cause);
srslte::proc_outcome_t step(); srslte::proc_outcome_t step() { return srslte::proc_outcome_t::yield; }
srslte::proc_outcome_t react(const t311_expiry& ev);
srslte::proc_outcome_t react(const cell_selection_proc::cell_selection_complete_ev& e);
srslte::proc_outcome_t react(const serv_cell_cfg_completed& result);
static const char* name() { return "Connection re-establishment"; } static const char* name() { return "Connection re-establishment"; }
uint32_t get_source_earfcn() const { return reest_source_freq; } uint32_t get_source_earfcn() const { return reest_source_freq; }
private: private:
enum class state_t { cell_reselection, cell_configuration } state; enum class state_t { wait_cell_selection, wait_cell_configuration, wait_reest_msg } state;
rrc* rrc_ptr = nullptr; rrc* rrc_ptr = nullptr;
asn1::rrc::reest_cause_e reest_cause = asn1::rrc::reest_cause_e::nulltype; asn1::rrc::reest_cause_e reest_cause = asn1::rrc::reest_cause_e::nulltype;
@ -274,9 +281,10 @@ private:
uint16_t reest_source_pci = 0; uint16_t reest_source_pci = 0;
uint32_t reest_source_freq = 0; uint32_t reest_source_freq = 0;
srslte::proc_outcome_t step_cell_reselection(); bool sibs_acquired() const;
srslte::proc_outcome_t step_cell_configuration(); bool passes_cell_criteria() const;
srslte::proc_outcome_t cell_criteria(); srslte::proc_outcome_t cell_criteria();
srslte::proc_outcome_t start_cell_selection();
}; };
class rrc::ho_proc class rrc::ho_proc

@ -657,11 +657,13 @@ void rrc::timer_expired(uint32_t timeout_id)
rrc_log->info("Timer T310 expired: Radio Link Failure\n"); rrc_log->info("Timer T310 expired: Radio Link Failure\n");
radio_link_failure_push_cmd(); radio_link_failure_push_cmd();
} else if (timeout_id == t311.id()) { } else if (timeout_id == t311.id()) {
rrc_log->console("Timer T311 expired: Going to RRC IDLE\n");
if (connection_reest.is_idle()) { if (connection_reest.is_idle()) {
rrc_log->info("Timer T311 expired: Going to RRC IDLE\n"); rrc_log->info("Timer T311 expired: Going to RRC IDLE\n");
start_go_idle(); start_go_idle();
} else { } else {
// Do nothing, this is handled by the procedure // Do nothing, this is handled by the procedure
connection_reest.trigger(connection_reest_proc::t311_expiry{});
} }
} else if (timeout_id == t301.id()) { } else if (timeout_id == t301.id()) {
if (state == RRC_STATE_IDLE) { if (state == RRC_STATE_IDLE) {

@ -444,6 +444,13 @@ proc_outcome_t rrc::serving_cell_config_proc::step()
return launch_sib_acquire(); return launch_sib_acquire();
} }
void rrc::serving_cell_config_proc::then(const srslte::proc_state_t& result)
{
if (rrc_ptr->connection_reest.is_busy()) {
rrc_ptr->connection_reest.trigger(connection_reest_proc::serv_cell_cfg_completed{});
}
}
/************************************** /**************************************
* Cell Selection Procedure * Cell Selection Procedure
*************************************/ *************************************/
@ -661,10 +668,14 @@ proc_outcome_t rrc::cell_selection_proc::step()
void rrc::cell_selection_proc::then(const srslte::proc_result_t<cs_result_t>& proc_result) const void rrc::cell_selection_proc::then(const srslte::proc_result_t<cs_result_t>& proc_result) const
{ {
// Inform Connection Request Procedure // Inform Connection Request Procedure
if (rrc_ptr->conn_req_proc.is_busy()) {
Info("Completed with %s. Informing proc %s\n", Info("Completed with %s. Informing proc %s\n",
proc_result.is_success() ? "success" : "failure", proc_result.is_success() ? "success" : "failure",
rrc_ptr->conn_req_proc.get()->name()); rrc_ptr->conn_req_proc.get()->name());
rrc_ptr->conn_req_proc.trigger(proc_result); rrc_ptr->conn_req_proc.trigger(proc_result);
} else if (rrc_ptr->connection_reest.is_busy()) {
rrc_ptr->connection_reest.trigger(proc_result);
}
} }
/************************************** /**************************************
@ -1133,161 +1144,100 @@ void rrc::cell_reselection_proc::then(const srslte::proc_state_t& result)
* RRC Connection Re-establishment procedure * RRC Connection Re-establishment procedure
*************************************/ *************************************/
rrc::connection_reest_proc::connection_reest_proc(srsue::rrc* rrc_) : rrc_ptr(rrc_), state(state_t::cell_reselection) {} rrc::connection_reest_proc::connection_reest_proc(srsue::rrc* rrc_) : rrc_ptr(rrc_), state(state_t::wait_cell_selection)
{}
proc_outcome_t rrc::connection_reest_proc::init(asn1::rrc::reest_cause_e cause) proc_outcome_t rrc::connection_reest_proc::init(asn1::rrc::reest_cause_e cause)
{ {
Info("Starting... Cause: %s\n",
cause == asn1::rrc::reest_cause_opts::recfg_fail
? "Reconfiguration failure"
: cause == asn1::rrc::reest_cause_opts::ho_fail ? "Handover failure" : "Other failure");
// Save Current RNTI before MAC Reset // Save Current RNTI before MAC Reset
mac_interface_rrc::ue_rnti_t uernti; mac_interface_rrc::ue_rnti_t uernti;
rrc_ptr->mac->get_rntis(&uernti); rrc_ptr->mac->get_rntis(&uernti);
// If security is activated, RRC connected and C-RNTI available // 5.3.7.1 - Conditions for Reestablishment procedure
if (rrc_ptr->security_is_activated && rrc_ptr->state == RRC_STATE_CONNECTED && uernti.crnti != 0) { if (not rrc_ptr->security_is_activated or rrc_ptr->state != RRC_STATE_CONNECTED or
// Save reestablishment cause and current C-RNTI uernti.crnti == SRSLTE_INVALID_RNTI) {
Warning("Conditions are NOT met to start procedure.\n");
return proc_outcome_t::error;
}
// Save reestablishment Cause and current C-RNTI context
reest_rnti = uernti.crnti; reest_rnti = uernti.crnti;
reest_cause = cause; reest_cause = cause;
reest_source_pci = rrc_ptr->meas_cells.serving_cell().get_pci(); // needed for reestablishment with another cell reest_source_pci = rrc_ptr->meas_cells.serving_cell().get_pci(); // needed for reestablishment with another cell
reest_source_freq = rrc_ptr->meas_cells.serving_cell().get_earfcn(); reest_source_freq = rrc_ptr->meas_cells.serving_cell().get_earfcn();
// the initiation of reestablishment procedure as indicates in 3GPP 36.331 Section 5.3.7.2 Info("Starting... cause: \"%s\", UE context: {C-RNTI=0x%x, PCI=%d, DL-EARFCN=%d}\n",
// Cannot be called from here because it has PHY-MAC re-configuration that should be performed in a different thread reest_cause == asn1::rrc::reest_cause_opts::recfg_fail
Info("Conditions are met. Initiating RRC Connection Reestablishment Procedure\n"); ? "Reconfiguration failure"
: cause == asn1::rrc::reest_cause_opts::ho_fail ? "Handover failure" : "Other failure",
reest_rnti,
reest_source_pci,
reest_source_freq);
// stop timer T310, if running; // 5.3.7.2 - Initiation
// 1> stop timer T310, if running;
rrc_ptr->t310.stop(); rrc_ptr->t310.stop();
// start timer T311; // 1> start timer T311;
rrc_ptr->t311.run(); rrc_ptr->t311.run();
// Suspend all RB except SRB0 // 1> Suspend all RB except SRB0;
for (int i = 1; i < SRSLTE_N_RADIO_BEARERS; i++) { for (int i = 1; i < SRSLTE_N_RADIO_BEARERS; i++) {
if (rrc_ptr->rlc->has_bearer(i)) { if (rrc_ptr->rlc->has_bearer(i)) {
rrc_ptr->rlc->suspend_bearer(i); rrc_ptr->rlc->suspend_bearer(i);
} }
} }
// reset MAC; // 1> reset MAC;
rrc_ptr->mac->reset(); rrc_ptr->mac->reset();
// configure lower layers to consider the SCell(s), if configured, to be in deactivated state; // configure lower layers to consider the SCell(s), if configured, to be in deactivated state;
rrc_ptr->phy->set_activation_deactivation_scell(0); rrc_ptr->phy->set_activation_deactivation_scell(0);
// apply the default physical channel configuration as specified in 9.2.4;
// 1> apply the default physical channel configuration as specified in 9.2.4;
// Note: this is done by the MAC Reset procedure // Note: this is done by the MAC Reset procedure
// apply the default semi-persistent scheduling configuration as specified in 9.2.3; // 1> apply the default semi-persistent scheduling configuration as specified in 9.2.3;
// N.A. // N.A.
// apply the default MAC main configuration as specified in 9.2.2; // 1> apply the default MAC main configuration as specified in 9.2.2;
rrc_ptr->apply_mac_config_dedicated_default(); rrc_ptr->apply_mac_config_dedicated_default();
// Launch cell reselection // 1> perform cell selection in accordance with the cell selection process as specified in TS 36.304 [4];
if (not rrc_ptr->cell_reselector.launch()) { return start_cell_selection();
Error("Failed to initiate a Cell re-selection procedure...\n");
return proc_outcome_t::error;
}
state = state_t::cell_reselection;
} else {
Warning("Conditions are NOT met to start ConnectionReestablishment\n");
return proc_outcome_t::success;
}
return proc_outcome_t::yield;
} }
srslte::proc_outcome_t rrc::connection_reest_proc::step_cell_reselection() bool rrc::connection_reest_proc::sibs_acquired() const
{ {
return rrc_ptr->meas_cells.serving_cell().has_sib1() && rrc_ptr->meas_cells.serving_cell().has_sib2() &&
rrc_ptr->meas_cells.serving_cell().has_sib3();
}
// Run cell reselection // Perform cell selection in accordance to 36.304
if (not rrc_ptr->cell_reselector.run()) { bool rrc::connection_reest_proc::passes_cell_criteria() const
// Check T311 {
if (not rrc_ptr->t311.is_running()) { return rrc_ptr->phy_ctrl->is_in_sync() and sibs_acquired() and
// Abort procedure if T311 expires rrc_ptr->cell_selection_criteria(rrc_ptr->meas_cells.serving_cell().get_rsrp());
Info("T311 expired during cell reselection. Going to IDLE.\n");
rrc_ptr->start_go_idle();
return proc_outcome_t::success;
}
// Cell reselection finished or not started
if (rrc_ptr->phy_ctrl->is_in_sync()) {
// In-sync, check SIBs
if (rrc_ptr->meas_cells.serving_cell().has_sib1() && rrc_ptr->meas_cells.serving_cell().has_sib2() &&
rrc_ptr->meas_cells.serving_cell().has_sib3()) {
Info("In-sync, SIBs available. Going to cell criteria\n");
return cell_criteria();
} else {
Info("SIBs missing (%d, %d, %d), launching serving cell configuration procedure\n",
rrc_ptr->meas_cells.serving_cell().has_sib1(),
rrc_ptr->meas_cells.serving_cell().has_sib2(),
rrc_ptr->meas_cells.serving_cell().has_sib3());
std::vector<uint32_t> required_sibs = {0, 1, 2};
if (!rrc_ptr->serv_cell_cfg.launch(required_sibs)) {
Error("Failed to initiate configure serving cell\n");
return proc_outcome_t::error;
}
state = state_t::cell_configuration;
}
} else {
// Out-of-sync, relaunch reselection
Info("Serving cell is out-of-sync, re-launching re-selection procedure. T311: %d/%d ms\n",
rrc_ptr->t311.time_elapsed(),
rrc_ptr->t311.duration());
if (!rrc_ptr->cell_reselector.launch()) {
return proc_outcome_t::error;
}
}
}
return proc_outcome_t::yield;
} }
proc_outcome_t rrc::connection_reest_proc::step_cell_configuration() srslte::proc_outcome_t rrc::connection_reest_proc::react(const serv_cell_cfg_completed& ev)
{ {
if (not rrc_ptr->serv_cell_cfg.run()) { if (state != state_t::wait_cell_configuration) {
// Check T311 return proc_outcome_t::yield;
if (!rrc_ptr->t311.is_running()) {
// Abort procedure if T311 expires
Info("T311 expired during cell configuration. Going to IDLE.\n");
rrc_ptr->start_go_idle();
return proc_outcome_t::success;
} }
// SIBs adquisition not started or finished
if (rrc_ptr->phy_ctrl->is_in_sync()) {
// In-sync
if (rrc_ptr->meas_cells.serving_cell().has_sib1() && rrc_ptr->meas_cells.serving_cell().has_sib2() &&
rrc_ptr->meas_cells.serving_cell().has_sib3()) {
// All SIBs are available
return cell_criteria(); return cell_criteria();
}
// Required SIBs are not available
Error("Failed to configure serving cell. Couldn't acquire SIBs.\n");
return proc_outcome_t::error;
} else {
// Out-of-sync, relaunch reselection
Info("Serving cell is out-of-sync, re-launching re-selection procedure\n");
if (!rrc_ptr->cell_reselector.launch()) {
Error("Failed to initiate a Cell re-selection procedure...\n");
return proc_outcome_t::error;
}
state = state_t::cell_reselection;
}
}
return proc_outcome_t::yield;
} }
// 5.3.7.3 - Actions following cell selection while T311 is running
srslte::proc_outcome_t rrc::connection_reest_proc::cell_criteria() srslte::proc_outcome_t rrc::connection_reest_proc::cell_criteria()
{ {
// Perform cell selection in accordance to 36.304 if (not passes_cell_criteria()) {
if (rrc_ptr->cell_selection_criteria(rrc_ptr->meas_cells.serving_cell().get_rsrp())) { Info("Selected Serving cell does not pass criteria. Re-launching re-selection procedure\n");
// Actions following cell reselection while T311 is running 5.3.7.3 return start_cell_selection();
}
// Upon selecting a suitable E-UTRA cell, the UE shall: // Upon selecting a suitable E-UTRA cell, the UE shall:
Info("Cell Selection criteria passed after %dms. Sending RRC Connection Reestablishment Request\n", Info("Cell Selection criteria passed after %dms. Sending RRC Connection Reestablishment Request\n",
rrc_ptr->t311.time_elapsed()); rrc_ptr->t311.time_elapsed());
@ -1297,51 +1247,78 @@ srslte::proc_outcome_t rrc::connection_reest_proc::cell_criteria()
Info("Applying SIB2 configuration\n"); Info("Applying SIB2 configuration\n");
rrc_ptr->handle_sib2(); rrc_ptr->handle_sib2();
// stop timer T311; // 1> stop timer T311;
rrc_ptr->t311.stop(); rrc_ptr->t311.stop();
// start timer T301; // 1> start timer T301;
rrc_ptr->t301.run(); rrc_ptr->t301.run();
// apply the timeAlignmentTimerCommon included in SystemInformationBlockType2; // 1> apply the timeAlignmentTimerCommon included in SystemInformationBlockType2;
// Not implemented yet. // Not implemented yet.
// initiate transmission of the RRCConnectionReestablishmentRequest message in accordance with 5.3.7.4; // 1> initiate transmission of the RRCConnectionReestablishmentRequest message in accordance with 5.3.7.4;
rrc_ptr->send_con_restablish_request(reest_cause, reest_rnti, reest_source_pci); rrc_ptr->send_con_restablish_request(reest_cause, reest_rnti, reest_source_pci);
} else if (rrc_ptr->t311.is_running()) {
// Upon selecting an inter-RAT cell
Info("Reestablishment Cell Selection criteria failed.\n");
state = state_t::wait_reest_msg;
return proc_outcome_t::success;
}
srslte::proc_outcome_t rrc::connection_reest_proc::start_cell_selection()
{
// Launch cell reselection // Launch cell reselection
if (not rrc_ptr->cell_reselector.launch()) { if (not rrc_ptr->cell_selector.launch()) {
Error("Failed to initiate a Cell re-selection procedure...\n"); Error("Failed to initiate a Cell re-selection procedure...\n");
return proc_outcome_t::error; // Wait for T311 to expire
}
state = state_t::cell_reselection;
return proc_outcome_t::yield; return proc_outcome_t::yield;
} }
return proc_outcome_t::success; rrc_ptr->callback_list.add_proc(rrc_ptr->cell_selector);
state = state_t::wait_cell_selection;
return proc_outcome_t::yield;
} }
proc_outcome_t rrc::connection_reest_proc::step() srslte::proc_outcome_t
rrc::connection_reest_proc::react(const cell_selection_proc::cell_selection_complete_ev& cell_selected_ev)
{ {
proc_outcome_t ret = proc_outcome_t::yield; if (state != state_t::wait_cell_selection) {
return proc_outcome_t::yield;
}
/* // Relaunch cell selection if there is still time
* Implementation of procedure in 3GPP 36.331 Section 5.3.7.3: Actions following cell selection while T311 is if (cell_selected_ev.is_error() or not rrc_ptr->phy_ctrl->is_in_sync()) {
* running // Out-of-sync, relaunch reselection
*/ Info("Serving cell is out-of-sync, re-launching re-selection procedure. T311: %d/%d ms\n",
switch (state) { rrc_ptr->t311.time_elapsed(),
case state_t::cell_reselection: rrc_ptr->t311.duration());
ret = step_cell_reselection(); return start_cell_selection();
break; }
case state_t::cell_configuration: // Acquire SIBs if necessary
ret = step_cell_configuration(); if (not sibs_acquired()) {
break; Info("SIBs missing (%d, %d, %d), launching serving cell configuration procedure\n",
rrc_ptr->meas_cells.serving_cell().has_sib1(),
rrc_ptr->meas_cells.serving_cell().has_sib2(),
rrc_ptr->meas_cells.serving_cell().has_sib3());
std::vector<uint32_t> required_sibs = {0, 1, 2};
if (!rrc_ptr->serv_cell_cfg.launch(required_sibs)) {
Error("Failed to initiate configure serving cell\n");
// Wait for T311 expiry
return proc_outcome_t::yield;
}
rrc_ptr->callback_list.add_proc(rrc_ptr->serv_cell_cfg);
state = state_t::wait_cell_configuration;
return proc_outcome_t::yield;
} }
return ret; return cell_criteria();
}
// 5.3.7.6 - T311 expiry
srslte::proc_outcome_t rrc::connection_reest_proc::react(const t311_expiry& ev)
{
// Abort procedure if T311 expires
Info("T311 expired during cell configuration. Going to RRC idle\n");
rrc_ptr->start_go_idle();
return proc_outcome_t::error;
} }
/************************************** /**************************************

Loading…
Cancel
Save