Line data Source code
1 : /* 2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #ifndef SRC_BGP_ROUTING_INSTANCE_ROUTEPATH_REPLICATOR_H_ 6 : #define SRC_BGP_ROUTING_INSTANCE_ROUTEPATH_REPLICATOR_H_ 7 : 8 : #include <boost/ptr_container/ptr_map.hpp> 9 : #include <sandesh/sandesh_trace.h> 10 : 11 : #include <list> 12 : #include <map> 13 : #include <set> 14 : #include <string> 15 : #include <vector> 16 : #include <mutex> 17 : 18 : #include "base/lifetime.h" 19 : #include "base/util.h" 20 : #include "bgp/bgp_path.h" 21 : #include "db/db_entry.h" 22 : #include "db/db_table.h" 23 : 24 : class BgpRoute; 25 : class BgpServer; 26 : class BgpTable; 27 : class RtGroup; 28 : class RoutePathReplicator; 29 : class RouteTarget; 30 : 31 : // 32 : // This keeps track of a RoutePathReplicator's listener state for a BgpTable. 33 : // An instance is created for each VRF table and for the VPN table. 34 : // 35 : // An entry for VPN table is created when RoutePathReplicator is initialized. 36 : // An entry for a VRF table is created when processing a Join for the first 37 : // export route target for the VRF. 38 : // TableState is removed when a Bgp table is deleted. 39 : // TableState takes a delete reference to the BgpTable and DeleteActor of the 40 : // TableState manages the unregister of this listener from the BgpTable and 41 : // delete of TableState object. 42 : // 43 : // A TableState entry keeps track of all the export route targets for a VRF 44 : // by maintaining the GroupList. TableState cannot be deleted if GroupList 45 : // is non-empty and table has replicated routes. Replicated routes are tracked 46 : // using the DBStateCount of this listener 47 : // 48 : class TableState { 49 : public: 50 : typedef std::set<RtGroup *> GroupList; 51 : 52 : TableState(RoutePathReplicator *replicator, BgpTable *table); 53 : ~TableState(); 54 : 55 : void ManagedDelete(); 56 : bool MayDelete() const; 57 : void RetryDelete(); 58 : 59 : LifetimeActor *deleter(); 60 : const LifetimeActor *deleter() const; 61 : bool deleted() const; 62 : 63 : void AddGroup(RtGroup *group); 64 : void RemoveGroup(RtGroup *group); 65 : const RtGroup *FindGroup(RtGroup *group) const; 66 4 : bool empty() const { return list_.empty(); } 67 : 68 4589814 : DBTableBase::ListenerId listener_id() const { return listener_id_; } 69 254181 : void set_listener_id(DBTableBase::ListenerId listener_id) { 70 254181 : assert(listener_id_ == DBTableBase::kInvalidId); 71 254181 : listener_id_ = listener_id; 72 254181 : } 73 : 74 : uint32_t route_count() const; 75 : 76 508404 : RoutePathReplicator *replicator() { 77 508404 : return replicator_; 78 : } 79 : 80 : const RoutePathReplicator *replicator() const { 81 : return replicator_; 82 : } 83 : 84 2 : BgpTable *table() const { 85 2 : return table_; 86 : } 87 : 88 276816 : BgpTable *table() { 89 276816 : return table_; 90 : } 91 : 92 276910 : const DBTable::DBTableWalkRef &walk_ref() const { 93 276910 : return walk_ref_; 94 : } 95 : 96 356909 : DBTable::DBTableWalkRef &walk_ref() { 97 356909 : return walk_ref_; 98 : } 99 : 100 22611 : void set_walk_ref(DBTable::DBTableWalkRef walk_ref) { 101 22611 : walk_ref_ = walk_ref; 102 22611 : } 103 : 104 : private: 105 : class DeleteActor; 106 : RoutePathReplicator *replicator_; 107 : BgpTable *table_; 108 : DBTableBase::ListenerId listener_id_; 109 : boost::scoped_ptr<DeleteActor> deleter_; 110 : LifetimeRef<TableState> table_delete_ref_; 111 : GroupList list_; 112 : DBTable::DBTableWalkRef walk_ref_; 113 : 114 : DISALLOW_COPY_AND_ASSIGN(TableState); 115 : }; 116 : 117 : // 118 : // This keeps track of the replication state for a route in the primary table. 119 : // The ReplicatedRtPathList is a set of SecondaryRouteInfo, where each element 120 : // represents a secondary path in a secondary table. An entry is added to the 121 : // set when a path is replicated to a secondary table removed when it's not 122 : // replicated anymore. 123 : // 124 : // Changes to ReplicatedRtPathList may be triggered by changes in the primary 125 : // route, changes in the export targets of the primary table or changes in the 126 : // import targets of secondary tables. 127 : // 128 : // A RtReplicated is deleted when the route in the primary table is no longer 129 : // replicated to any secondary tables. 130 : // 131 : class RtReplicated : public DBState { 132 : public: 133 : struct SecondaryRouteInfo { 134 : public: 135 : BgpTable *table_; 136 : const IPeer *peer_; 137 : uint32_t path_id_; 138 : BgpPath::PathSource src_; 139 : BgpRoute *rt_; 140 : 141 944056 : SecondaryRouteInfo(BgpTable *table, const IPeer *peer, 142 : uint32_t path_id, BgpPath::PathSource src, BgpRoute *rt) 143 944056 : : table_(table), 144 944056 : peer_(peer), 145 944056 : path_id_(path_id), 146 944056 : src_(src), 147 944056 : rt_(rt) { 148 944056 : } 149 3968833 : int CompareTo(const SecondaryRouteInfo &rhs) const { 150 3968833 : KEY_COMPARE(table_, rhs.table_); 151 998994 : KEY_COMPARE(peer_, rhs.peer_); 152 863686 : KEY_COMPARE(path_id_, rhs.path_id_); 153 852609 : KEY_COMPARE(src_, rhs.src_); 154 852609 : KEY_COMPARE(rt_, rhs.rt_); 155 851239 : return 0; 156 : } 157 3541263 : bool operator<(const SecondaryRouteInfo &rhs) const { 158 3541263 : return (CompareTo(rhs) < 0); 159 : } 160 428362 : bool operator>(const SecondaryRouteInfo &rhs) const { 161 428362 : return (CompareTo(rhs) > 0); 162 : } 163 : 164 : std::string ToString() const; 165 : }; 166 : 167 : typedef std::set<SecondaryRouteInfo> ReplicatedRtPathList; 168 : 169 : explicit RtReplicated(RoutePathReplicator *replicator); 170 : 171 : void AddRouteInfo(BgpTable *table, BgpRoute *rt, 172 : ReplicatedRtPathList::const_iterator it); 173 : void DeleteRouteInfo(BgpTable *table, BgpRoute *rt, 174 : ReplicatedRtPathList::const_iterator it); 175 : 176 1431386 : const ReplicatedRtPathList &GetList() const { return replicate_list_; } 177 1430682 : ReplicatedRtPathList *GetMutableList() { return &replicate_list_; } 178 : std::vector<std::string> GetTableNameList(const BgpPath *path) const; 179 : 180 : private: 181 : RoutePathReplicator *replicator_; 182 : ReplicatedRtPathList replicate_list_; 183 : }; 184 : 185 : // 186 : // This class implements functionality to import and export BgpPaths between 187 : // VRF BgpTables and a VPN BgpTable for a given address family. The exporting 188 : // table is referred to as the primary table and the importing tables are 189 : // referred to as secondary tables. 190 : // 191 : // The rules for importing and exporting paths are based on route targets of 192 : // the VRF tables and the route targets in VPN routes. They can be summarized 193 : // as follows: 194 : // 195 : // o The VPN table unconditionally imports routes from all VRF tables. 196 : // o The VPN table potentially exports routes to all VRF tables. 197 : // o A path in a VRF table is considered to have export targets of the table. 198 : // o A path in the VPN table has route targets in it's attributes. 199 : // o A path in a primary table is imported into a secondary table if one or 200 : // o more of the targets for the path is in the list of import targets for 201 : // the secondary table. 202 : // o Secondary paths are never exported to other secondary tables. 203 : // 204 : // Dependency tracking mechanisms are needed to implement replication in an 205 : // an efficient manner. RoutePathReplicator does the following: 206 : // 207 : // 1. When an export target is added to or removed from a VRF table, walk all 208 : // routes in the VRF table to re-evaluate the new set of secondary paths. 209 : // The DBTableWalkMgr provides this functionality. 210 : // 2. When an import target is added to or removed from a VRF table, walk all 211 : // VRF tables that have the target in question as an export target. The 212 : // list of tables that export a target is maintained in the RTargetGroupMgr. 213 : // This list is updated by the replicator (by calling RTargetGroupMgr APIs) 214 : // based on configuration changes in the routing instance. 215 : // 3. When an import target is added to or removed from a VRF tables, walk all 216 : // VPN routes with the target in question. This dependency is maintained 217 : // by RTargetGroupMgr. 218 : // 4. When a route is updated, calculate new set of secondary paths by going 219 : // through all VRF tables that import one of the targets for the route in 220 : // question. The list of VRF tables is obtained from the RTargetGroupMgr. 221 : // 5. When a route is updated, remove secondary paths that are not required 222 : // anymore. The list of previous secondary paths for a primary route is 223 : // maintained using RtReplicated and reconciled/synchronized with the new 224 : // list obtained from 4. 225 : // 226 : // The TableStateList keeps track of the TableState for each VRF from which 227 : // routes could be exported. It also has an entry for the TableState for the 228 : // VPN table. This entry is created when the replicator is initialized and 229 : // deleted during shutdown. 230 : // 231 : // The UnregTableList keeps track of tables for which we need to delete the 232 : // TableState. Requests are enqueued from the db::DBTable task when a table 233 : // walk finishes and the TableState is empty. 234 : // 235 : // A mutex is used to serialize access from multiple bgp::ConfigHelper tasks. 236 : // 237 : class RoutePathReplicator { 238 : public: 239 : RoutePathReplicator(BgpServer *server, Address::Family family); 240 : virtual ~RoutePathReplicator(); 241 : 242 : void Initialize(); 243 : void Join(BgpTable *table, const RouteTarget &rt, bool import); 244 : void Leave(BgpTable *table, const RouteTarget &rt, bool import); 245 : 246 : std::vector<std::string> GetReplicatedTableNameList(const BgpTable *table, 247 : const BgpRoute *route, const BgpPath *path) const; 248 : const RtReplicated *GetReplicationState(BgpTable *table, 249 : BgpRoute *rt) const; 250 : 251 : private: 252 : friend class ReplicationTest; 253 : friend class BGPaaSRDTest; 254 : friend class RtReplicated; 255 : friend class TableState; 256 : 257 : typedef std::map<BgpTable *, TableState *> TableStateList; 258 : typedef std::set<BgpTable *> UnregTableList; 259 : 260 : void RequestWalk(BgpTable *table); 261 : void BulkReplicationDone(DBTableBase *dbtable); 262 : bool UnregisterTables(); 263 : 264 : TableState *AddTableState(BgpTable *table, RtGroup *group = NULL); 265 : void RemoveTableState(BgpTable *table, RtGroup *group); 266 : void DeleteTableState(BgpTable *table); 267 : void UnregisterTableState(BgpTable *table); 268 : TableState *FindTableState(BgpTable *table); 269 : const TableState *FindTableState(const BgpTable *table) const; 270 : 271 : void JoinVpnTable(RtGroup *group); 272 : void LeaveVpnTable(RtGroup *group); 273 : 274 : bool RouteListener(TableState *ts, DBTablePartBase *root, 275 : DBEntryBase *entry); 276 : void DeleteSecondaryPath(BgpTable *table, BgpRoute *rt, 277 : const RtReplicated::SecondaryRouteInfo &rtinfo); 278 : void DBStateSync(BgpTable *table, TableState *ts, BgpRoute *rt, 279 : RtReplicated *dbstate, 280 : const RtReplicated::ReplicatedRtPathList *future); 281 : 282 9002350 : BgpServer *server() { return server_; } 283 7998023 : Address::Family family() const { return family_; } 284 : const BgpServer *server() const { return server_; } 285 : 286 : BgpServer *server_; 287 : std::mutex mutex_; 288 : TableStateList table_state_list_; 289 : Address::Family family_; 290 : BgpTable *vpn_table_; 291 : SandeshTraceBufferPtr trace_buf_; 292 : 293 : DISALLOW_COPY_AND_ASSIGN(RoutePathReplicator); 294 : }; 295 : 296 : #endif // SRC_BGP_ROUTING_INSTANCE_ROUTEPATH_REPLICATOR_H_