diff --git a/srsue/hdr/stack/rrc/rrc.h b/srsue/hdr/stack/rrc/rrc.h index 7864560e4..b2be787e9 100644 --- a/srsue/hdr/stack/rrc/rrc.h +++ b/srsue/hdr/stack/rrc/rrc.h @@ -118,20 +118,18 @@ class cell_t } cell_t() { - phy_interface_rrc_lte::phy_cell_t tmp; - ZERO_OBJECT(tmp); - ZERO_OBJECT(phy_cell); + phy_interface_rrc_lte::phy_cell_t tmp = {}; cell_t(tmp, 0); } - cell_t(phy_interface_rrc_lte::phy_cell_t phy_cell, float rsrp) + cell_t(phy_interface_rrc_lte::phy_cell_t phy_cell, float rsrp_) { - gettimeofday(&last_update, NULL); + gettimeofday(&last_update, nullptr); this->has_valid_sib1 = false; this->has_valid_sib2 = false; this->has_valid_sib3 = false; this->has_valid_sib13 = false; - this->phy_cell = phy_cell; - this->rsrp = rsrp; + this->phy_cell = phy_cell; + rsrp = rsrp_; in_sync = true; bzero(&sib1, sizeof(sib1)); bzero(&sib2, sizeof(sib2)); @@ -147,12 +145,13 @@ class cell_t return phy_cell.cell.id; } - void set_rsrp(float rsrp) { - if (!std::isnan(rsrp)) { - this->rsrp = rsrp; + void set_rsrp(float rsrp_) + { + if (!std::isnan(rsrp_)) { + rsrp = rsrp_; } in_sync = true; - gettimeofday(&last_update, NULL); + gettimeofday(&last_update, nullptr); } float get_rsrp() { @@ -262,24 +261,24 @@ class cell_t return std::string{buf}; } - phy_interface_rrc_lte::phy_cell_t phy_cell; - bool in_sync; - bool has_mcch; - asn1::rrc::sib_type1_s sib1; - asn1::rrc::sib_type2_s sib2; - asn1::rrc::sib_type3_s sib3; - asn1::rrc::sib_type13_r9_s sib13; - asn1::rrc::mcch_msg_s mcch; + phy_interface_rrc_lte::phy_cell_t phy_cell = {}; + bool in_sync = false; + bool has_mcch = false; + asn1::rrc::sib_type1_s sib1; + asn1::rrc::sib_type2_s sib2; + asn1::rrc::sib_type3_s sib3; + asn1::rrc::sib_type13_r9_s sib13; + asn1::rrc::mcch_msg_s mcch; private: - float rsrp; - - struct timeval last_update; + float rsrp = NAN; - bool has_valid_sib1; - bool has_valid_sib2; - bool has_valid_sib3; - bool has_valid_sib13; + struct timeval last_update = {}; + + bool has_valid_sib1 = false; + bool has_valid_sib2 = false; + bool has_valid_sib3 = false; + bool has_valid_sib13 = false; }; class rrc : public rrc_interface_nas, @@ -417,8 +416,8 @@ private: // RRC constants and timers srslte::timer_handler* timers = nullptr; - uint32_t n310_cnt, N310 = 0; - uint32_t n311_cnt, N311 = 0; + uint32_t n310_cnt = 0, N310 = 0; + uint32_t n311_cnt = 0, N311 = 0; srslte::timer_handler::unique_timer t300, t301, t302, t310, t311, t304; // Radio bearers @@ -470,12 +469,8 @@ private: void delete_last_neighbour(); std::string print_neighbour_cells(); - bool initiated = false; - asn1::rrc::reest_cause_e m_reest_cause = asn1::rrc::reest_cause_e::nulltype; - uint16_t m_reest_rnti = 0; - uint16_t m_reest_source_pci = 0; - bool reestablishment_started = false; - bool reestablishment_successful = false; + bool initiated = false; + bool reestablishment_successful = false; // Measurements sub-class class rrc_meas @@ -621,15 +616,17 @@ private: class process_pcch_proc; class go_idle_proc; class cell_reselection_proc; + class connection_reest_proc; srslte::proc_t cell_searcher; srslte::proc_t si_acquirer; srslte::proc_t serv_cell_cfg; srslte::proc_t cell_selector; - srslte::proc_t idle_setter; - srslte::proc_t pcch_processor; - srslte::proc_t conn_req_proc; - srslte::proc_t plmn_searcher; - srslte::proc_t cell_reselector; + srslte::proc_t idle_setter; + srslte::proc_t pcch_processor; + srslte::proc_t conn_req_proc; + srslte::proc_t plmn_searcher; + srslte::proc_t cell_reselector; + srslte::proc_t connection_reest; srslte::proc_manager_list_t callback_list; @@ -647,7 +644,7 @@ private: // Senders void send_con_request(srslte::establishment_cause_t cause); - void send_con_restablish_request(); + void send_con_restablish_request(asn1::rrc::reest_cause_e cause, uint16_t rnti, uint16_t pci); void send_con_restablish_complete(); void send_con_setup_complete(srslte::unique_byte_buffer_t nas_msg); void send_ul_info_transfer(srslte::unique_byte_buffer_t nas_msg); @@ -674,8 +671,7 @@ private: void radio_link_failure(); void leave_connected(); void stop_timers(); - void init_con_restablish_request(asn1::rrc::reest_cause_e cause); - void proc_con_restablish_request(); + void start_con_restablishment(asn1::rrc::reest_cause_e cause); void start_cell_reselection(); void log_rr_config_common(); diff --git a/srsue/hdr/stack/rrc/rrc_procedures.h b/srsue/hdr/stack/rrc/rrc_procedures.h index 59d268f74..7bf6e0177 100644 --- a/srsue/hdr/stack/rrc/rrc_procedures.h +++ b/srsue/hdr/stack/rrc/rrc_procedures.h @@ -230,6 +230,28 @@ private: srslte::proc_future_t cell_selection_fut; }; +class rrc::connection_reest_proc +{ +public: + explicit connection_reest_proc(rrc* rrc_); + srslte::proc_outcome_t init(asn1::rrc::reest_cause_e cause); + srslte::proc_outcome_t step(); + static const char* name() { return "Connection re-establishment"; } + +private: + enum class state_t { init, cell_reselection, cell_configuration, cell_criteria, success, error } 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; + + void step_init(); + void step_cell_reselection(); + void step_cell_configuration(); + void step_cell_criteria(); +}; + } // namespace srsue #endif // SRSLTE_RRC_PROCEDURES_H diff --git a/srsue/src/stack/rrc/rrc.cc b/srsue/src/stack/rrc/rrc.cc index 76565c070..8fadf737c 100644 --- a/srsue/src/stack/rrc/rrc.cc +++ b/srsue/src/stack/rrc/rrc.cc @@ -62,13 +62,13 @@ rrc::rrc(srslte::log* rrc_log_) : conn_req_proc(this), plmn_searcher(this), cell_reselector(this), + connection_reest(this), serving_cell(unique_cell_t(new cell_t({}, 0.0))) { + // Do nothing } -rrc::~rrc() -{ -} +rrc::~rrc() = default; static void srslte_rrc_handler(asn1::srsasn_logger_level_t level, void* ctx, const char* str) { @@ -233,10 +233,6 @@ void rrc::run_tti(uint32_t tti) } break; case RRC_STATE_CONNECTED: - // Performing reestablishment cell selection - if (m_reest_cause != asn1::rrc::reest_cause_e::nulltype) { - proc_con_restablish_request(); - } measurements.run_tti(tti); break; default: @@ -792,7 +788,7 @@ void rrc::radio_link_failure() { rrc_log->warning("Detected Radio-Link Failure\n"); rrc_log->console("Warning: Detected Radio-Link Failure\n"); if (state == RRC_STATE_CONNECTED) { - init_con_restablish_request(asn1::rrc::reest_cause_e::other_fail); + start_con_restablishment(asn1::rrc::reest_cause_e::other_fail); } } @@ -882,15 +878,11 @@ void rrc::send_con_request(srslte::establishment_cause_t cause) } /* RRC connection re-establishment procedure (5.3.7.4) */ -void rrc::send_con_restablish_request() +void rrc::send_con_restablish_request(asn1::rrc::reest_cause_e cause, uint16_t crnti, uint16_t pci) { - uint16_t crnti; - uint16_t pci; uint32_t cellid; // Clean reestablishment type - asn1::rrc::reest_cause_e cause = m_reest_cause; - m_reest_cause = asn1::rrc::reest_cause_e::nulltype; reestablishment_successful = false; if (cause == asn1::rrc::reest_cause_e::ho_fail) { @@ -899,11 +891,8 @@ void rrc::send_con_restablish_request() cellid = ho_src_cell.get_cell_id(); } else if (cause == asn1::rrc::reest_cause_e::other_fail) { // use source PCI after RLF - crnti = m_reest_rnti; - pci = m_reest_source_pci; cellid = serving_cell->get_cell_id(); } else { - crnti = m_reest_rnti; pci = serving_cell->get_pci(); cellid = serving_cell->get_cell_id(); } @@ -1264,7 +1253,7 @@ bool rrc::con_reconfig(asn1::rrc::rrc_conn_recfg_s* reconfig) // HO failure from T304 expiry 5.3.5.6 void rrc::ho_failed() { - init_con_restablish_request(asn1::rrc::reest_cause_e::ho_fail); + start_con_restablishment(asn1::rrc::reest_cause_e::ho_fail); } // Reconfiguration failure or Section 5.3.5.5 @@ -1280,7 +1269,7 @@ void rrc::con_reconfig_failed() if (security_is_activated) { // Start the Reestablishment Procedure - init_con_restablish_request(asn1::rrc::reest_cause_e::recfg_fail); + start_con_restablishment(asn1::rrc::reest_cause_e::recfg_fail); } else { start_go_idle(); } @@ -1315,7 +1304,6 @@ void rrc::leave_connected() { rrc_log->console("RRC IDLE\n"); rrc_log->info("Leaving RRC_CONNECTED state\n"); - m_reest_cause = asn1::rrc::reest_cause_e::nulltype; state = RRC_STATE_IDLE; drb_up = false; security_is_activated = false; @@ -1357,108 +1345,13 @@ void rrc::stop_timers() * * The parameter cause shall indicate the cause of the reestablishment according to the sections mentioned adobe. */ -void rrc::init_con_restablish_request(asn1::rrc::reest_cause_e cause) +void rrc::start_con_restablishment(asn1::rrc::reest_cause_e cause) { - // Save Current RNTI before MAC Reset - mac_interface_rrc::ue_rnti_t uernti; - mac->get_rntis(&uernti); - - // If security is activated, RRC connected and C-RNTI available - if (security_is_activated && state == RRC_STATE_CONNECTED && uernti.crnti != 0) { - // Save reestablishment cause and current C-RNTI - m_reest_rnti = uernti.crnti; - m_reest_cause = cause; - m_reest_source_pci = serving_cell->get_pci(); // needed for reestablishment with another cell - - reestablishment_started = false; - - // initiation of reestablishment procedure as indicates in 3GPP 36.331 Section 5.3.7.2 - rrc_log->info("Initiating RRC Connection Reestablishment Procedure\n"); - } else { - // 3GPP 36.331 Section 5.3.7.1 - // If AS security has not been activated, the UE does not initiate the procedure but instead - // moves to RRC_IDLE directly - start_go_idle(); - } -} - -/* Implementation of procedure in 3GPP 36.331 Section 5.3.7.3: Actions following cell selection while T311 is running - */ -void rrc::proc_con_restablish_request() -{ - if (!reestablishment_started) { - - reestablishment_started = true; - - rrc_log->info("Resetting timers and MAC in RRC Connection Reestablishment Procedure\n"); - - // stop timer T310, if running; - t310.stop(); - - // start timer T311; - t311.run(); - - // Suspend all RB except SRB0 - for (int i = 1; i < SRSLTE_N_RADIO_BEARERS; i++) { - if (rlc->has_bearer(i)) { - rlc->suspend_bearer(i); - } - } - - // reset MAC; - mac->reset(); - - // apply the default physical channel configuration as specified in 9.2.4; - set_phy_default_pucch_srs(); - - // apply the default semi-persistent scheduling configuration as specified in 9.2.3; - // N.A. - - // apply the default MAC main configuration as specified in 9.2.2; - apply_mac_config_dedicated_default(); - - // perform cell selection in accordance with the cell selection process as specified in TS 36.304 [4]; - start_cell_reselection(); + if (not connection_reest.launch(cause)) { + rrc_log->info("Failed to launch connection re-establishment pocedure\n"); } - // Check timer... - if (t311.is_running()) { - // Wait until we're synced and have obtained SIBs - if (serving_cell->in_sync && serving_cell->has_sib1() && serving_cell->has_sib2() && serving_cell->has_sib3()) { - // Perform cell selection in accordance to 36.304 - if (cell_selection_criteria(serving_cell->get_rsrp())) { - // Actions following cell reselection while T311 is running 5.3.7.3 - // Upon selecting a suitable E-UTRA cell, the UE shall: - rrc_log->info("Cell Selection criteria passed after %dms. Sending RRC Connection Reestablishment Request\n", - t311.value()); - - // stop timer T311; - t311.stop(); - - // start timer T301; - t301.run(); - - // apply the timeAlignmentTimerCommon included in SystemInformationBlockType2; - // TODO - - // initiate transmission of the RRCConnectionReestablishmentRequest message in accordance with 5.3.7.4; - send_con_restablish_request(); - } else { - // Upon selecting an inter-RAT cell - rrc_log->warning("Reestablishment Cell Selection criteria failed.\n"); - rrc_log->console("Reestablishment Cell Selection criteria failed (rsrp=%.2f)\n", - serving_cell->get_rsrp()); - leave_connected(); - } - } else { - // No synchronized, do nothing - } - } else { - // t311 expired or stopped - rrc_log->info("T311 expired while selecting cell. Going to IDLE\n"); - rrc_log->console("T311 expired while selecting cell. Going to IDLE\n"); - leave_connected(); - } + callback_list.add_proc(connection_reest); } void rrc::start_cell_reselection() diff --git a/srsue/src/stack/rrc/rrc_procedures.cc b/srsue/src/stack/rrc/rrc_procedures.cc index e94048839..82c11c84c 100644 --- a/srsue/src/stack/rrc/rrc_procedures.cc +++ b/srsue/src/stack/rrc/rrc_procedures.cc @@ -869,4 +869,211 @@ proc_outcome_t rrc::cell_reselection_proc::step() return srslte::proc_outcome_t::success; } +/************************************** + * RRC Connection Re-establishment procedure + *************************************/ + +rrc::connection_reest_proc::connection_reest_proc(srsue::rrc* rrc_) : rrc_ptr(rrc_), state(state_t::init) {} + +proc_outcome_t rrc::connection_reest_proc::init(asn1::rrc::reest_cause_e cause) +{ + Info("Starting...\n"); + + // Save Current RNTI before MAC Reset + mac_interface_rrc::ue_rnti_t uernti; + rrc_ptr->mac->get_rntis(&uernti); + + // If security is activated, RRC connected and C-RNTI available + if (rrc_ptr->security_is_activated && rrc_ptr->state == RRC_STATE_CONNECTED && uernti.crnti != 0) { + // Save reestablishment cause and current C-RNTI + reest_rnti = uernti.crnti; + reest_cause = cause; + reest_source_pci = rrc_ptr->serving_cell->get_pci(); // needed for reestablishment with another cell + + // the initiation of reestablishment procedure as indicates in 3GPP 36.331 Section 5.3.7.2 + // Cannot be called from here because it has PHY-MAC re-configuration that should be performed in a different thread + Info("Conditions are meet\n"); + state = state_t::init; + + } else { + // 3GPP 36.331 Section 5.3.7.1 + // If AS security has not been activated, the UE does not initiate the procedure but instead + // moves to RRC_IDLE directly + Info("Conditions are NOT meet\n"); + rrc_ptr->start_go_idle(); + state = state_t::success; + } + + return proc_outcome_t::yield; +} + +void rrc::connection_reest_proc::step_init() +{ + // initiation of reestablishment procedure as indicates in 3GPP 36.331 Section 5.3.7.2 + Info("Initiating RRC Connection Reestablishment Procedure\n"); + + // stop timer T310, if running; + rrc_ptr->t310.stop(); + + // start timer T311; + rrc_ptr->t311.run(); + + // Suspend all RB except SRB0 + for (int i = 1; i < SRSLTE_N_RADIO_BEARERS; i++) { + if (rrc_ptr->rlc->has_bearer(i)) { + rrc_ptr->rlc->suspend_bearer(i); + } + } + + // reset MAC; + rrc_ptr->mac->reset(); + + // apply the default physical channel configuration as specified in 9.2.4; + rrc_ptr->set_phy_default_pucch_srs(); + + // apply the default semi-persistent scheduling configuration as specified in 9.2.3; + // N.A. + + // apply the default MAC main configuration as specified in 9.2.2; + rrc_ptr->apply_mac_config_dedicated_default(); + + // Launch cell reselection + if (rrc_ptr->cell_reselector.launch()) { + state = state_t::cell_reselection; + } else { + Error("Failed to initiate a Cell re-selection procedure...\n"); + state = state_t::error; + } +} + +void rrc::connection_reest_proc::step_cell_reselection() +{ + if (!rrc_ptr->t311.is_running()) { + Info("During cell reselection, T311 expired. Aborting.\n"); + state = state_t::success; + } else if (rrc_ptr->cell_reselector.run()) { + // Keep running, do nothing + } else if (!rrc_ptr->serving_cell->in_sync) { + Info("Serving cell is out-of-sync, re-launching re-selection procedure\n"); + if (rrc_ptr->cell_reselector.launch()) { + state = state_t::cell_reselection; + } else { + // Error launching procedure + state = state_t::error; + } + } else if (rrc_ptr->serving_cell->has_sib1() && rrc_ptr->serving_cell->has_sib2() && + rrc_ptr->serving_cell->has_sib3()) { + Info("In-sync, SIBs available. Going to cell criteria\n"); + state = state_t::cell_criteria; + } else { + Info("SIBs missing (%d, %d, %d), launching serving cell configuration procedure\n", + rrc_ptr->serving_cell->has_sib1(), + rrc_ptr->serving_cell->has_sib2(), + rrc_ptr->serving_cell->has_sib3()); + std::vector required_sibs = {1, 2, 3}; + if (rrc_ptr->serv_cell_cfg.launch(required_sibs)) { + state = state_t::cell_configuration; + } else { + Error("Failed to initiate configure serving cell\n"); + state = state_t::error; + } + } +} + +void rrc::connection_reest_proc::step_cell_configuration() +{ + if (!rrc_ptr->t311.is_running()) { + Info("During cell configuration, T311 expired. Aborting.\n"); + state = state_t::success; + } else if (rrc_ptr->serv_cell_cfg.run()) { + // Keep running, do nothing + } else if (!rrc_ptr->serving_cell->in_sync) { + Info("Serving cell is out-of-sync, re-launching re-selection procedure\n"); + if (rrc_ptr->cell_reselector.launch()) { + state = state_t::cell_reselection; + } else { + Error("Failed to initiate a Cell re-selection procedure...\n"); + state = state_t::error; + } + } else if (rrc_ptr->serving_cell->has_sib1() && rrc_ptr->serving_cell->has_sib2() && + rrc_ptr->serving_cell->has_sib3()) { + Info("SIBs available. Going to cell criteria\n"); + state = state_t::cell_criteria; + } else { + Error("Failed to configure serving cell\n"); + state = state_t::error; + } +} + +void rrc::connection_reest_proc::step_cell_criteria() +{ + // Wait until we're synced and have obtained SIBs + // Perform cell selection in accordance to 36.304 + if (!rrc_ptr->t311.is_running()) { + Info("During cell selection criteria, T311 expired. Aborting.\n"); + state = state_t::success; + } else if (rrc_ptr->cell_selection_criteria(rrc_ptr->serving_cell->get_rsrp())) { + // Actions following cell reselection while T311 is running 5.3.7.3 + // Upon selecting a suitable E-UTRA cell, the UE shall: + Info("Cell Selection criteria passed after %dms. Sending RRC Connection Reestablishment Request\n", + rrc_ptr->t311.value()); + + // stop timer T311; + rrc_ptr->t311.stop(); + + // start timer T301; + rrc_ptr->t301.run(); + + // apply the timeAlignmentTimerCommon included in SystemInformationBlockType2; + // TODO + + // 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); + } else { + // Upon selecting an inter-RAT cell + Warning("Reestablishment Cell Selection criteria failed.\n"); + rrc_ptr->leave_connected(); + } + state = state_t::success; +} + +proc_outcome_t rrc::connection_reest_proc::step() +{ + proc_outcome_t proc_outcome = srslte::proc_outcome_t::yield; + + /* + * Implementation of procedure in 3GPP 36.331 Section 5.3.7.3: Actions following cell selection while T311 is running + */ + switch (state) { + + case state_t::init: + step_init(); + break; + + case state_t::cell_reselection: + step_cell_reselection(); + break; + + case state_t::cell_configuration: + step_cell_configuration(); + break; + + case state_t::cell_criteria: + step_cell_criteria(); + break; + + case state_t::success: + Info("Finished successfully\n"); + proc_outcome = srslte::proc_outcome_t::success; + break; + + case state_t::error: + Info("Finished with error\n"); + proc_outcome = srslte::proc_outcome_t::error; + break; + } + + return proc_outcome; +} + } // namespace srsue