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