OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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.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 namespace mpl = boost::mpl;
22 namespace sc = boost::statechart;
23 
24 namespace BFD {
25 
26 struct EvRecvInit : sc::event<EvRecvInit> {};
27 struct EvRecvDown : sc::event<EvRecvDown> {};
28 struct EvRecvUp : sc::event<EvRecvUp> {};
29 struct EvRecvAdminDown : sc::event<EvRecvAdminDown> {};
30 struct EvTimeout : sc::event<EvTimeout> {};
31 // struct EvReset : sc::event<EvReset> {};
32 
33 struct BFDStateAware {
34  virtual BFDState getState() const = 0;
35  virtual ~BFDStateAware(){}
36 };
37 
38 struct InitState;
39 struct DownState;
40 struct UpState;
42  public sc::state_machine<StateMachineImpl, DownState> {
43  public:
44  explicit StateMachineImpl(EventManager *evm, Session *session) :
45  evm_(evm), session_(session) {
46  initiate();
47  }
48 
49  void Notify(BFDState state) {
50  LOG(DEBUG, "StateMachine state: " << state);
51  if (cb_.is_initialized() && session_) {
52  (cb_.get())(session_->key(), GetState());
53  } else {
54  LOG(ERROR, "StateMachine cb initialized: "
55  << cb_.is_initialized() << " session: " << session_);
56  }
57  }
58 
60  BFDState old_state = GetState();
61  switch (state) {
62  case kAdminDown:
63  process_event(EvRecvAdminDown());
64  break;
65  case kDown:
66  process_event(EvRecvDown());
67  break;
68  case kInit:
69  process_event(EvRecvInit());
70  break;
71  case kUp:
72  process_event(EvRecvUp());
73  break;
74  }
75  if (old_state != GetState()) {
76  Notify(GetState());
77  }
78  }
79 
80  void ProcessTimeout() {
81  BFDState old_state = GetState();
82  process_event(EvTimeout());
83  if (old_state != GetState())
84  Notify(GetState());
85  }
86 
88  return state_cast<const BFDStateAware &>().getState();
89  }
90 
91  void SetCallback(boost::optional<ChangeCb> cb) {
92  cb_ = cb;
93  }
94 
95  private:
96  boost::optional<ChangeCb> cb_;
99 };
100 
101 struct InitState : sc::simple_state<InitState, StateMachineImpl>,
102  BFDStateAware {
103  typedef mpl::list<
104  sc::transition<EvRecvInit, UpState>,
105  sc::transition<EvRecvDown, InitState>,
106  sc::transition<EvRecvUp, UpState>,
107  sc::transition<EvRecvAdminDown, DownState>,
108  sc::transition<EvTimeout, DownState>
110  virtual BFDState getState() const { return kInit; }
111  virtual ~InitState() {}
112 };
113 
114 struct UpState : sc::simple_state<UpState, StateMachineImpl>, BFDStateAware {
115  typedef mpl::list<
116  sc::transition<EvRecvInit, UpState>,
117  sc::transition<EvRecvDown, DownState>,
118  sc::transition<EvRecvUp, UpState>,
119  sc::transition<EvRecvAdminDown, DownState>,
120  sc::transition<EvTimeout, DownState>
122  virtual BFDState getState() const { return kUp; }
123  virtual ~UpState() {}
124 };
125 
126 struct DownState : sc::simple_state<DownState, StateMachineImpl>,
127  BFDStateAware {
128  typedef mpl::list<
129  sc::transition<EvRecvInit, UpState>,
130  sc::transition<EvRecvDown, InitState>,
131  sc::transition<EvRecvUp, DownState>,
132  sc::transition<EvRecvAdminDown, DownState>,
133  sc::transition<EvTimeout, DownState>
135  virtual BFDState getState() const { return kDown; }
136  virtual ~DownState() {}
137 };
138 
140  return new StateMachineImpl(evm, session);
141 }
142 
143 } // namespace BFD
const SessionKey & key() const
Definition: bfd_session.cc:271
void Notify(BFDState state)
boost::optional< ChangeCb > cb_
virtual BFDState getState() const
mpl::list< sc::transition< EvRecvInit, UpState >, sc::transition< EvRecvDown, InitState >, sc::transition< EvRecvUp, DownState >, sc::transition< EvRecvAdminDown, DownState >, sc::transition< EvTimeout, DownState > > reactions
StateMachineImpl(EventManager *evm, Session *session)
StateMachine * CreateStateMachine(EventManager *evm, Session *session)
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
BFDState
Definition: bfd_common.h:21
mpl::list< sc::transition< EvRecvInit, UpState >, sc::transition< EvRecvDown, InitState >, sc::transition< EvRecvUp, UpState >, sc::transition< EvRecvAdminDown, DownState >, sc::transition< EvTimeout, DownState > > reactions
void SetCallback(boost::optional< ChangeCb > cb)
#define LOG(_Level, _Msg)
Definition: logging.h:33
virtual BFDState getState() const
void ProcessRemoteState(BFDState state)
virtual BFDState getState() const =0
static EventManager evm