LCOV - code coverage report
Current view: top level - bgp/routing-policy - routing_policy.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 36 37 97.3 %
Date: 2026-06-04 02:06:09 Functions: 16 17 94.1 %
Legend: Lines: hit not hit

          Line data    Source code
       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 <sandesh/sandesh_trace.h>
      12             : 
      13             : #include <list>
      14             : #include <map>
      15             : #include <string>
      16             : #include <utility>
      17             : #include <vector>
      18             : #include <mutex>
      19             : #include <atomic>
      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;
      32             : class BgpRoutingPolicyConfig;
      33             : class RoutingInstance;
      34             : class RoutingPolicyMatch;
      35             : class RoutingPolicyAction;
      36             : class RoutingPolicyTermConfig;
      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;
     205         477 :     void set_actions(const ActionList &actions) {
     206         477 :         actions_ = actions;
     207         477 :     }
     208         477 :     void set_matches(const MatchList &matches) {
     209         477 :         matches_ = matches;
     210         477 :     }
     211        2670 :     const MatchList &matches() const {
     212        2670 :         return matches_;
     213             :     }
     214        4212 :     const ActionList &actions() const {
     215        4212 :         return actions_;
     216             :     }
     217             :     bool operator==(const PolicyTerm &term) const;
     218             : 
     219             : private:
     220             :     MatchList matches_;
     221             :     ActionList actions_;
     222             : };
     223             : 
     224             : class RoutingPolicy {
     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,
     231             :                     const BgpRoutingPolicyConfig *config);
     232             :     virtual ~RoutingPolicy();
     233             :     void ProcessConfig();
     234             :     void UpdateConfig(const BgpRoutingPolicyConfig *config);
     235             :     void ClearConfig();
     236             :     void Shutdown();
     237             : 
     238             :     bool MayDelete() const;
     239             :     void RetryDelete();
     240             :     void ManagedDelete();
     241             :     LifetimeActor *deleter();
     242             :     const LifetimeActor *deleter() const;
     243             :     bool deleted() const;
     244             : 
     245         279 :     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             : 
     252        1271 :     RoutingPolicyTermList *terms() { return &terms_; }
     253         777 :     const RoutingPolicyTermList &terms() const { return terms_; }
     254         198 :     void add_term(PolicyTermPtr term) {
     255         198 :         terms_.push_back(term);
     256         198 :     }
     257             : 
     258             :     PolicyResult operator()(const BgpRoute *route,
     259             :                             const BgpPath *path, BgpAttr *attr) const;
     260         280 :     uint32_t generation() const { return generation_; }
     261          13 :     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             : 
     269             :     PolicyTermPtr BuildTerm(const RoutingPolicyTermConfig &term);
     270             :     std::string name_;
     271             :     BgpServer *server_;
     272             :     RoutingPolicyMgr *mgr_;
     273             :     const BgpRoutingPolicyConfig *config_;
     274             :     boost::scoped_ptr<DeleteActor> deleter_;
     275             :     LifetimeRef<RoutingPolicy> manager_delete_ref_;
     276             : 
     277             :     // Updated when routing policy undergoes a change
     278             :     std::atomic<uint32_t> refcount_;
     279             :     uint32_t generation_;
     280             :     RoutingPolicyTermList terms_;
     281             : };
     282             : 
     283        1724 : inline void intrusive_ptr_add_ref(RoutingPolicy *policy) {
     284        1724 :     policy->refcount_++;
     285        1733 :     return;
     286             : }
     287             : 
     288        1732 : inline void intrusive_ptr_release(RoutingPolicy *policy) {
     289        1732 :     int prev = policy->refcount_.fetch_sub(1);
     290        1732 :     if (prev == 1) {
     291         163 :         if (policy->MayDelete())
     292         163 :             policy->RetryDelete();
     293             :     }
     294        1732 : }
     295             : 
     296             : class RoutingPolicyMgr {
     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 *,
     302             :             DBTable::DBTableWalkRef> RoutingPolicyWalkRequests;
     303             : 
     304             :     explicit RoutingPolicyMgr(BgpServer *server);
     305             :     virtual ~RoutingPolicyMgr();
     306             :     SandeshTraceBufferPtr trace_buffer() const { return trace_buf_; }
     307             : 
     308             :     name_iterator name_begin() { return routing_policies_.begin(); }
     309           0 :     name_iterator name_end() { return routing_policies_.end(); }
     310             :     name_iterator name_lower_bound(const std::string &name) {
     311             :         return routing_policies_.lower_bound(name);
     312             :     }
     313             :     const_name_iterator name_cbegin() { return routing_policies_.begin(); }
     314          22 :     const_name_iterator name_cend() { return routing_policies_.end(); }
     315           6 :     const_name_iterator name_clower_bound(const std::string &name) {
     316           6 :         return routing_policies_.lower_bound(name);
     317             :     }
     318             : 
     319         646 :     RoutingPolicy *GetRoutingPolicy(const std::string &name) {
     320         646 :         name_iterator it;
     321         646 :         if ((it = routing_policies_.find(name)) != routing_policies_.end()) {
     322         485 :             return it->second;
     323             :         }
     324         161 :         return NULL;
     325             :     }
     326             :     const RoutingPolicy *GetRoutingPolicy(const std::string &name) const {
     327             :         const_name_iterator it;
     328             :         if ((it = routing_policies_.find(name)) != routing_policies_.end()) {
     329             :             return it->second;
     330             :         }
     331             :         return NULL;
     332             :     }
     333             : 
     334             :     virtual RoutingPolicy *CreateRoutingPolicy(
     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          43 :     BgpServer *server() { return server_; }
     347             :     const BgpServer *server() const { return server_; }
     348             :     LifetimeActor *deleter();
     349             : 
     350             :     RoutingPolicy::PolicyResult ExecuteRoutingPolicy(
     351             :         const RoutingPolicy *policy, const BgpRoute *route,
     352             :         const BgpPath *path, BgpAttr *attr) const;
     353             : 
     354             :     // Update the routing policy list on attach point
     355             :     bool UpdateRoutingPolicyList(const RoutingPolicyConfigList &cfg_list,
     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);
     364             :     bool EvaluateRoutingPolicy(DBTablePartBase *root, DBEntryBase *entry);
     365             : 
     366             : private:
     367             :     class DeleteActor;
     368             : 
     369             :     BgpServer *server_;
     370             :     std::mutex mutex_;
     371             :     RoutingPolicyList routing_policies_;
     372             :     boost::scoped_ptr<DeleteActor> deleter_;
     373             :     LifetimeRef<RoutingPolicyMgr> server_delete_ref_;
     374             :     RoutingPolicyWalkRequests routing_policy_sync_;
     375             :     SandeshTraceBufferPtr trace_buf_;
     376             : };
     377             : 
     378             : #endif  // SRC_BGP_ROUTING_POLICY_ROUTING_POLICY_H_

Generated by: LCOV version 1.14