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