Line data Source code
1 : /* 2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. 3 : * Copyright Contributors to the OpenSDN project 4 : */ 5 : 6 : #ifndef vnsw_agent_route_walker_hpp 7 : #define vnsw_agent_route_walker_hpp 8 : 9 : #include <atomic> 10 : 11 : #include <boost/intrusive_ptr.hpp> 12 : #include <boost/array.hpp> 13 : 14 : #include <cmn/agent_cmn.h> 15 : #include <cmn/agent.h> 16 : #include <sandesh/sandesh_trace.h> 17 : 18 : /** 19 : * The infrastructure is to support and manage VRF walks along with 20 : * corresponding route walks. 21 : * Following type of walks can be issued: 22 : * 1) ALL VRF walk - Use API StartVrfWalk() 23 : * 2) Specific VRF walk - Use StartRouteWalk(vrf_entry) API 24 : * 3) Specialized walk - Issue StartVrfWalk() and override VrfWalkNotify() to 25 : * select a set of VRF to walk on. By default VrfWalkNotify starts walks on 26 : * all route table. 27 : * RouteWalkNotify() - This should be overriden to listen and act on route 28 : * entry notifications. By default it ignores the request. 29 : * 4) Only VRF walk - Use API StartVRFWalk and override VrfWalkNotify() to not 30 : * start route table walk. In this way only VRF entries can be traversed 31 : * without route walks issued. 32 : * 33 : * Multiple objects of this class can have separate parallel walks. 34 : * There is no more walk cancellations to start a new walk. 35 : * Same walk reference can be used to restart walks with different context. 36 : * Each AgentRouteWalker instance will have its own walker reference on vrf 37 : * table. Walk on this table will result in more walk references created for 38 : * route tables. These references are stored in DB State keyed with Vrf walk 39 : * reference. 40 : * 41 : * How to use the walker? 42 : * 43 : * Either walker can be derived or directly instantiated. Then the object needs 44 : * to be registered with agent route walker manager. Once the scope of walker is 45 : * over release of this walker should be done via agent routewalk manager. 46 : * 47 : * Walk References in walker: 48 : * Walker maintain two kind of references. First is the walk reference to walk 49 : * VRF table. This is part of walker itself. 50 : * Second is a set of references which is used to walk route tables. 51 : * These references are stored in state created on each vrf entry. 52 : * State is keyed with walker pointer and has an array of walk references. 53 : * Route walk references are stored in state because for each vrf there can be 54 : * different references and (vrf+walker) is the key to identify them. 55 : * 56 : * Agent Route Walk Manager 57 : * ------------------------ 58 : * 59 : * Manager keeps a track of all walkers under a instrusive pointer list. 60 : * It has also maintained a listener on agent's vrf table. There is a state 61 : * maintained on each VRF which contains a map of walker to route table walker 62 : * references. 63 : * DB state is created by agent route walk manager and is unique for a vrf 64 : * entry. Each instance of AgentRouteWalker will insert its vrf_walk_ref in this 65 : * state and maintain route table references with walk tracker in same. 66 : * 67 : * On receiving vrf delete manager can refer to state and invoke release of all 68 : * walk references. 69 : * 70 : */ 71 : 72 : #define AGENT_DBWALK_TRACE_BUF "AgentDBwalkTrace" 73 : extern SandeshTraceBufferPtr AgentDBwalkTraceBuf; 74 : 75 : #define AGENT_DBWALK_TRACE(obj, ...) do { \ 76 : obj::TraceMsg(AgentDBwalkTraceBuf, __FILE__, __LINE__, ##__VA_ARGS__); \ 77 : } while (false) 78 : 79 : class AgentRouteWalker; 80 : class AgentRouteWalkerManager; 81 : void intrusive_ptr_add_ref(AgentRouteWalker *w); 82 : void intrusive_ptr_release(AgentRouteWalker *w); 83 : typedef boost::intrusive_ptr<AgentRouteWalker> AgentRouteWalkerPtr; 84 : 85 : struct RouteWalkerDBState : DBState { 86 : typedef boost::array<DBTable::DBTableWalkRef, Agent::ROUTE_TABLE_MAX> RouteWalkRef; 87 : typedef std::map<AgentRouteWalkerPtr, RouteWalkRef> AgentRouteWalkerRefMap; 88 : typedef AgentRouteWalkerRefMap::iterator AgentRouteWalkerRefMapIter; 89 : typedef AgentRouteWalkerRefMap::const_iterator AgentRouteWalkerRefMapConstIter; 90 : 91 : RouteWalkerDBState(); 92 : AgentRouteWalkerRefMap walker_ref_map_; 93 : }; 94 : 95 : class AgentRouteWalker { 96 : public: 97 : static const int kInvalidWalkCount = 0; 98 : typedef boost::function<void()> WalkDone; 99 : typedef boost::function<void(VrfEntry *)> RouteWalkDoneCb; 100 : typedef std::map<const VrfEntry *, std::atomic<int> > VrfRouteWalkCountMap; 101 : 102 : virtual ~AgentRouteWalker(); 103 : 104 : void StartVrfWalk(); 105 : //Route table walk for specified VRF 106 : void StartRouteWalk(VrfEntry *vrf); 107 : 108 : virtual bool VrfWalkNotify(DBTablePartBase *partition, DBEntryBase *e); 109 : virtual bool RouteWalkNotify(DBTablePartBase *partition, DBEntryBase *e); 110 : 111 : virtual void VrfWalkDone(DBTableBase *part); 112 : virtual void RouteWalkDone(DBTableBase *part); 113 : 114 : //Walk done callbacks 115 : void WalkDoneCallback(WalkDone cb); 116 : void RouteWalkDoneForVrfCallback(RouteWalkDoneCb cb); 117 : 118 : //Helpers 119 : int walk_count() const {return walk_count_;} 120 15 : bool IsWalkCompleted() const {return (walk_count_ == kInvalidWalkCount);} 121 0 : bool IsValidDeleteWalkRef() const { 122 0 : return delete_walk_ref_.get() != NULL; 123 : } 124 0 : bool IsValidVrfWalkRef() const { 125 0 : return vrf_walk_ref_.get() != NULL; 126 : } 127 0 : bool IsDeregisterDone() const { return deregister_done_;} 128 : bool AreAllWalksDone() const; 129 : bool AreAllRouteWalksDone(const VrfEntry *vrf) const; 130 : bool IsRouteTableWalkCompleted(RouteWalkerDBState *state); 131 732 : AgentRouteWalkerManager *mgr() {return mgr_;} 132 853 : Agent *agent() const {return agent_;} 133 0 : uint32_t refcount() const { return refcount_; } 134 : 135 : protected: 136 : friend class AgentRouteWalkerManager; 137 : friend void intrusive_ptr_add_ref(AgentRouteWalker *w); 138 : friend void intrusive_ptr_release(AgentRouteWalker *w); 139 : AgentRouteWalker(const std::string &name, Agent *agent); 140 328 : void set_mgr(AgentRouteWalkerManager *mgr) {mgr_ = mgr;} 141 : 142 : private: 143 : void Callback(VrfEntry *vrf); 144 : void OnRouteTableWalkCompleteForVrf(VrfEntry *vrf); 145 : void DecrementWalkCount(); 146 : void DecrementRouteWalkCount(const VrfEntry *vrf); 147 1592 : void IncrementWalkCount() {walk_count_++;} 148 : void IncrementRouteWalkCount(const VrfEntry *vrf); 149 : void WalkTable(AgentRouteTable *table, 150 : DBTable::DBTableWalkRef &route_table_walk_ref); 151 : DBTable::DBTableWalkRef AllocateRouteTableReferences(AgentRouteTable *table); 152 : void VrfWalkDoneInternal(DBTableBase *part); 153 : void RouteWalkDoneInternal(DBTableBase *part, AgentRouteWalkerPtr ptr); 154 : DBTable::DBTableWalkRef LocateRouteTableWalkRef(const VrfEntry *vrf, 155 : RouteWalkerDBState *state, 156 : AgentRouteTable *table); 157 : RouteWalkerDBState *LocateRouteWalkerDBState(VrfEntry *vrf); 158 656 : DBTable::DBTableWalkRef &vrf_walk_ref() { 159 656 : return vrf_walk_ref_; 160 : } 161 656 : DBTable::DBTableWalkRef &delete_walk_ref() { 162 656 : return delete_walk_ref_; 163 : } 164 : //Walk to release all references. 165 : void ReleaseVrfWalkReference(); 166 : bool Deregister(DBTablePartBase *partition, DBEntryBase *e); 167 : static void DeregisterDone(AgentRouteWalkerPtr walker); 168 : 169 : Agent *agent_; 170 : std::string name_; 171 : VrfRouteWalkCountMap route_walk_count_; 172 : std::atomic<int> walk_count_; 173 : WalkDone walk_done_cb_; 174 : RouteWalkDoneCb route_walk_done_for_vrf_cb_; 175 : DBTable::DBTableWalkRef vrf_walk_ref_; 176 : AgentRouteWalkerManager *mgr_; 177 : bool deregister_done_; 178 : DBTable::DBTableWalkRef delete_walk_ref_; 179 : mutable std::atomic<uint32_t> refcount_; 180 : DISALLOW_COPY_AND_ASSIGN(AgentRouteWalker); 181 : }; 182 : 183 : class AgentRouteWalkerManager { 184 : public: 185 : typedef std::set<AgentRouteWalkerPtr> WalkRefList; 186 : typedef std::set<AgentRouteWalkerPtr>::iterator WalkRefListIter; 187 : 188 : AgentRouteWalkerManager(Agent *agent); 189 : virtual ~AgentRouteWalkerManager(); 190 : Agent *agent() {return agent_;} 191 : 192 : void RegisterWalker(AgentRouteWalker *walker); 193 : void ReleaseWalker(AgentRouteWalker *walker); 194 : void Shutdown(); 195 : void TryUnregister(); 196 : //UT helper 197 2 : uint8_t walk_ref_list_size() const {return walk_ref_list_.size();} 198 : 199 : protected: 200 : friend class AgentRouteWalker; 201 : void VrfNotify(DBTablePartBase *partition, DBEntryBase *e); 202 : void RemoveWalker(AgentRouteWalkerPtr walker); 203 : void ValidateAgentRouteWalker(AgentRouteWalkerPtr walker) const; 204 : RouteWalkerDBState *CreateState(VrfEntry *vrf); 205 : void RemoveWalkReferencesInVrf(RouteWalkerDBState *state, VrfEntry *vrf); 206 2886 : DBTable::ListenerId vrf_listener_id() const { 207 2886 : return vrf_listener_id_; 208 : } 209 : 210 : private: 211 : DBTable::ListenerId vrf_listener_id_; 212 : Agent *agent_; 213 : WalkRefList walk_ref_list_; 214 : bool marked_for_deletion_; 215 : DISALLOW_COPY_AND_ASSIGN(AgentRouteWalkerManager); 216 : }; 217 : 218 : #endif