diff --git a/srsue/hdr/stack/rrc/rrc.h b/srsue/hdr/stack/rrc/rrc.h index 77b29347b..2c7adf42c 100644 --- a/srsue/hdr/stack/rrc/rrc.h +++ b/srsue/hdr/stack/rrc/rrc.h @@ -330,13 +330,13 @@ public: void new_cell_meas(const std::vector& meas); // MAC interface - void ho_ra_completed(bool ra_successful); + void ho_ra_completed(bool ra_successful) final; void release_pucch_srs(); void run_tti(); void ra_problem(); // GW interface - bool is_connected(); // this is also NAS interface + bool is_connected() final; // this is also NAS interface bool have_drb(); // PDCP interface @@ -405,8 +405,6 @@ private: srslte::phy_cfg_t current_phy_cfg, previous_phy_cfg = {}; srslte::mac_cfg_t current_mac_cfg, previous_mac_cfg = {}; bool current_scell_configured[SRSLTE_MAX_CARRIERS] = {}; - bool pending_mob_reconf = false; - asn1::rrc::rrc_conn_recfg_s mob_reconf = {}; srslte::as_security_config_t sec_cfg = {}; @@ -473,9 +471,6 @@ private: bool reestablishment_started = false; bool reestablishment_successful = false; - // Process HO completition in the background - void process_ho_ra_completed(bool ra_successful); - // Measurements private subclass class rrc_meas; std::unique_ptr measurements; @@ -525,7 +520,7 @@ private: class go_idle_proc; class cell_reselection_proc; class connection_reest_proc; - class ho_prep_proc; + class ho_proc; srslte::proc_t phy_cell_selector; srslte::proc_t cell_searcher; srslte::proc_t si_acquirer; @@ -537,7 +532,7 @@ private: srslte::proc_t plmn_searcher; srslte::proc_t cell_reselector; srslte::proc_t connection_reest; - srslte::proc_t ho_prep_proc; + srslte::proc_t ho_handler; srslte::proc_manager_list_t callback_list; diff --git a/srsue/hdr/stack/rrc/rrc_procedures.h b/srsue/hdr/stack/rrc/rrc_procedures.h index b7f7cf297..cf1ad4de3 100644 --- a/srsue/hdr/stack/rrc/rrc_procedures.h +++ b/srsue/hdr/stack/rrc/rrc_procedures.h @@ -302,18 +302,22 @@ private: srslte::proc_outcome_t cell_criteria(); }; -class rrc::ho_prep_proc +class rrc::ho_proc { public: struct t304_expiry {}; + struct ra_completed_ev { + bool success; + }; - explicit ho_prep_proc(rrc* rrc_); + explicit ho_proc(rrc* rrc_); srslte::proc_outcome_t init(const asn1::rrc::rrc_conn_recfg_s& rrc_reconf); srslte::proc_outcome_t react(cell_select_event_t ev); srslte::proc_outcome_t react(t304_expiry ev); + srslte::proc_outcome_t react(ra_completed_ev ev); srslte::proc_outcome_t step(); void then(const srslte::proc_state_t& result); - static const char* name() { return "Handover Preparation"; } + static const char* name() { return "Handover"; } private: rrc* rrc_ptr = nullptr; @@ -325,7 +329,7 @@ private: // state uint32_t target_earfcn; - enum state_t { launch_phy_cell_select, wait_phy_cell_select_complete } state; + enum state_t { launch_phy_cell_select, wait_phy_cell_select_complete, wait_ra_completion } state; }; } // namespace srsue diff --git a/srsue/src/stack/rrc/rrc.cc b/srsue/src/stack/rrc/rrc.cc index 3f7a6d487..8536f79ab 100644 --- a/srsue/src/stack/rrc/rrc.cc +++ b/srsue/src/stack/rrc/rrc.cc @@ -100,7 +100,7 @@ rrc::rrc(stack_interface_rrc* stack_) : plmn_searcher(this), cell_reselector(this), connection_reest(this), - ho_prep_proc(this), + ho_handler(this), serving_cell(unique_cell_t(new cell_t())) { measurements = std::unique_ptr(new rrc_meas()); @@ -169,8 +169,6 @@ void rrc::init(phy_interface_rrc_lte* phy_, cell_clean_cnt = 0; - pending_mob_reconf = false; - // Set default values for RRC. MAC and PHY are set to default themselves set_rrc_default(); @@ -275,7 +273,7 @@ void rrc::run_tti() radio_link_failure(); break; case cmd_msg_t::HO_COMPLETE: - process_ho_ra_completed(msg.lcid > 0); + ho_handler.trigger(ho_proc::ra_completed_ev{msg.lcid > 0}); break; case cmd_msg_t::STOP: return; @@ -793,6 +791,7 @@ void rrc::radio_link_failure() // TODO: Generate and store failure report rrc_log->warning("Detected Radio-Link Failure\n"); rrc_log->console("Warning: Detected Radio-Link Failure\n"); + if (state == RRC_STATE_CONNECTED) { start_con_restablishment(reest_cause_e::other_fail); } @@ -1052,38 +1051,13 @@ void rrc::ho_ra_completed(bool ra_successful) cmd_q.push(std::move(msg)); } -void rrc::process_ho_ra_completed(bool ra_successful) -{ - if (pending_mob_reconf) { - if (ra_successful) { - if (!measurements->parse_meas_config( - &mob_reconf.crit_exts.c1().rrc_conn_recfg_r8(), true, ho_src_cell.get_earfcn())) { - rrc_log->error("Parsing measurementConfig. TODO: Send ReconfigurationReject\n"); - } - t304.stop(); - } - // T304 will expiry and send ho_failure - - rrc_log->info("HO %ssuccessful\n", ra_successful ? "" : "un"); - rrc_log->console("HO %ssuccessful\n", ra_successful ? "" : "un"); - - pending_mob_reconf = false; - } else { - rrc_log->error("Received HO random access completed but no pending mobility reconfiguration info\n"); - } -} - bool rrc::con_reconfig_ho(rrc_conn_recfg_s* reconfig) { - // store mobilityControlInfo - mob_reconf = *reconfig; - pending_mob_reconf = true; - - if (not ho_prep_proc.launch(mob_reconf)) { + if (not ho_handler.launch(*reconfig)) { rrc_log->error("Unable to launch Handover Preparation procedure\n"); return false; } - callback_list.add_proc(ho_prep_proc); + callback_list.add_proc(ho_handler); return true; } @@ -1157,7 +1131,7 @@ bool rrc::con_reconfig(rrc_conn_recfg_s* reconfig) // HO failure from T304 expiry 5.3.5.6 void rrc::ho_failed() { - ho_prep_proc.trigger(ho_prep_proc::t304_expiry{}); + ho_handler.trigger(ho_proc::t304_expiry{}); start_con_restablishment(reest_cause_e::ho_fail); } diff --git a/srsue/src/stack/rrc/rrc_procedures.cc b/srsue/src/stack/rrc/rrc_procedures.cc index 0e8ddca4f..366504e78 100644 --- a/srsue/src/stack/rrc/rrc_procedures.cc +++ b/srsue/src/stack/rrc/rrc_procedures.cc @@ -22,6 +22,7 @@ #include "srsue/hdr/stack/rrc/rrc_procedures.h" #include "srslte/common/security.h" #include "srslte/common/tti_point.h" +#include "srsue/hdr/stack/rrc/rrc_meas.h" #include // for printing uint64_t #define Error(fmt, ...) rrc_ptr->rrc_log->error("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) @@ -66,7 +67,7 @@ void rrc::phy_cell_select_proc::then(const srslte::proc_state_t& result) } else if (rrc_ptr->cell_selector.is_busy()) { rrc_ptr->cell_selector.trigger(cell_select_event_t{result.is_success()}); } else { - rrc_ptr->ho_prep_proc.trigger(cell_select_event_t{result.is_success()}); + rrc_ptr->ho_handler.trigger(cell_select_event_t{result.is_success()}); } } @@ -1337,9 +1338,9 @@ proc_outcome_t rrc::connection_reest_proc::step() * Handover Preparation Procedure *************************************/ -rrc::ho_prep_proc::ho_prep_proc(srsue::rrc* rrc_) : rrc_ptr(rrc_) {} +rrc::ho_proc::ho_proc(srsue::rrc* rrc_) : rrc_ptr(rrc_) {} -srslte::proc_outcome_t rrc::ho_prep_proc::init(const asn1::rrc::rrc_conn_recfg_s& rrc_reconf) +srslte::proc_outcome_t rrc::ho_proc::init(const asn1::rrc::rrc_conn_recfg_s& rrc_reconf) { Info("Starting...\n"); recfg_r8 = rrc_reconf.crit_exts.c1().rrc_conn_recfg_r8(); @@ -1381,8 +1382,12 @@ srslte::proc_outcome_t rrc::ho_prep_proc::init(const asn1::rrc::rrc_conn_recfg_s return proc_outcome_t::yield; } -srslte::proc_outcome_t rrc::ho_prep_proc::react(srsue::cell_select_event_t ev) +srslte::proc_outcome_t rrc::ho_proc::react(srsue::cell_select_event_t ev) { + if (state != wait_phy_cell_select_complete) { + Warning("Received unexpected PHY Cell Selection event\n"); + return proc_outcome_t::yield; + } // Check if cell has not been deleted in the meantime cell_t* target_cell = rrc_ptr->get_neighbour_cell_handle(target_earfcn, recfg_r8.mob_ctrl_info.target_pci); if (target_cell == nullptr) { @@ -1439,10 +1444,12 @@ srslte::proc_outcome_t rrc::ho_prep_proc::react(srsue::cell_select_event_t ev) recfg_r8.mob_ctrl_info.target_pci, rrc_ptr->serving_cell->get_earfcn(), ncc, &rrc_ptr->sec_cfg); rrc_ptr->pdcp->config_security_all(rrc_ptr->sec_cfg); - return proc_outcome_t::success; + + state = wait_ra_completion; + return proc_outcome_t::yield; } -srslte::proc_outcome_t rrc::ho_prep_proc::step() +srslte::proc_outcome_t rrc::ho_proc::step() { if (rrc_ptr->state != RRC_STATE_CONNECTED) { Info("HO interrupted, since RRC is no longer in connected state\n"); @@ -1476,13 +1483,33 @@ srslte::proc_outcome_t rrc::ho_prep_proc::step() return proc_outcome_t::yield; } -srslte::proc_outcome_t rrc::ho_prep_proc::react(t304_expiry ev) +srslte::proc_outcome_t rrc::ho_proc::react(t304_expiry ev) { Info("HO preparation timed out.\n"); return proc_outcome_t::error; } -void rrc::ho_prep_proc::then(const srslte::proc_state_t& result) +srslte::proc_outcome_t rrc::ho_proc::react(ra_completed_ev ev) +{ + if (state != wait_ra_completion) { + Warning("Received unexpected RA Complete Event\n"); + return proc_outcome_t::yield; + } + + rrc_ptr->t304.stop(); + if (ev.success) { + if (not rrc_ptr->measurements->parse_meas_config(&recfg_r8, true, rrc_ptr->ho_src_cell.get_earfcn())) { + Error("Parsing measurementConfig. TODO: Send ReconfigurationReject\n"); + } + } + + Info("HO %ssuccessful\n", ev.success ? "" : "un"); + rrc_ptr->rrc_log->console("HO %ssuccessful\n", ev.success ? "" : "un"); + + return ev.success ? proc_outcome_t::success : proc_outcome_t::error; +} + +void rrc::ho_proc::then(const srslte::proc_state_t& result) { Info("Finished HO Preparation %s\n", result.is_success() ? "successfully" : "with error"); if (result.is_error()) {