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_POLICY_ROUTING_POLICY_H_ 7 : #define SRC_BGP_ROUTING_POLICY_ROUTING_POLICY_H_ 8 : 9 : #include <boost/scoped_ptr.hpp> 10 : #include <boost/intrusive_ptr.hpp> 11 : #include <boost/shared_ptr.hpp> 12 : #include <sandesh/sandesh_trace.h> 13 : 14 : #include <list> 15 : #include <map> 16 : #include <string> 17 : #include <utility> 18 : #include <vector> 19 : #include <mutex> 20 : #include <atomic> 21 : 22 : #include "base/lifetime.h" 23 : #include "base/util.h" 24 : #include "bgp/bgp_common.h" 25 : #include "db/db_table.h" 26 : 27 : class BgpAttr; 28 : class BgpPath; 29 : class BgpRoute; 30 : class BgpServer; 31 : class BgpTable; 32 : class RoutingPolicyMgr; 33 : class BgpRoutingPolicyConfig; 34 : class RoutingInstance; 35 : class RoutingPolicyMatch; 36 : class RoutingPolicyAction; 37 : class RoutingPolicyTermConfig; 38 : class TaskTrigger; 39 : 40 : // Routing Policy Manager 41 : // This class implements the routing policy for control node. 42 : // It maintains the list of routing policies configured on the system 43 : // It provides API to lookup the routing policy by name. 44 : // 45 : // A mutex is used to serialize access from multiple bgp::ConfigHelper tasks. 46 : // 47 : // It provides two APIs to apply routing policy on the routes belonging to given 48 : // routing instance. 49 : // 1. ApplyRoutingPolicy 50 : // Apply routing policy on the routing instance passed as input. 51 : // To achieve this Routing policy manager walks all the routing tables of 52 : // the routing instance. On each route encountered during the walk, policy 53 : // is evaluated using EvaluateRoutingPolicy. EvaluateRoutingPolicy visits 54 : // all the BgpPath and apply all routing policies of that routing instance 55 : // on that BgpPath. 56 : // 57 : // 2. ExecuteRoutingPolicy 58 : // This function is called on the given route + path from two code path. 59 : // First one is from InsertPath. i.e. when new path is being added to a 60 : // route. 61 : // Second path is from DBTable walk context while applying the routing 62 : // policy on routing instance. This function calls the operator() of the 63 : // policy in input to match and apply the action on successful match. 64 : // 65 : // 66 : // RoutingPolicyManager takes a delete reference of BgpServer. 67 : // 68 : // RoutingPolicy 69 : // 70 : // This represents one Routing Policy in operational data. 71 : // Each routing policy has multiple policy terms (represented using PolicyTerm 72 : // class) represented as ordered list using std::list. 73 : // 74 : // Routing Policy object takes lifetime reference of RoutingPolicyMgr. 75 : // 76 : // Reference to RoutingPolicy object is done using intrusive pointer which 77 : // keeps track of ref_count. 78 : // The DeleteActor of the RoutingPolicy uses this ref_count to allow/disallow 79 : // delete of the RoutingPolicy object. On last dereference of the RoutingPolicy 80 : // object, RetryDelete on the DeleteActor is triggered. 81 : // 82 : // RoutingPolicy is removed from the name-map in RoutingPolicyMgr only in 83 : // Destroy method of DeleteActor. It is possible that config might have revived 84 : // the RoutingPolicy object with same name(with same or different config). 85 : // In such case, RoutingPolicyMgr recreate the routing policy based on the 86 : // new config object. 87 : // 88 : // RoutingPolicy object provided operator() to apply the policy on a 89 : // BgpRoute+BgpPath. In this operator overload function, route is processed 90 : // against each policy term till a terminal rule is encountered. 91 : // A terminal rule is a term where action on successful match is to Reject or 92 : // Accept the route. Return value gives the hint of result of policy apply. 93 : // Result is represented as a pair with first element representing whether the 94 : // match was for terminal rule and second element indicating whether there 95 : // was a policy match. 96 : // 97 : // RoutingPolicy object is updated on config update function in UpdateConfig 98 : // method. This method walks newly configured policy term list and existing 99 : // policy term list and compares the PolicyTerm to see whether 100 : // a. Policy term matches (Done using operator==() function on PolicyTerm). 101 : // If no match is found, new PolicyTerm as per new config is created and 102 : // inserted in to ordered list of PolicyTerm. 103 : // b. New policy Term is inserted 104 : // c. Existing policy term is deleted 105 : // At the end of the update, generation number of the policy term is updated to 106 : // indicate config change to Routing Policy. Routing Instances referring to 107 : // this policy is not triggered from this path. It is expected that 108 : // BgpConfigListener infra would put the RoutingInstance to the change_list when 109 : // the routing policy it is referring undergoes a change. 110 : // 111 : // Routing Instance 112 : // Routing instance maintains ordered list of routing policies that it refers. 113 : // This is represented as std::list of pair<RoutingPolicyPtr, gen-id of policy>. 114 : // Please note RoutingPolicyPtr is an intrusive pointer to RoutingPolicy object. 115 : // 116 : // While processing the routing policies on each routes belonging to this 117 : // instance, each of routing policies are applied till terminal rule is hit. 118 : // BgpRoute is update with all policy actions from the matching policy term. 119 : // Policy action is stored in BgpPath (in flag ond/or in BgpAttr) 120 : // 121 : // Update of the routing instance checks whether the routing policy list on the 122 : // instance has changed. This process checks for following 123 : // a. If a routing policy order is update 124 : // b. If new routing policy(ies) are added to the routing policy list 125 : // c. If existing routing policy(ies) are removed from the routing policy list 126 : // d. If the routing policies that it is referring has undergone config change 127 : // This is done by checking the generation number of routing policy that 128 : // is applied on the routing instance. 129 : // In case the routing policy is updated on the routing instance 130 : // (if either of (a) to (d) above is true), all the BgpTables belonging to the 131 : // routing instance is walked to reapply the routing policy. 132 : // 133 : // BgpRoute/BgpPath 134 : // BgpPath maintains original BgpAttribute that it received in a new field 135 : // called as original_attr_. The path attribute attr_ represents the 136 : // BgpAttribute after applying the policy. 137 : // New flag is introduced to indicate if the path is rejected by routing policy. 138 : // 139 : // PolicyTerm 140 : // Policy Term has two ordered lists 141 : // 1. Match conditions 142 : // 2. Actions 143 : // 144 : // PolicyTerm class provides accessor method to get list of matches and actions. 145 : // It also provides compare function (operator==()) to check whether two policy 146 : // terms matches/same. It would return true if each policy term has same match 147 : // set(ordered list) and same action list(ordered). 148 : // 149 : // Policy action is represented as ordered list of action to be taken on 150 : // successful match. The top of the action list indicates what should be done 151 : // with route on successful match. e.g. Accept/Reject/NextTerm. 152 : // Subsequent entry in this list are the update action to be taken on policy 153 : // match. 154 : // 155 : // Match Condition 156 : // RoutingPolicyMatch is the abstract base class to implement a match condition. 157 : // This abstract class provides Match() function to compare the route + Path 158 : // attribute with match condition. The derived class provides implementation 159 : // to compare the route + attribute with match condition. Another method of this 160 : // class is comparator function operator==(). This method compares whether two 161 : // match conditions are same. This is done by comparing the typeid() (RTTI) and 162 : // calling IsEqual pure virtual method if type ids are same. 163 : // 164 : // All match conditions inherit this RoutingPolicyMatch and provide 165 : // implementation of pure virtual methods. 166 : // In the current release, match is supported on Community and prefix. 167 : // 168 : // MatchCommunity implements match for community value 169 : // MatchPrefix provides templetized implementation for matching prefix. 170 : // Currently PrefixMatchInet and PrefixMatchInet6 implementation is supported 171 : // to match inet and inet6 routes. 172 : // 173 : // Policy Action 174 : // RoutingPolicyAction is the abstract base class for implementing the policy 175 : // action. 176 : // Action is represented as 177 : // RoutingPolicyNexTermAction, 178 : // RoutingPolicyRejectAction, 179 : // RoutingPolicyAcceptAction or 180 : // RoutingPolicyUpdateAction 181 : // This represents NextTerm, Reject, accept and route update action respectively 182 : // RoutingPolicyRejectAction & RoutingPolicyAcceptAction as Terminal actions. 183 : // RoutingPolicyNexTermAction and RoutingPolicyAcceptAction may/may not have 184 : // RoutingPolicyUpdateAction associated with it. 185 : // RoutingPolicyUpdateAction represents the modification done to path attribute 186 : // on successful match. 187 : // RoutingPolicyAction provides comparator function to check whether two actions 188 : // are same. This is done by comparing the typeid() of the object and invoking 189 : // IsEqual when typeid() is same. 190 : // RoutingPolicyUpdateAction which inherits the RoutingPolicyAction provides the 191 : // pure virtual method operator() to apply update action on BgpAttr. 192 : // Currently support for updating the local-pref and community list is supported 193 : // for update action. 194 : // UpdateCommunity supports add/remove/set list of 195 : // community to incoming BgpAttr. 196 : // 197 : class PolicyTerm { 198 : public: 199 : typedef std::vector<RoutingPolicyAction *> ActionList; 200 : typedef std::vector<RoutingPolicyMatch *> MatchList; 201 : PolicyTerm(); 202 : ~PolicyTerm(); 203 : bool terminal() const; 204 : bool ApplyTerm(const BgpRoute *route, 205 : const BgpPath *path, BgpAttr *attr) const; 206 477 : void set_actions(const ActionList &actions) { 207 477 : actions_ = actions; 208 477 : } 209 477 : void set_matches(const MatchList &matches) { 210 477 : matches_ = matches; 211 477 : } 212 2671 : const MatchList &matches() const { 213 2671 : return matches_; 214 : } 215 4211 : const ActionList &actions() const { 216 4211 : return actions_; 217 : } 218 : bool operator==(const PolicyTerm &term) const; 219 : 220 : private: 221 : MatchList matches_; 222 : ActionList actions_; 223 : }; 224 : 225 : class RoutingPolicy { 226 : public: 227 : typedef boost::shared_ptr<PolicyTerm> PolicyTermPtr; 228 : typedef std::list<PolicyTermPtr> RoutingPolicyTermList; 229 : typedef std::pair<bool, bool> PolicyResult; 230 : RoutingPolicy(std::string name, BgpServer *server, 231 : RoutingPolicyMgr *mgr, 232 : const BgpRoutingPolicyConfig *config); 233 : virtual ~RoutingPolicy(); 234 : void ProcessConfig(); 235 : void UpdateConfig(const BgpRoutingPolicyConfig *config); 236 : void ClearConfig(); 237 : void Shutdown(); 238 : 239 : bool MayDelete() const; 240 : void RetryDelete(); 241 : void ManagedDelete(); 242 : LifetimeActor *deleter(); 243 : const LifetimeActor *deleter() const; 244 : bool deleted() const; 245 : 246 278 : const std::string &name() const { return name_; } 247 : const BgpRoutingPolicyConfig *config() const { return config_; } 248 : const RoutingPolicyMgr *manager() const { return mgr_; } 249 : 250 : BgpServer *server() { return server_; } 251 : const BgpServer *server() const { return server_; } 252 : 253 1271 : RoutingPolicyTermList *terms() { return &terms_; } 254 773 : const RoutingPolicyTermList &terms() const { return terms_; } 255 198 : void add_term(PolicyTermPtr term) { 256 198 : terms_.push_back(term); 257 198 : } 258 : 259 : PolicyResult operator()(const BgpRoute *route, 260 : const BgpPath *path, BgpAttr *attr) const; 261 279 : uint32_t generation() const { return generation_; } 262 13 : uint32_t refcount() const { return refcount_; } 263 : 264 : private: 265 : friend class RoutingPolicyMgr; 266 : class DeleteActor; 267 : friend void intrusive_ptr_add_ref(RoutingPolicy *policy); 268 : friend void intrusive_ptr_release(RoutingPolicy *policy); 269 : 270 : PolicyTermPtr BuildTerm(const RoutingPolicyTermConfig &term); 271 : std::string name_; 272 : BgpServer *server_; 273 : RoutingPolicyMgr *mgr_; 274 : const BgpRoutingPolicyConfig *config_; 275 : boost::scoped_ptr<DeleteActor> deleter_; 276 : LifetimeRef<RoutingPolicy> manager_delete_ref_; 277 : 278 : // Updated when routing policy undergoes a change 279 : std::atomic<uint32_t> refcount_; 280 : uint32_t generation_; 281 : RoutingPolicyTermList terms_; 282 : }; 283 : 284 1724 : inline void intrusive_ptr_add_ref(RoutingPolicy *policy) { 285 1724 : policy->refcount_++; 286 1728 : return; 287 : } 288 : 289 1726 : inline void intrusive_ptr_release(RoutingPolicy *policy) { 290 1726 : int prev = policy->refcount_.fetch_sub(1); 291 1726 : if (prev == 1) { 292 163 : if (policy->MayDelete()) 293 163 : policy->RetryDelete(); 294 : } 295 1726 : } 296 : 297 : class RoutingPolicyMgr { 298 : public: 299 : typedef std::map<std::string, RoutingPolicy*> RoutingPolicyList; 300 : typedef RoutingPolicyList::iterator name_iterator; 301 : typedef RoutingPolicyList::const_iterator const_name_iterator; 302 : typedef std::map<BgpTable *, 303 : DBTable::DBTableWalkRef> RoutingPolicyWalkRequests; 304 : 305 : explicit RoutingPolicyMgr(BgpServer *server); 306 : virtual ~RoutingPolicyMgr(); 307 : SandeshTraceBufferPtr trace_buffer() const { return trace_buf_; } 308 : 309 : name_iterator name_begin() { return routing_policies_.begin(); } 310 0 : name_iterator name_end() { return routing_policies_.end(); } 311 : name_iterator name_lower_bound(const std::string &name) { 312 : return routing_policies_.lower_bound(name); 313 : } 314 : const_name_iterator name_cbegin() { return routing_policies_.begin(); } 315 22 : const_name_iterator name_cend() { return routing_policies_.end(); } 316 6 : const_name_iterator name_clower_bound(const std::string &name) { 317 6 : return routing_policies_.lower_bound(name); 318 : } 319 : 320 646 : RoutingPolicy *GetRoutingPolicy(const std::string &name) { 321 646 : name_iterator it; 322 646 : if ((it = routing_policies_.find(name)) != routing_policies_.end()) { 323 485 : return it->second; 324 : } 325 161 : return NULL; 326 : } 327 : const RoutingPolicy *GetRoutingPolicy(const std::string &name) const { 328 : const_name_iterator it; 329 : if ((it = routing_policies_.find(name)) != routing_policies_.end()) { 330 : return it->second; 331 : } 332 : return NULL; 333 : } 334 : 335 : virtual RoutingPolicy *CreateRoutingPolicy( 336 : const BgpRoutingPolicyConfig *config); 337 : void UpdateRoutingPolicy(const BgpRoutingPolicyConfig *config); 338 : virtual void DeleteRoutingPolicy(const std::string &name); 339 : 340 : 341 : bool deleted(); 342 : void ManagedDelete(); 343 : 344 : void DestroyRoutingPolicy(RoutingPolicy *policy); 345 : 346 : size_t count() const { return routing_policies_.size(); } 347 43 : BgpServer *server() { return server_; } 348 : const BgpServer *server() const { return server_; } 349 : LifetimeActor *deleter(); 350 : 351 : RoutingPolicy::PolicyResult ExecuteRoutingPolicy( 352 : const RoutingPolicy *policy, const BgpRoute *route, 353 : const BgpPath *path, BgpAttr *attr) const; 354 : 355 : // Update the routing policy list on attach point 356 : bool UpdateRoutingPolicyList(const RoutingPolicyConfigList &cfg_list, 357 : RoutingPolicyAttachList *oper_list); 358 : 359 : // RoutingInstance is updated with new set of policies. This function 360 : // applies that policy on each route of this routing instance 361 : void ApplyRoutingPolicy(RoutingInstance *instance); 362 : 363 : void RequestWalk(BgpTable *table); 364 : void WalkDone(DBTableBase *dbtable); 365 : bool EvaluateRoutingPolicy(DBTablePartBase *root, DBEntryBase *entry); 366 : 367 : private: 368 : class DeleteActor; 369 : 370 : BgpServer *server_; 371 : std::mutex mutex_; 372 : RoutingPolicyList routing_policies_; 373 : boost::scoped_ptr<DeleteActor> deleter_; 374 : LifetimeRef<RoutingPolicyMgr> server_delete_ref_; 375 : RoutingPolicyWalkRequests routing_policy_sync_; 376 : SandeshTraceBufferPtr trace_buf_; 377 : }; 378 : 379 : #endif // SRC_BGP_ROUTING_POLICY_ROUTING_POLICY_H_