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