- 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
master
Francisco Paisana 4 years ago
parent 53f1a62c64
commit b7ed8b1858

@ -246,8 +246,10 @@ struct apply_first_guard_pass<FSM, type_list<> > {
template <typename SrcState, typename Event> template <typename SrcState, typename Event>
static bool trigger(FSM* f, SrcState& s, const Event& ev) static bool trigger(FSM* f, SrcState& s, const Event& ev)
{ {
otherfsmDebug( otherfsmDebug(static_cast<typename FSM::derived_t*>(f),
static_cast<typename FSM::derived_t*>(f), "unhandled event caught: \"%s\"\n", get_type_name<Event>().c_str()); "unhandled event caught in state \"%s\": \"%s\"\n",
get_type_name<SrcState>().c_str(),
get_type_name<Event>().c_str());
return false; return false;
} }
}; };
@ -348,16 +350,23 @@ public:
bool (Derived::*GuardFn)(SrcState&, const Event&) = nullptr> bool (Derived::*GuardFn)(SrcState&, const Event&) = nullptr>
using upd = row<SrcState, SrcState, Event, ReactFn, GuardFn>; using upd = row<SrcState, SrcState, Event, ReactFn, GuardFn>;
template <typename DestState, typename Event, bool (Derived::*GuardFn)(const Event&) = nullptr> template <typename DestState,
typename Event,
void (Derived::*ReactFn)(const Event&) = nullptr,
bool (Derived::*GuardFn)(const Event&) = nullptr>
struct to_state { struct to_state {
using dest_state_t = DestState; using dest_state_t = DestState;
using event_t = Event; using event_t = Event;
constexpr static void (Derived::*react_fn)(const Event&) = ReactFn;
constexpr static bool (Derived::*guard_fn)(const Event&) = GuardFn; constexpr static bool (Derived::*guard_fn)(const Event&) = GuardFn;
template <typename SrcState> template <typename SrcState>
static bool react(derived_view* f, SrcState& s, const event_t& ev) static bool react(derived_view* f, SrcState& s, const event_t& ev)
{ {
if (guard_fn == nullptr or (f->*guard_fn)(ev)) { if (guard_fn == nullptr or (f->*guard_fn)(ev)) {
if (react_fn != nullptr) {
(f->*react_fn)(ev);
}
return true; return true;
} }
return false; return false;

@ -153,7 +153,7 @@ private:
struct wait_recfg_comp {}; struct wait_recfg_comp {};
struct s1_source_ho_st : public subfsm_t<s1_source_ho_st> { struct s1_source_ho_st : public subfsm_t<s1_source_ho_st> {
ho_meas_report_ev report; 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 { struct wait_ho_req_ack_st {
void enter(s1_source_ho_st* f, const ho_meas_report_ev& ev); 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_) {} explicit s1_source_ho_st(rrc_mobility* parent_) : base_t(parent_) {}
private: private:
bool send_ho_cmd(wait_ho_req_ack_st& s, const ho_cmd_msg& container); void send_ho_cmd(wait_ho_req_ack_st& s, const ho_cmd_msg& ho_cmd);
void handle_ho_cancel(wait_ho_req_ack_st& s, const ho_cancel_ev& ev); void handle_ho_cancel(const ho_cancel_ev& ev);
void handle_ho_cancel(status_transfer_st& s, const ho_cancel_ev& ev);
protected: protected:
using fsm = s1_source_ho_st; using fsm = s1_source_ho_st;
@ -177,10 +176,8 @@ private:
// Start Target Event Action Guard // Start Target Event Action Guard
// +-------------------+------------------+---------------------+-----------------------+---------------------+ // +-------------------+------------------+---------------------+-----------------------+---------------------+
to_state< idle_st, srslte::failure_ev >, to_state< idle_st, srslte::failure_ev >,
row< wait_ho_req_ack_st, status_transfer_st, ho_cmd_msg, nullptr, &fsm::send_ho_cmd >, to_state< idle_st, ho_cancel_ev, &fsm::handle_ho_cancel >,
row< wait_ho_req_ack_st, idle_st, ho_cmd_msg >, row< wait_ho_req_ack_st, status_transfer_st, ho_cmd_msg, &fsm::send_ho_cmd >
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 >
// +-------------------+------------------+---------------------+-----------------------+---------------------+ // +-------------------+------------------+---------------------+-----------------------+---------------------+
>; >;
// clang-format on // clang-format on

@ -774,7 +774,25 @@ void rrc::ue::rrc_mobility::handle_ho_preparation_complete(bool is_success, srsl
trigger(srslte::failure_ev{}); trigger(srslte::failure_ev{});
return; 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( 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, 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)
const srslte::unique_byte_buffer_t& 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");
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 */ /* 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::rrc::dl_dcch_msg_s dl_dcch_msg;
{ {
asn1::cbit_ref bref(&rrchocmd.crit_exts.c1().ho_cmd_r8().ho_cmd_msg[0], asn1::cbit_ref bref(&ho_cmd.ho_cmd_msg[0], ho_cmd.ho_cmd_msg.size());
rrchocmd.crit_exts.c1().ho_cmd_r8().ho_cmd_msg.size());
if (dl_dcch_msg.unpack(bref) != asn1::SRSASN_SUCCESS) { if (dl_dcch_msg.unpack(bref) != asn1::SRSASN_SUCCESS) {
get_log()->warning("Unpacking of RRC DL-DCCH message with HO Command was unsuccessful.\n"); 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 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) { 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"); 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(); 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) { 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"); get_log()->warning("HandoverCommand is expected to have mobility control subfield\n");
return false; trigger(ho_cancel_ev{});
return;
} }
/* Send HO Command to UE */ /* Send HO Command to UE */
if (not parent_fsm()->rrc_ue->send_dl_dcch(&dl_dcch_msg)) { 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 //! 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); parent_fsm()->rrc_enb->s1ap->send_ho_cancel(parent_fsm()->rrc_ue->rnti);
} }

Loading…
Cancel
Save