From b7ed8b18586999b2de9f697e029728fb90d38520 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Mon, 12 Oct 2020 16:01:53 +0100 Subject: [PATCH] - added react method to to_state<...> transitions - s1 handover composite state simplified - the eNB now starts a HO cancellation when it receives an invalid Handover Command - the FSM log now prints the current state when it receives an unhandled event --- lib/include/srslte/common/fsm.h | 15 +++++-- srsenb/hdr/stack/rrc/rrc_mobility.h | 13 +++--- srsenb/src/stack/rrc/rrc_mobility.cc | 64 +++++++++++++--------------- 3 files changed, 47 insertions(+), 45 deletions(-) diff --git a/lib/include/srslte/common/fsm.h b/lib/include/srslte/common/fsm.h index 10fabf733..fb36b3d40 100644 --- a/lib/include/srslte/common/fsm.h +++ b/lib/include/srslte/common/fsm.h @@ -246,8 +246,10 @@ struct apply_first_guard_pass > { template static bool trigger(FSM* f, SrcState& s, const Event& ev) { - otherfsmDebug( - static_cast(f), "unhandled event caught: \"%s\"\n", get_type_name().c_str()); + otherfsmDebug(static_cast(f), + "unhandled event caught in state \"%s\": \"%s\"\n", + get_type_name().c_str(), + get_type_name().c_str()); return false; } }; @@ -348,16 +350,23 @@ public: bool (Derived::*GuardFn)(SrcState&, const Event&) = nullptr> using upd = row; - template + template struct to_state { using dest_state_t = DestState; using event_t = Event; + constexpr static void (Derived::*react_fn)(const Event&) = ReactFn; constexpr static bool (Derived::*guard_fn)(const Event&) = GuardFn; template static bool react(derived_view* f, SrcState& s, const event_t& ev) { if (guard_fn == nullptr or (f->*guard_fn)(ev)) { + if (react_fn != nullptr) { + (f->*react_fn)(ev); + } return true; } return false; diff --git a/srsenb/hdr/stack/rrc/rrc_mobility.h b/srsenb/hdr/stack/rrc/rrc_mobility.h index e3f7ebdb0..4bf433c29 100644 --- a/srsenb/hdr/stack/rrc/rrc_mobility.h +++ b/srsenb/hdr/stack/rrc/rrc_mobility.h @@ -153,7 +153,7 @@ private: struct wait_recfg_comp {}; struct s1_source_ho_st : public subfsm_t { ho_meas_report_ev report; - using ho_cmd_msg = srslte::unique_byte_buffer_t; + using ho_cmd_msg = asn1::rrc::ho_cmd_r8_ies_s; struct wait_ho_req_ack_st { void enter(s1_source_ho_st* f, const ho_meas_report_ev& ev); @@ -165,9 +165,8 @@ private: explicit s1_source_ho_st(rrc_mobility* parent_) : base_t(parent_) {} private: - bool send_ho_cmd(wait_ho_req_ack_st& s, const ho_cmd_msg& container); - void handle_ho_cancel(wait_ho_req_ack_st& s, const ho_cancel_ev& ev); - void handle_ho_cancel(status_transfer_st& s, const ho_cancel_ev& ev); + void send_ho_cmd(wait_ho_req_ack_st& s, const ho_cmd_msg& ho_cmd); + void handle_ho_cancel(const ho_cancel_ev& ev); protected: using fsm = s1_source_ho_st; @@ -177,10 +176,8 @@ private: // Start Target Event Action Guard // +-------------------+------------------+---------------------+-----------------------+---------------------+ to_state< idle_st, srslte::failure_ev >, - row< wait_ho_req_ack_st, status_transfer_st, ho_cmd_msg, nullptr, &fsm::send_ho_cmd >, - row< wait_ho_req_ack_st, idle_st, ho_cmd_msg >, - row< wait_ho_req_ack_st, idle_st, ho_cancel_ev, &fsm::handle_ho_cancel >, - row< status_transfer_st, idle_st, ho_cancel_ev, &fsm::handle_ho_cancel > + to_state< idle_st, ho_cancel_ev, &fsm::handle_ho_cancel >, + row< wait_ho_req_ack_st, status_transfer_st, ho_cmd_msg, &fsm::send_ho_cmd > // +-------------------+------------------+---------------------+-----------------------+---------------------+ >; // clang-format on diff --git a/srsenb/src/stack/rrc/rrc_mobility.cc b/srsenb/src/stack/rrc/rrc_mobility.cc index e7ec7755f..d0fbf1d6b 100644 --- a/srsenb/src/stack/rrc/rrc_mobility.cc +++ b/srsenb/src/stack/rrc/rrc_mobility.cc @@ -774,7 +774,25 @@ void rrc::ue::rrc_mobility::handle_ho_preparation_complete(bool is_success, srsl trigger(srslte::failure_ev{}); return; } - trigger(std::move(container)); + /* unpack RRC HOCmd struct and perform sanity checks */ + asn1::rrc::ho_cmd_s rrchocmd; + { + asn1::cbit_ref bref(container->msg, container->N_bytes); + if (rrchocmd.unpack(bref) != asn1::SRSASN_SUCCESS) { + get_log()->warning("Unpacking of RRC HOCommand was unsuccessful\n"); + get_log()->warning_hex(container->msg, container->N_bytes, "Received container:\n"); + trigger(ho_cancel_ev{}); + return; + } + } + if (rrchocmd.crit_exts.type().value != c1_or_crit_ext_opts::c1 or + rrchocmd.crit_exts.c1().type().value != ho_cmd_s::crit_exts_c_::c1_c_::types_opts::ho_cmd_r8) { + get_log()->warning("Only handling r8 Handover Commands\n"); + trigger(ho_cancel_ev{}); + return; + } + + trigger(rrchocmd.crit_exts.c1().ho_cmd_r8()); } bool rrc::ue::rrc_mobility::start_s1_tenb_ho( @@ -996,62 +1014,40 @@ void rrc::ue::rrc_mobility::s1_source_ho_st::wait_ho_req_ack_st::enter(s1_source } } -bool rrc::ue::rrc_mobility::s1_source_ho_st::send_ho_cmd(wait_ho_req_ack_st& s, - const srslte::unique_byte_buffer_t& container) +void rrc::ue::rrc_mobility::s1_source_ho_st::send_ho_cmd(wait_ho_req_ack_st& s, const ho_cmd_r8_ies_s& ho_cmd) { - /* unpack RRC HOCmd struct and perform sanity checks */ - asn1::rrc::ho_cmd_s rrchocmd; - { - asn1::cbit_ref bref(container->msg, container->N_bytes); - if (rrchocmd.unpack(bref) != asn1::SRSASN_SUCCESS) { - get_log()->warning("Unpacking of RRC HOCommand was unsuccessful\n"); - get_log()->warning_hex(container->msg, container->N_bytes, "Received container:\n"); - return false; - } - } - if (rrchocmd.crit_exts.type().value != c1_or_crit_ext_opts::c1 or - rrchocmd.crit_exts.c1().type().value != ho_cmd_s::crit_exts_c_::c1_c_::types_opts::ho_cmd_r8) { - get_log()->warning("Only handling r8 Handover Commands\n"); - return false; - } - /* unpack DL-DCCH message containing the RRCRonnectionReconf (with MobilityInfo) to be sent to the UE */ asn1::rrc::dl_dcch_msg_s dl_dcch_msg; { - asn1::cbit_ref bref(&rrchocmd.crit_exts.c1().ho_cmd_r8().ho_cmd_msg[0], - rrchocmd.crit_exts.c1().ho_cmd_r8().ho_cmd_msg.size()); + asn1::cbit_ref bref(&ho_cmd.ho_cmd_msg[0], ho_cmd.ho_cmd_msg.size()); if (dl_dcch_msg.unpack(bref) != asn1::SRSASN_SUCCESS) { get_log()->warning("Unpacking of RRC DL-DCCH message with HO Command was unsuccessful.\n"); - return false; + trigger(ho_cancel_ev{}); + return; } } if (dl_dcch_msg.msg.type().value != dl_dcch_msg_type_c::types_opts::c1 or dl_dcch_msg.msg.c1().type().value != dl_dcch_msg_type_c::c1_c_::types_opts::rrc_conn_recfg) { get_log()->warning("HandoverCommand is expected to contain an RRC Connection Reconf message inside\n"); - return false; + trigger(ho_cancel_ev{}); + return; } asn1::rrc::rrc_conn_recfg_s& reconf = dl_dcch_msg.msg.c1().rrc_conn_recfg(); if (not reconf.crit_exts.c1().rrc_conn_recfg_r8().mob_ctrl_info_present) { get_log()->warning("HandoverCommand is expected to have mobility control subfield\n"); - return false; + trigger(ho_cancel_ev{}); + return; } /* Send HO Command to UE */ if (not parent_fsm()->rrc_ue->send_dl_dcch(&dl_dcch_msg)) { - return false; + trigger(ho_cancel_ev{}); + return; } - - return true; -} - -//! Called in Source ENB during S1-Handover when there was a Reestablishment Request -void rrc::ue::rrc_mobility::s1_source_ho_st::handle_ho_cancel(wait_ho_req_ack_st& s, const ho_cancel_ev& ev) -{ - parent_fsm()->rrc_enb->s1ap->send_ho_cancel(parent_fsm()->rrc_ue->rnti); } //! Called in Source ENB during S1-Handover when there was a Reestablishment Request -void rrc::ue::rrc_mobility::s1_source_ho_st::handle_ho_cancel(status_transfer_st& s, const ho_cancel_ev& ev) +void rrc::ue::rrc_mobility::s1_source_ho_st::handle_ho_cancel(const ho_cancel_ev& ev) { parent_fsm()->rrc_enb->s1ap->send_ho_cancel(parent_fsm()->rrc_ue->rnti); }