Line data Source code
1 : /* 2 : * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #ifndef SRC_BGP_ROUTING_INSTANCE_ROUTE_AGGREGATOR_H_ 6 : #define SRC_BGP_ROUTING_INSTANCE_ROUTE_AGGREGATOR_H_ 7 : 8 : #include <map> 9 : #include <set> 10 : #include <mutex> 11 : 12 : #include "bgp/routing-instance/iroute_aggregator.h" 13 : 14 : #include "bgp/bgp_condition_listener.h" 15 : #include "bgp/bgp_config.h" 16 : #include "bgp/inet/inet_route.h" 17 : #include "bgp/inet/inet_table.h" 18 : #include "bgp/inet6/inet6_route.h" 19 : #include "bgp/inet6/inet6_table.h" 20 : 21 : class AggregateRouteConfig; 22 : 23 : template <typename T> class AggregateRoute; 24 : 25 : template <typename T1, typename T2, typename T3, typename T4> 26 : struct AggregateRouteBase { 27 : typedef T1 TableT; 28 : typedef T2 RouteT; 29 : typedef T3 PrefixT; 30 : typedef T4 AddressT; 31 : }; 32 : 33 : class AggregateInetRoute : public AggregateRouteBase< 34 : InetTable, InetRoute, Ip4Prefix, Ip4Address> { 35 : }; 36 : 37 : class AggregateInet6Route : public AggregateRouteBase< 38 : Inet6Table, Inet6Route, Inet6Prefix, Ip6Address> { 39 : }; 40 : 41 : typedef ConditionMatchPtr AggregateRoutePtr; 42 : 43 : // 44 : // RouteAggregator 45 : // ================ 46 : // 47 : // This class implements the route aggregation for control node. It provides 48 : // APIs to create/delete/update route aggregation config for a routing instance 49 : // An object of this class for the address families that supports route 50 : // aggregation is hooked to routing instance. Currently route aggregation is 51 : // supported for INET and INET6 address family. Support for multiple address 52 : // family is implemented with template for each address family 53 : // 54 : // RouteAggregator uses BgpConditionListener to track more specific routes of 55 : // the configured aggregate prefix and PathResolver to resolve nexthop for 56 : // aggregate route 57 : // 58 : // RouteAggregator uses AddMatchCondition method of BgpConditionListener when 59 : // new route-aggregate prefix is created on routing instance. 60 : // 61 : // AggregateRoute 62 : // ================ 63 : // 64 : // AggregateRoute class implements the MatchCondition for BgpConditionListener 65 : // and implements the Match() to detect the more specific route. 66 : // RouteAggregator stores the match object, AggregateRoute, in 67 : // aggregate_route_map_. 68 : // 69 : // AggregateRoute class stores the contributing routes in "contributors_" list. 70 : // Match is executed in db::DBTable task in each partition context. 71 : // The contributing routes are maintained per partition to ensure concurrent 72 : // access to contributing routes. 73 : // 74 : // On the successful match, AggregateRoute calls AddContributingRoute or 75 : // RemoveContributingRoute based the state and puts the AggregateRoute object 76 : // in update_aggregate_list_ and trigger update_list_trigger_ 77 : // task trigger to process the aggregate route. 78 : // 79 : // In task trigger method for update_list_trigger_ is 80 : // responsible for creating and deleting the Aggregate route. 81 : // Aggregate route is added when first contributing route is added to 82 : // contributors_ and removed when last contributing route is removed 83 : // 84 : // RouteAggregator creates the aggregate route with Aggregate as 85 : // path source and ResolveNexthop as flags. The BgpAttribute on the aggregate 86 : // route contains all the property as specified in the config. Currently, 87 : // config supports specifying only the nexthop for the aggregate route. 88 : // The "ResolveNexthop" flag on the route triggers the PathResolver module to 89 : // resolve the corresponding nexthop and create path with all forwarding info 90 : // based on nexthop specified by config. 91 : // 92 : // AggregateRoute also stores the resulting aggregate route in the object. 93 : // 94 : // Update of the route-aggregate config: 95 : // ==================================== 96 : // 97 : // AggregateRoute provides "UpdateNexthop" method. This method is invoked when 98 : // nexthop is updated in route-aggregate config object. This method deletes the 99 : // executing RouteAggregation path(and stop path resolution) and invokes path 100 : // resolution after updating the BgpAttribute with new nexthop 101 : // 102 : // Delete of the route-aggregate config: 103 : // ==================================== 104 : // 105 : // When route-aggregate is removed from the routing instance for a given prefix, 106 : // RouteAggregator invokes RemoveMatchCondition to initiate the delete process. 107 : // StopAggregateRouteDone callback indicates the RouteAggregator about 108 : // completion of remove process and it triggers unregister_list_trigger_ to 109 : // unregister the match condition. StopAggregateRouteDone callback puts the 110 : // AggregateRoute object in unregister_aggregate_list_. 111 : // 112 : // When the route-aggregate for a given prefix is in delete process, the 113 : // AggregateRoute is still maintained in the aggregate_route_map_. This will 114 : // avoid/ensure new route-aggregate config with same object is handled only 115 : // after successful delete completion of previous AggregateRoute match object 116 : // unregister_list_trigger_ is executed in bgp::Config task and walks the 117 : // unregister_aggregate_list_ to complete the deletion process by calling 118 : // UnregisterMatchCondition(). It also triggers ProcessAggregateRouteConfig to 119 : // apply new config for pending delete prefixes. 120 : // 121 : // DBState: RouteAggregatorState: 122 : // ============================ 123 : // 124 : // RouteAggregator registers with the BgpTable to set the DBState. 125 : // The RouteAggregatorState implements the DBState. 126 : // The DBState is added on both matching/contributing route and aggregate route. 127 : // A route can be both contributing and aggregating route at the same time. 128 : // So two boolean fields are used to indicate the state of the route. 129 : // IsContributingRoute()/IsAggregateRoute API exposed by the RouteAggregator 130 : // access the DBState on the BgpRoute to return the state. 131 : // In addition to the boolean, a reference to the match object is stored in the 132 : // DBState. "aggregating_info_" is the match condition object valid for 133 : // aggregating route and "contributing_info_" refers to the match condition to 134 : // which the route is contributing. 135 : // 136 : // Lifetime management 137 : // =================== 138 : // 139 : // RouteAggregator takes a delete reference to the parent routing instance and 140 : // implements a DeleteActor to manage deletion 141 : // MayDelete() method of DeleteActor for RouteAggregator returns false till 142 : // 1. aggregate_route_map_ is not empty [To check whether config is deleted] 143 : // 2. update_aggregate_list_ is not empty [contributing routes are processed] 144 : // 3. unregister_aggregate_list_ is not empty [unregister of Match condition 145 : // is complete] 146 : // Task triggers update_list_trigger_ and unregister_list_trigger_ will 147 : // call RetryDelete() to complete the delete RouteAggregator object 148 : // 149 : // Concurrency 150 : // =========== 151 : // bgp::RouteAggregation task runs in exclusion to any task that adds/deletes 152 : // path from route. i.e. db::DBTable, bgp::ServiceChain, bgp::StaticRoute and 153 : // bgp::ResolverPath. 154 : // bgp::RouteAggregation runs in exclusion to bgp::Config task 155 : // Match() function of the AggregateRoute class is run in per partition 156 : // db::DBTable task. Hence the "contributors_" maintains the contributing routes 157 : // in per partition list to allow concurrent access 158 : // 159 : template <typename T> 160 : class RouteAggregator : public IRouteAggregator { 161 : public: 162 : typedef typename T::RouteT RouteT; 163 : typedef typename T::PrefixT PrefixT; 164 : typedef typename T::AddressT AddressT; 165 : typedef AggregateRoute<T> AggregateRouteT; 166 : 167 : // Map of AggregateRoute prefix to the AggregateRoute match object 168 : typedef std::map<PrefixT, AggregateRoutePtr> AggregateRouteMap; 169 : 170 : explicit RouteAggregator(RoutingInstance *instance); 171 : ~RouteAggregator(); 172 : 173 : virtual void Initialize(); 174 : 175 : // Config 176 : virtual void ProcessAggregateRouteConfig(); 177 : virtual void UpdateAggregateRouteConfig(); 178 : virtual void FlushAggregateRouteConfig(); 179 : 180 32 : virtual uint32_t GetAggregateRouteCount() const { 181 32 : return aggregate_route_map_.size(); 182 : } 183 5029 : const AggregateRouteMap &aggregate_route_map() const { 184 5029 : return aggregate_route_map_; 185 : } 186 : 187 : Address::Family GetFamily() const; 188 : AddressT GetAddress(IpAddress addr) const; 189 : BgpTable *bgp_table() const; 190 4176 : DBTableBase::ListenerId listener_id() const { 191 4176 : return listener_id_; 192 : } 193 : 194 : bool MayDelete() const; 195 : void ManagedDelete(); 196 : void RetryDelete(); 197 : 198 : void EvaluateAggregateRoute(AggregateRoutePtr entry); 199 : void UnregisterAndResolveRouteAggregate(AggregateRoutePtr entry); 200 : 201 : virtual bool IsAggregateRoute(const BgpRoute *route) const; 202 : virtual bool IsContributingRoute(const BgpRoute *route) const; 203 : 204 : virtual bool FillAggregateRouteInfo(AggregateRouteEntriesInfo *info, 205 : bool summary) const; 206 : 207 : private: 208 : class DeleteActor; 209 : typedef std::set<AggregateRoutePtr> AggregateRouteProcessList; 210 : typedef BgpInstanceConfig::AggregateRouteList AggregateRouteConfigList; 211 : 212 : int CompareAggregateRoute(typename AggregateRouteMap::iterator loc, 213 : AggregateRouteConfigList::iterator it); 214 : void AddAggregateRoute(AggregateRouteConfigList::iterator it); 215 : void DelAggregateRoute(typename AggregateRouteMap::iterator loc); 216 : void UpdateAggregateRoute(typename AggregateRouteMap::iterator loc, 217 : AggregateRouteConfigList::iterator it); 218 : 219 : void LocateAggregateRoutePrefix(const AggregateRouteConfig &cfg); 220 : void RemoveAggregateRoutePrefix(const PrefixT &static_route); 221 : void StopAggregateRouteDone(BgpTable *table, ConditionMatch *info); 222 : 223 : bool ProcessUnregisterList(); 224 : bool ProcessUpdateList(); 225 : 226 : bool RouteListener(DBTablePartBase *root, DBEntryBase *entry); 227 : 228 1007 : RoutingInstance *routing_instance() { return rtinstance_; } 229 : 230 : // Enable/Disable task triggers 231 : virtual void DisableRouteAggregateUpdate(); 232 : virtual void EnableRouteAggregateUpdate(); 233 : virtual size_t GetUpdateAggregateListSize() const; 234 : 235 : virtual void DisableUnregResolveTask(); 236 : virtual void EnableUnregResolveTask(); 237 : virtual size_t GetUnregResolveListSize() const; 238 : 239 : RoutingInstance *rtinstance_; 240 : BgpConditionListener *condition_listener_; 241 : DBTableBase::ListenerId listener_id_; 242 : AggregateRouteMap aggregate_route_map_; 243 : boost::scoped_ptr<TaskTrigger> update_list_trigger_; 244 : boost::scoped_ptr<TaskTrigger> unregister_list_trigger_; 245 : std::mutex mutex_; 246 : AggregateRouteProcessList update_aggregate_list_; 247 : AggregateRouteProcessList unregister_aggregate_list_; 248 : boost::scoped_ptr<DeleteActor> deleter_; 249 : LifetimeRef<RouteAggregator> instance_delete_ref_; 250 : 251 : DISALLOW_COPY_AND_ASSIGN(RouteAggregator); 252 : }; 253 : 254 : typedef RouteAggregator<AggregateInetRoute> RouteAggregatorInet; 255 : typedef RouteAggregator<AggregateInet6Route> RouteAggregatorInet6; 256 : 257 : #endif // SRC_BGP_ROUTING_INSTANCE_ROUTE_AGGREGATOR_H_