OpenSDN source code
bfd_state_machine.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 CodiLime, Inc. All rights reserved.
3  */
4 
5 #include "bfd/bfd_common.h"
6 #include "bfd/bfd_session.h"
8 
9 #include <list>
10 #include <boost/optional.hpp>
11 #include <boost/bind/bind.hpp>
12 #include <boost/statechart/event.hpp>
13 #include <boost/statechart/transition.hpp>
14 #include <boost/statechart/state_machine.hpp>
15 #include <boost/statechart/simple_state.hpp>
16 #include <boost/statechart/custom_reaction.hpp>
17 #include <boost/mpl/list.hpp>
18 
19 #include "base/logging.h"
20 
21 using namespace boost::placeholders;
22 namespace mpl = boost::mpl;
23 namespace sc = boost::statechart;
24 
25 namespace BFD {
26 
27 struct EvRecvInit : sc::event<EvRecvInit> {};
28 struct EvRecvDown : sc::event<EvRecvDown> {};
29 struct EvRecvUp : sc::event<EvRecvUp> {};
30 struct EvRecvAdminDown : sc::event<EvRecvAdminDown> {};
31 struct EvTimeout : sc::event<EvTimeout> {};
32 // struct EvReset : sc::event<EvReset> {};
33 
34 struct BFDStateAware {
35  virtual BFDState getState() const = 0;
36  virtual ~BFDStateAware(){}
37 };
38 
39 struct InitState;
40 struct DownState;
41 struct UpState;
43  public sc::state_machine<StateMachineImpl, DownState> {
44  public:
45  explicit StateMachineImpl(EventManager *evm, Session *session) :
46  evm_(evm), session_(session) {
47  initiate();
48  }
49 
50  void Notify(BFDState state) {
51  LOG(DEBUG, "StateMachine state: " << state);
52  if (cb_.is_initialized() && session_) {
53  (cb_.get())(session_->key(), GetState());
54  } else {
55  LOG(ERROR, "StateMachine cb initialized: "
56  << cb_.is_initialized() << " session: " << session_);
57  }
58  }
59 
61  BFDState old_state = GetState();
62  switch (state) {
63  case kAdminDown:
64  process_event(EvRecvAdminDown());
65  break;
66  case kDown:
67  process_event(EvRecvDown());
68  break;
69  case kInit:
70  process_event(EvRecvInit());
71  break;
72  case kUp:
73  process_event(EvRecvUp());
74  break;
75  }
76  if (old_state != GetState()) {
77  Notify(GetState());
78  }
79  }
80 
81  void ProcessTimeout() {
82  BFDState old_state = GetState();
83  process_event(EvTimeout());
84  if (old_state != GetState())
85  Notify(GetState());
86  }
87 
89  return state_cast<const BFDStateAware &>().getState();
90  }
91 
92  void SetCallback(boost::optional<ChangeCb> cb) {
93  cb_ = cb;
94  }
95 
96  private:
97  boost::optional<ChangeCb> cb_;
100 };
101 
102 struct InitState : sc::simple_state<InitState, StateMachineImpl>,
103  BFDStateAware {
104  typedef mpl::list<
105  sc::transition<EvRecvInit, UpState>,
106  sc::transition<EvRecvDown, InitState>,
107  sc::transition<EvRecvUp, UpState>,
108  sc::transition<EvRecvAdminDown, DownState>,
109  sc::transition<EvTimeout, DownState>
111  virtual BFDState getState() const { return kInit; }
112  virtual ~InitState() {}
113 };
114 
115 struct UpState : sc::simple_state<UpState, StateMachineImpl>, BFDStateAware {
116  typedef mpl::list<
117  sc::transition<EvRecvInit, UpState>,
118  sc::transition<EvRecvDown, DownState>,
119  sc::transition<EvRecvUp, UpState>,
120  sc::transition<EvRecvAdminDown, DownState>,
121  sc::transition<EvTimeout, DownState>
123  virtual BFDState getState() const { return kUp; }
124  virtual ~UpState() {}
125 };
126 
127 struct DownState : sc::simple_state<DownState, StateMachineImpl>,
128  BFDStateAware {
129  typedef mpl::list<
130  sc::transition<EvRecvInit, UpState>,
131  sc::transition<EvRecvDown, InitState>,
132  sc::transition<EvRecvUp, DownState>,
133  sc::transition<EvRecvAdminDown, DownState>,
134  sc::transition<EvTimeout, DownState>
136  virtual BFDState getState() const { return kDown; }
137  virtual ~DownState() {}
138 };
139 
141  return new StateMachineImpl(evm, session);
142 }
143 
144 } // namespace BFD
void SetCallback(boost::optional< ChangeCb > cb)
void ProcessRemoteState(BFDState state)
boost::optional< ChangeCb > cb_
void Notify(BFDState state)
StateMachineImpl(EventManager *evm, Session *session)
static EventManager evm
#define LOG(_Level, _Msg)
Definition: logging.h:34
Definition: bfd_client.h:9
BFDState
Definition: bfd_common.h:21
@ kUp
Definition: bfd_common.h:22
@ kDown
Definition: bfd_common.h:22
@ kAdminDown
Definition: bfd_common.h:22
@ kInit
Definition: bfd_common.h:22
StateMachine * CreateStateMachine(EventManager *evm, Session *session)
virtual BFDState getState() const =0
mpl::list< sc::transition< EvRecvInit, UpState >, sc::transition< EvRecvDown, InitState >, sc::transition< EvRecvUp, DownState >, sc::transition< EvRecvAdminDown, DownState >, sc::transition< EvTimeout, DownState > > reactions
virtual BFDState getState() const
mpl::list< sc::transition< EvRecvInit, UpState >, sc::transition< EvRecvDown, InitState >, sc::transition< EvRecvUp, UpState >, sc::transition< EvRecvAdminDown, DownState >, sc::transition< EvTimeout, DownState > > reactions
virtual BFDState getState() const
mpl::list< sc::transition< EvRecvInit, UpState >, sc::transition< EvRecvDown, DownState >, sc::transition< EvRecvUp, UpState >, sc::transition< EvRecvAdminDown, DownState >, sc::transition< EvTimeout, DownState > > reactions
virtual BFDState getState() const