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