- 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
This commit is contained in:
Francisco Paisana 2020-10-12 16:01:53 +01:00
parent 53f1a62c64
commit b7ed8b1858
3 changed files with 47 additions and 45 deletions

View File

@ -246,8 +246,10 @@ struct apply_first_guard_pass<FSM, type_list<> > {
template <typename SrcState, typename Event>
static bool trigger(FSM* f, SrcState& s, const Event& ev)
{
otherfsmDebug(
static_cast<typename FSM::derived_t*>(f), "unhandled event caught: \"%s\"\n", get_type_name<Event>().c_str());
otherfsmDebug(static_cast<typename FSM::derived_t*>(f),
"unhandled event caught in state \"%s\": \"%s\"\n",
get_type_name<SrcState>().c_str(),
get_type_name<Event>().c_str());
return false;
}
};
@ -348,16 +350,23 @@ public:
bool (Derived::*GuardFn)(SrcState&, const Event&) = nullptr>
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 {
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 <typename SrcState>
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;

View File

@ -153,7 +153,7 @@ private:
struct wait_recfg_comp {};
struct s1_source_ho_st : public subfsm_t<s1_source_ho_st> {
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

View File

@ -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);
}