Line data Source code
1 : /* 2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. 3 : * Copyright Contributors to the OpenSDN project 4 : */ 5 : #ifndef __ROUTE_PREFERENCE_H__ 6 : #define __ROUTE_PREFERENCE_H__ 7 : 8 : #include <boost/statechart/custom_reaction.hpp> 9 : #include <boost/statechart/event.hpp> 10 : #include <boost/statechart/simple_state.hpp> 11 : #include <boost/statechart/state.hpp> 12 : #include <boost/statechart/state_machine.hpp> 13 : 14 : namespace sc = boost::statechart; 15 : struct Init; 16 : struct WaitForTraffic; 17 : struct TrafficSeen; 18 : struct ActiveActiveState; 19 : class PathPreferenceModule; 20 : 21 : #define PATH_PREFERENCE_TRACE(...) \ 22 : do { \ 23 : PathPreferenceTrace::TraceMsg(PathPreferenceTraceBuf, __FILE__, __LINE__,\ 24 : ##__VA_ARGS__); \ 25 : } while (false) \ 26 : 27 : //Per Path state machine to determine preference of a path based on 28 : //traffic(GARP or flow from VM) 29 : class PathPreferenceSM: 30 : public sc::state_machine<PathPreferenceSM, Init> { 31 : typedef DependencyList<PathPreferenceSM, PathPreferenceSM> PathDependencyList; 32 : public: 33 : static const uint32_t kMinInterval = 4 * 1000; 34 : static const uint32_t kMaxInterval = 32 * 1000; 35 : static const uint32_t kMaxFlapCount = 5; 36 : PathPreferenceSM(Agent *agent, const Peer *peer, 37 : AgentRoute *rt, bool dependent_rt, 38 : const PathPreference &pref); 39 : ~PathPreferenceSM(); 40 3002 : uint32_t sequence() const {return path_preference_.sequence();} 41 1335 : uint32_t preference() const {return path_preference_.preference();} 42 1182 : bool wait_for_traffic() const {return path_preference_.wait_for_traffic();} 43 1820 : bool ecmp() const {return path_preference_.ecmp();} 44 1182 : uint32_t timeout() const { return timeout_;} 45 : 46 : uint64_t last_stable_high_priority_change_at() const { 47 : return last_stable_high_priority_change_at_; 48 : } 49 : uint32_t flap_count() const { return flap_count_;} 50 : 51 1415 : bool is_dependent_rt() const { return is_dependent_rt_;} 52 164 : void set_sequence(uint32_t seq_no) { 53 164 : path_preference_.set_sequence(seq_no); 54 164 : } 55 : 56 458 : void set_preference(uint32_t preference) { 57 458 : path_preference_.set_preference(preference); 58 458 : } 59 : 60 458 : void set_wait_for_traffic(bool wait_for_traffic) { 61 458 : path_preference_.set_wait_for_traffic(wait_for_traffic); 62 458 : } 63 : 64 : void set_ecmp(bool ecmp) { 65 : path_preference_.set_ecmp(ecmp); 66 : } 67 : 68 6066 : void set_seen(bool seen) { 69 6066 : seen_ = seen; 70 6066 : } 71 : 72 386 : void set_max_sequence(uint32_t seq) { 73 386 : max_sequence_ = seq; 74 386 : } 75 : 76 : void set_timeout(uint32_t timeout) { 77 : timeout_ = timeout; 78 : } 79 : 80 : void set_last_stable_high_priority_change_at(uint64_t timestamp) { 81 : last_stable_high_priority_change_at_ = timestamp; 82 : } 83 : 84 3343 : void set_dependent_rt(PathPreferenceSM *sm) { 85 3343 : dependent_rt_.reset(sm); 86 3343 : } 87 : 88 3343 : void set_is_dependent_rt(bool dependent_path) { 89 3343 : is_dependent_rt_ = dependent_path; 90 3343 : } 91 : 92 3343 : void set_dependent_ip(const IpAddress &ip) { 93 3343 : path_preference_.set_dependent_ip(ip); 94 3343 : } 95 : 96 294 : IpAddress dependent_ip() { 97 294 : return path_preference_.dependent_ip(); 98 : } 99 : 100 : bool IsFlap() const; 101 3447 : bool seen() { return seen_; } 102 233 : uint32_t max_sequence() const { return max_sequence_;} 103 : void Process(); 104 : void Delete(); 105 : void Log(std::string state); 106 : void EnqueuePathChange(); 107 : bool Retry(); 108 : void StartRetryTimer(); 109 : void CancelRetryTimer(); 110 : bool RetryTimerRunning(); 111 : void IncreaseRetryTimeout(); 112 : void DecreaseRetryTimeout(); 113 : bool IsPathFlapping() const; 114 : bool IsPathStable() const; 115 : void UpdateFlapTime(); 116 : void UpdateDependentRoute(); 117 : private: 118 : Agent *agent_; 119 : const Peer *peer_; 120 : AgentRoute *rt_; 121 : PathPreference path_preference_; 122 : uint32_t max_sequence_; 123 : bool seen_; 124 : Timer *timer_; 125 : uint32_t timeout_; 126 : uint64_t last_stable_high_priority_change_at_; 127 : uint64_t backoff_timer_fired_time_; 128 : uint32_t flap_count_; 129 : bool is_dependent_rt_; 130 : DependencyRef<PathPreferenceSM, PathPreferenceSM> dependent_rt_; 131 1184 : DEPENDENCY_LIST(PathPreferenceSM, PathPreferenceSM, dependent_routes_); 132 : }; 133 : 134 : //Per Route state machine containing a map for all 135 : //local path state machine data 136 : class PathPreferenceState: public DBState { 137 : public: 138 : typedef std::map<const Peer *, PathPreferenceSM *> PeerPathPreferenceMap; 139 : PathPreferenceState(Agent *agent, AgentRoute *rt_); 140 : ~PathPreferenceState(); 141 : void Process(bool &should_resolve); 142 : PathPreferenceSM *GetSM(const Peer *); 143 : PathPreferenceSM* GetDependentPath(const AgentPath *path) const; 144 : private: 145 : bool GetRouteListenerId(const VrfEntry *vrf, 146 : const Agent::RouteTableType &table, 147 : DBTableBase::ListenerId &rt_id) const; 148 : Agent *agent_; 149 : AgentRoute *rt_; 150 : PeerPathPreferenceMap path_preference_peer_map_; 151 : }; 152 : 153 : //Per VM interface state, containing floating IP 154 : //and static route a interface contains 155 : struct PathPreferenceIntfState : public DBState { 156 : PathPreferenceIntfState(const VmInterface *intf); 157 : struct RouteAddrList { 158 : RouteAddrList(); 159 : RouteAddrList(const Address::Family &family, const IpAddress &ip, 160 : uint32_t plen, const std::string &vrf); 161 : bool operator<(const RouteAddrList &rhs) const; 162 : bool operator==(const RouteAddrList &rhs) const; 163 : 164 : Address::Family family_; 165 : IpAddress ip_; 166 : uint32_t plen_; 167 : std::string vrf_name_; 168 : mutable bool seen_; 169 : }; 170 : uint32_t DependentRouteListSize() const { return dependent_rt_.size(); } 171 : private: 172 : const VmInterface *intf_; 173 : RouteAddrList instance_ip_; 174 : std::set<RouteAddrList> dependent_rt_; 175 : }; 176 : 177 : struct PathPreferenceVrfState: public DBState { 178 74 : PathPreferenceVrfState(DBTableBase::ListenerId uc_rt_id, 179 : DBTableBase::ListenerId evpn_rt_id, 180 : DBTableBase::ListenerId uc6_rt_id, 181 74 : DBTableBase::ListenerId mpls_rt_id): 182 74 : uc_rt_id_(uc_rt_id), evpn_rt_id_(evpn_rt_id), 183 74 : uc6_rt_id_(uc6_rt_id),mpls_rt_id_(mpls_rt_id) {} 184 : DBTableBase::ListenerId uc_rt_id_; 185 : DBTableBase::ListenerId evpn_rt_id_; 186 : DBTableBase::ListenerId uc6_rt_id_; 187 : DBTableBase::ListenerId mpls_rt_id_; 188 : }; 189 : 190 : struct PathPreferenceRouteListener : public DBState { 191 : PathPreferenceRouteListener(Agent *agent, AgentRouteTable *table); 192 : virtual void Delete(); 193 : 194 : void Notify(DBTablePartBase *partition, DBEntryBase *e); 195 : void Init(); 196 : bool DeleteState(DBTablePartBase *partition, DBEntryBase *e); 197 : void Walkdone(DBTable::DBTableWalkRef walk_ref, DBTableBase *partition, 198 : PathPreferenceRouteListener *state); 199 296 : DBTableBase::ListenerId id() const { return id_;} 200 : void ManagedDelete(); 201 296 : void set_deleted() {deleted_ = true;} 202 : bool deleted() const {return deleted_;} 203 : private: 204 : Agent *agent_; 205 : AgentRouteTable *rt_table_; 206 : DBTableBase::ListenerId id_; 207 : LifetimeRef<PathPreferenceRouteListener> table_delete_ref_; 208 : bool deleted_; 209 : DBTable::DBTableWalkRef managed_delete_walk_ref_; 210 : }; 211 : 212 : class PathPreferenceModule { 213 : public: 214 : struct PathPreferenceEventContainer { 215 : IpAddress ip_; 216 : uint32_t plen_; 217 : MacAddress mac_; 218 : uint32_t interface_index_; 219 : uint32_t vrf_index_; 220 : uint32_t vxlan_id_; 221 : boost::intrusive_ptr<const sc::event_base> event; 222 : }; 223 : 224 : PathPreferenceModule(Agent *agent); 225 : void Init(); 226 : void Shutdown(); 227 : void VrfNotify(DBTablePartBase *partition, DBEntryBase *e); 228 : void EnqueueTrafficSeen(IpAddress ip, uint32_t plen, 229 : uint32_t interface_index, uint32_t vrf_index, 230 : const MacAddress &mac); 231 : bool DequeueEvent(PathPreferenceEventContainer e); 232 : Agent *agent() { return agent_;} 233 616 : DBTableBase::ListenerId vrf_id() const { return vrf_id_;} 234 : DBTableBase::ListenerId intf_id() const { return intf_id_;} 235 : void AddUnresolvedPath(PathPreferenceState *sm); 236 : void DeleteUnresolvedPath(PathPreferenceState *sm); 237 : void Resolve(); 238 : private: 239 : Agent *agent_; 240 : DBTableBase::ListenerId vrf_id_; 241 : DBTableBase::ListenerId intf_id_; 242 : WorkQueue<PathPreferenceEventContainer> work_queue_; 243 : std::set<PathPreferenceState *> unresolved_paths_; 244 : }; 245 : #endif