LCOV - code coverage report
Current view: top level - bgp/routing-policy - routing_policy.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 22 363 6.1 %
Date: 2026-09-21 02:11:39 Functions: 8 44 18.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include "bgp/routing-policy/routing_policy.h"
       6             : 
       7             : #include <boost/assign/list_of.hpp>
       8             : #include <boost/foreach.hpp>
       9             : 
      10             : #include "base/task_annotations.h"
      11             : #include "base/task_trigger.h"
      12             : #include "bgp/bgp_config.h"
      13             : #include "bgp/bgp_factory.h"
      14             : #include "bgp/bgp_server.h"
      15             : #include "bgp/bgp_table.h"
      16             : #include "bgp/routing-instance/routing_instance.h"
      17             : #include "bgp/routing-policy/routing_policy_action.h"
      18             : #include "bgp/routing-policy/routing_policy_match.h"
      19             : 
      20             : 
      21             : class RoutingPolicyMgr::DeleteActor : public LifetimeActor {
      22             : public:
      23          32 :     explicit DeleteActor(RoutingPolicyMgr *manager)
      24          32 :         : LifetimeActor(manager->server_->lifetime_manager()),
      25          32 :           manager_(manager) {
      26          32 :     }
      27          32 :     virtual bool MayDelete() const {
      28          32 :         return true;
      29             :     }
      30          32 :     virtual void Shutdown() {
      31          32 :     }
      32          32 :     virtual void Destroy() {
      33             :         // memory is deallocated by BgpServer scoped_ptr.
      34          32 :         manager_->server_delete_ref_.Reset(NULL);
      35          32 :     }
      36             : 
      37             : private:
      38             :     RoutingPolicyMgr *manager_;
      39             : };
      40             : 
      41          32 : RoutingPolicyMgr::RoutingPolicyMgr(BgpServer *server) :
      42          32 :         server_(server),
      43          32 :         deleter_(new DeleteActor(this)),
      44          32 :         server_delete_ref_(this, server->deleter()),
      45          64 :         trace_buf_(SandeshTraceBufferCreate("RoutingPolicyMgr", 500)) {
      46          32 : }
      47             : 
      48          64 : RoutingPolicyMgr::~RoutingPolicyMgr() {
      49          64 : }
      50             : 
      51          32 : void RoutingPolicyMgr::ManagedDelete() {
      52          32 :     deleter_->Delete();
      53          32 : }
      54             : 
      55           0 : LifetimeActor *RoutingPolicyMgr::deleter() {
      56           0 :     return deleter_.get();
      57             : }
      58             : 
      59           0 : bool RoutingPolicyMgr::deleted() {
      60           0 :     return deleter()->IsDeleted();
      61             : }
      62             : 
      63           0 : RoutingPolicy *RoutingPolicyMgr::CreateRoutingPolicy(
      64             :                                  const BgpRoutingPolicyConfig *config) {
      65           0 :     RoutingPolicy *policy = GetRoutingPolicy(config->name());
      66             : 
      67           0 :     if (policy) {
      68           0 :         if (policy->deleted()) {
      69           0 :             return NULL;
      70             :         }
      71           0 :         return policy;
      72             :     }
      73             : 
      74           0 :     policy = BgpStaticObjectFactory::Create<RoutingPolicy>(
      75           0 :         config->name(), server_, this, config);
      76           0 :     routing_policies_.insert(std::make_pair(config->name(), policy));
      77           0 :     policy->ProcessConfig();
      78             : 
      79           0 :     return policy;
      80             : }
      81             : 
      82           0 : void RoutingPolicyMgr::UpdateRoutingPolicy(
      83             :                                    const BgpRoutingPolicyConfig *config) {
      84           0 :     CHECK_CONCURRENCY("bgp::Config");
      85             : 
      86           0 :     RoutingPolicy *policy = GetRoutingPolicy(config->name());
      87           0 :     if (policy && policy->deleted()) {
      88           0 :         return;
      89           0 :     } else if (!policy) {
      90           0 :         return;
      91             :     }
      92             : 
      93           0 :     policy->UpdateConfig(config);
      94             : }
      95             : 
      96             : //
      97             : // Concurrency: BGP Config task
      98             : //
      99             : // Trigger deletion of a particular routing-policy
     100             : //
     101           0 : void RoutingPolicyMgr::DeleteRoutingPolicy(const std::string &name) {
     102           0 :     CHECK_CONCURRENCY("bgp::Config");
     103             : 
     104           0 :     RoutingPolicy *policy = GetRoutingPolicy(name);
     105             : 
     106           0 :     if (policy && policy->deleted()) {
     107           0 :         return;
     108           0 :     } else if (!policy) {
     109           0 :         return;
     110             :     }
     111             : 
     112           0 :     policy->ClearConfig();
     113             : 
     114           0 :     policy->ManagedDelete();
     115             : }
     116             : 
     117             : //
     118             : // Concurrency: Called from BGP config task manager
     119             : //
     120           0 : void RoutingPolicyMgr::DestroyRoutingPolicy(RoutingPolicy *policy) {
     121           0 :     CHECK_CONCURRENCY("bgp::Config");
     122             : 
     123           0 :     const std::string name = policy->name();
     124           0 :     routing_policies_.erase(name);
     125           0 :     delete policy;
     126             : 
     127           0 :     if (deleted()) return;
     128             : 
     129             :     const BgpRoutingPolicyConfig *config
     130           0 :         = server()->config_manager()->FindRoutingPolicy(name);
     131           0 :     if (config) {
     132           0 :         CreateRoutingPolicy(config);
     133           0 :         return;
     134             :     }
     135           0 : }
     136             : 
     137             : // Given a routing instance re-evaluate routes/paths by applying routing policy
     138             : // Walks all the tables of the given routing instance and apply the policy
     139             : // This function puts the table into the walk request queue and triggers the
     140             : // task to start the actual walk
     141           0 : void RoutingPolicyMgr::ApplyRoutingPolicy(RoutingInstance *instance) {
     142           0 :     CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
     143             : 
     144           0 :     std::scoped_lock lock(mutex_);
     145           0 :     BOOST_FOREACH(RoutingInstance::RouteTableList::value_type &entry,
     146             :                   instance->GetTables()) {
     147           0 :         BgpTable *table = entry.second;
     148           0 :         if (table->IsRoutingPolicySupported())
     149           0 :             RequestWalk(table);
     150             :     }
     151           0 : }
     152             : 
     153             : // On a given path of the route, apply the policy
     154           0 : RoutingPolicy::PolicyResult RoutingPolicyMgr::ExecuteRoutingPolicy(
     155             :                              const RoutingPolicy *policy, const BgpRoute *route,
     156             :                              const BgpPath *path, BgpAttr *attr) const {
     157           0 :     return (*policy)(route, path, attr);
     158             : }
     159             : 
     160             : //
     161             : // Concurrency: Called in the context of the DB partition task.
     162             : // On a given route, apply routing policy
     163             : // Walk through all the paths of the given route, and evaluate the result of the
     164             : // routing policy
     165             : //
     166           0 : bool RoutingPolicyMgr::EvaluateRoutingPolicy(DBTablePartBase *root,
     167             :                                              DBEntryBase *entry) {
     168           0 :     CHECK_CONCURRENCY("db::DBTable");
     169             : 
     170           0 :     BgpTable *table = static_cast<BgpTable *>(root->parent());
     171           0 :     BgpRoute *route = static_cast<BgpRoute *>(entry);
     172           0 :     const RoutingInstance *rtinstance = table->routing_instance();
     173           0 :     if (route->IsDeleted()) return true;
     174             : 
     175           0 :     bool sort_and_notify = false;
     176           0 :     const Path *prev_front = route->front();
     177           0 :     for (Route::PathList::iterator it = route->GetPathList().begin();
     178           0 :         it != route->GetPathList().end(); ++it) {
     179           0 :         BgpPath *path = static_cast<BgpPath *>(it.operator->());
     180           0 :         uint32_t old_flags = path->GetFlags();
     181           0 :         const BgpAttr *old_attr = path->GetAttr();
     182           0 :         rtinstance->ProcessRoutingPolicy(route, path);
     183           0 :         if ((sort_and_notify == false) &&
     184           0 :             (old_flags != path->GetFlags() || old_attr != path->GetAttr())) {
     185           0 :             sort_and_notify = true;
     186             :         }
     187             :     }
     188             : 
     189           0 :     if (sort_and_notify) {
     190           0 :         route->Sort(&BgpTable::PathSelection, prev_front);
     191           0 :         root->Notify(entry);
     192             :     }
     193           0 :     return true;
     194             : }
     195             : 
     196             : //
     197             : //
     198           0 : bool RoutingPolicyMgr::UpdateRoutingPolicyList(
     199             :                                         const RoutingPolicyConfigList &cfg_list,
     200             :                                         RoutingPolicyAttachList *oper_list) {
     201           0 :     CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
     202             : 
     203           0 :     std::scoped_lock lock(mutex_);
     204           0 :     bool update_policy = false;
     205             :     // Number of routing policies is different
     206           0 :     if (oper_list->size() != cfg_list.size())
     207           0 :         update_policy = true;
     208             : 
     209           0 :     RoutingPolicyAttachList::iterator oper_it = oper_list->begin(), oper_next;
     210           0 :     RoutingPolicyConfigList::const_iterator config_it = cfg_list.begin();
     211           0 :     while (oper_it != oper_list->end() &&
     212           0 :            config_it != cfg_list.end()) {
     213             :         // Compare the configured routing policies on the routing-instance
     214             :         // with operational data.
     215           0 :         if (oper_it->first->name() == config_it->routing_policy_) {
     216           0 :             if (oper_it->second != oper_it->first->generation()) {
     217             :                 // Policy content is updated
     218           0 :                 oper_it->second = oper_it->first->generation();
     219           0 :                 update_policy = true;
     220             :             }
     221           0 :             ++oper_it;
     222           0 :             ++config_it;
     223             :         } else {
     224             :             // Policy Order is updated or new policy is added
     225             :             // or policy is deleted
     226             :             RoutingPolicy *policy =
     227           0 :                 GetRoutingPolicy(config_it->routing_policy_);
     228           0 :             if (policy) {
     229           0 :                 *oper_it = std::make_pair(policy, policy->generation());
     230           0 :                 ++oper_it;
     231           0 :                 ++config_it;
     232           0 :                 update_policy = true;
     233             :             } else {
     234             :                 // points to routing policy that doesn't exists
     235             :                 // will revisit in next config notification
     236           0 :                 ++config_it;
     237             :             }
     238             :         }
     239             :     }
     240           0 :     for (oper_next = oper_it; oper_it != oper_list->end();
     241           0 :          oper_it = oper_next) {
     242             :         // Existing policy(ies) are removed
     243           0 :         ++oper_next;
     244           0 :         oper_list->erase(oper_it);
     245           0 :         update_policy = true;
     246             :     }
     247           0 :     for (; config_it != cfg_list.end(); ++config_it) {
     248             :         // new policy(ies) are added
     249           0 :         RoutingPolicy *policy = GetRoutingPolicy(config_it->routing_policy_);
     250           0 :         if (policy) {
     251           0 :             oper_list->push_back(std::make_pair(policy, policy->generation()));
     252             :         }
     253           0 :         update_policy = true;
     254             :     }
     255             : 
     256           0 :     return update_policy;
     257           0 : }
     258             : 
     259             : void
     260           0 : RoutingPolicyMgr::RequestWalk(BgpTable *table) {
     261           0 :     CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
     262           0 :     RoutingPolicyWalkRequests::iterator it = routing_policy_sync_.find(table);
     263           0 :     if (it == routing_policy_sync_.end()) {
     264             :         DBTable::DBTableWalkRef walk_ref = table->AllocWalker(
     265             :             boost::bind(&RoutingPolicyMgr::EvaluateRoutingPolicy, this, _1, _2),
     266           0 :             boost::bind(&RoutingPolicyMgr::WalkDone, this, _2));
     267           0 :         table->WalkTable(walk_ref);
     268           0 :         routing_policy_sync_.insert(std::make_pair(table, walk_ref));
     269           0 :     } else {
     270           0 :         table->WalkAgain(it->second);
     271             :     }
     272           0 : }
     273             : 
     274             : void
     275           0 : RoutingPolicyMgr::WalkDone(DBTableBase *dbtable) {
     276           0 :     CHECK_CONCURRENCY("db::Walker");
     277           0 :     BgpTable *table = static_cast<BgpTable *>(dbtable);
     278           0 :     RoutingPolicyWalkRequests::iterator it = routing_policy_sync_.find(table);
     279           0 :     assert(it != routing_policy_sync_.end());
     280           0 :     DBTable::DBTableWalkRef walk_ref = it->second;
     281           0 :     routing_policy_sync_.erase(it);
     282           0 :     table->ReleaseWalker(walk_ref);
     283           0 : }
     284             : 
     285             : class RoutingPolicy::DeleteActor : public LifetimeActor {
     286             : public:
     287           0 :     DeleteActor(BgpServer *server, RoutingPolicy *parent)
     288           0 :             : LifetimeActor(server->lifetime_manager()), parent_(parent) {
     289           0 :     }
     290           0 :     virtual bool MayDelete() const {
     291           0 :         return parent_->MayDelete();
     292             :     }
     293           0 :     virtual void Shutdown() {
     294           0 :         parent_->Shutdown();
     295           0 :     }
     296           0 :     virtual void Destroy() {
     297           0 :         parent_->mgr_->DestroyRoutingPolicy(parent_);
     298           0 :     }
     299             : 
     300             : private:
     301             :     RoutingPolicy *parent_;
     302             : };
     303             : 
     304           0 : RoutingPolicy::RoutingPolicy(std::string name, BgpServer *server,
     305             :                                  RoutingPolicyMgr *mgr,
     306           0 :                                  const BgpRoutingPolicyConfig *config)
     307           0 :     : name_(name), server_(server), mgr_(mgr), config_(config),
     308           0 :       deleter_(new DeleteActor(server, this)),
     309           0 :       manager_delete_ref_(this, mgr->deleter()), generation_(0) {
     310           0 :     refcount_ = 0;
     311           0 : }
     312             : 
     313           0 : RoutingPolicy::~RoutingPolicy() {
     314           0 :     terms_.clear();
     315           0 : }
     316             : 
     317           0 : RoutingPolicy::PolicyTermPtr RoutingPolicy::BuildTerm(
     318             :     const RoutingPolicyTermConfig &cfg_term) {
     319           0 :     PolicyTerm::ActionList actions;
     320           0 :     PolicyTerm::MatchList matches;
     321             : 
     322           0 :     if (!cfg_term.match.community_match.empty()) {
     323             :         MatchCommunity *community = new MatchCommunity(
     324           0 :             cfg_term.match.community_match,
     325           0 :             cfg_term.match.community_match_all);
     326           0 :         matches.push_back(community);
     327             :     }
     328             : 
     329           0 :     if (!cfg_term.match.ext_community_match.empty()) {
     330             :         MatchExtCommunity *ext_community = new MatchExtCommunity(
     331           0 :             cfg_term.match.ext_community_match,
     332           0 :             cfg_term.match.ext_community_match_all);
     333           0 :         matches.push_back(ext_community);
     334             :     }
     335             : 
     336           0 :     if (!cfg_term.match.protocols_match.empty()) {
     337             :         MatchProtocol *protocol =
     338           0 :          new MatchProtocol(cfg_term.match.protocols_match);
     339           0 :         matches.push_back(protocol);
     340             :     }
     341             : 
     342           0 :     if (!cfg_term.match.prefixes_to_match.empty()) {
     343           0 :         PrefixMatchConfigList inet_prefix_list;
     344           0 :         PrefixMatchConfigList inet6_prefix_list;
     345           0 :         BOOST_FOREACH(PrefixMatchConfig match,
     346             :             cfg_term.match.prefixes_to_match) {
     347           0 :             boost::system::error_code ec;
     348           0 :             Ip4Address ip4;
     349             :             int plen;
     350           0 :             ec = Ip4PrefixParse(match.prefix_to_match, &ip4, &plen);
     351           0 :             if (ec.value() == 0) {
     352           0 :                 inet_prefix_list.push_back(match);
     353             :             } else {
     354           0 :                 Ip6Address ip6;
     355           0 :                 ec = Inet6PrefixParse(match.prefix_to_match, &ip6, &plen);
     356           0 :                 if (ec.value() == 0) {
     357           0 :                     inet6_prefix_list.push_back(match);
     358             :                 }
     359             :             }
     360           0 :         }
     361           0 :         if (!inet_prefix_list.empty()) {
     362           0 :             MatchPrefixInet *prefix = new MatchPrefixInet(inet_prefix_list);
     363           0 :             matches.push_back(prefix);
     364             :         }
     365           0 :         if (!inet6_prefix_list.empty()) {
     366           0 :             MatchPrefixInet6 *prefix = new MatchPrefixInet6(inet6_prefix_list);
     367           0 :             matches.push_back(prefix);
     368             :         }
     369           0 :     }
     370             : 
     371             :     // Build the Action object
     372           0 :     if (cfg_term.action.action == RoutingPolicyActionConfig::REJECT) {
     373           0 :         RoutingPolicyRejectAction *action = new RoutingPolicyRejectAction();
     374           0 :         actions.push_back(action);
     375           0 :     } else if (cfg_term.action.action == RoutingPolicyActionConfig::NEXT_TERM) {
     376           0 :         RoutingPolicyNexTermAction *action = new RoutingPolicyNexTermAction();
     377           0 :         actions.push_back(action);
     378           0 :     } else if (cfg_term.action.action == RoutingPolicyActionConfig::ACCEPT) {
     379           0 :         RoutingPolicyAcceptAction *action = new RoutingPolicyAcceptAction();
     380           0 :         actions.push_back(action);
     381             :     }
     382             : 
     383           0 :     if (!cfg_term.action.update.aspath_expand.empty()) {
     384             :         UpdateAsPath *expand_aspath =
     385           0 :             new UpdateAsPath(cfg_term.action.update.aspath_expand);
     386           0 :         actions.push_back(expand_aspath);
     387             :     }
     388             : 
     389           0 :     if (!cfg_term.action.update.community_set.empty()) {
     390             :         UpdateCommunity *set_comm =
     391           0 :             new UpdateCommunity(cfg_term.action.update.community_set, "set");
     392           0 :         actions.push_back(set_comm);
     393             :     }
     394             : 
     395           0 :     if (!cfg_term.action.update.community_remove.empty()) {
     396             :         UpdateCommunity *remove_comm =
     397           0 :             new UpdateCommunity(cfg_term.action.update.community_remove, "remove");
     398           0 :         actions.push_back(remove_comm);
     399             :     }
     400             : 
     401           0 :     if (!cfg_term.action.update.community_add.empty()) {
     402             :         UpdateCommunity *add_comm =
     403           0 :             new UpdateCommunity(cfg_term.action.update.community_add, "add");
     404           0 :         actions.push_back(add_comm);
     405             :     }
     406             : 
     407           0 :     if (!cfg_term.action.update.ext_community_set.empty()) {
     408             :         UpdateExtCommunity *set_comm = new UpdateExtCommunity(
     409           0 :                 cfg_term.action.update.ext_community_set, "set");
     410           0 :         actions.push_back(set_comm);
     411             :     }
     412             : 
     413           0 :     if (!cfg_term.action.update.ext_community_remove.empty()) {
     414             :         UpdateExtCommunity *remove_comm = new UpdateExtCommunity(
     415           0 :                 cfg_term.action.update.ext_community_remove, "remove");
     416           0 :         actions.push_back(remove_comm);
     417             :     }
     418             : 
     419           0 :     if (!cfg_term.action.update.ext_community_add.empty()) {
     420             :         UpdateExtCommunity *add_comm = new UpdateExtCommunity(
     421           0 :                 cfg_term.action.update.ext_community_add, "add");
     422           0 :         actions.push_back(add_comm);
     423             :     }
     424             : 
     425           0 :     if (cfg_term.action.update.local_pref) {
     426             :         UpdateLocalPref *local_pref =
     427           0 :             new UpdateLocalPref(cfg_term.action.update.local_pref);
     428           0 :         actions.push_back(local_pref);
     429             :     }
     430             : 
     431           0 :     if (cfg_term.action.update.med) {
     432             :         UpdateMed *med =
     433           0 :             new UpdateMed(cfg_term.action.update.med);
     434           0 :         actions.push_back(med);
     435             :     }
     436             : 
     437           0 :     PolicyTermPtr ret_term;
     438           0 :     if (!actions.empty() || !matches.empty()) {
     439           0 :         ret_term = PolicyTermPtr(new PolicyTerm());
     440           0 :         ret_term->set_actions(actions);
     441           0 :         ret_term->set_matches(matches);
     442             :     }
     443             : 
     444           0 :     return ret_term;
     445           0 : }
     446             : 
     447           0 : void RoutingPolicy::ProcessConfig() {
     448           0 :     BOOST_FOREACH(const RoutingPolicyTermConfig cfg_term, config_->terms()) {
     449             :         // Build each terms and insert to operational data
     450           0 :         PolicyTermPtr term = BuildTerm(cfg_term);
     451           0 :         if (term)
     452           0 :             add_term(term);
     453           0 :     }
     454           0 : }
     455             : 
     456             : //
     457             : // Reprogram policy terms based on new config.
     458             : // If the policy term has changed (number of terms got updated, or new term is
     459             : // added or earlier term is deleted or existing term is updated), increment the
     460             : // generation number to indicate the update
     461             : //
     462           0 : void RoutingPolicy::UpdateConfig(const BgpRoutingPolicyConfig *cfg) {
     463           0 :     CHECK_CONCURRENCY("bgp::Config");
     464           0 :     config_ = cfg;
     465           0 :     bool update_policy = false;
     466           0 :     if (terms()->size() != config_->terms().size())
     467           0 :         update_policy = true;
     468             : 
     469           0 :     RoutingPolicyTermList::iterator oper_it = terms()->begin(), oper_next;
     470             :     BgpRoutingPolicyConfig::RoutingPolicyTermList::const_iterator
     471           0 :         config_it = config_->terms().begin();
     472           0 :     while (oper_it != terms()->end() && config_it != config_->terms().end()) {
     473           0 :         PolicyTermPtr term = BuildTerm(*config_it);
     474           0 :         if (**oper_it == *term) {
     475           0 :             ++oper_it;
     476           0 :             ++config_it;
     477             :         } else {
     478           0 :             if (term) {
     479           0 :                 *oper_it = term;
     480           0 :                 update_policy = true;
     481           0 :                 ++oper_it;
     482           0 :                 ++config_it;
     483             :             } else {
     484           0 :                 ++config_it;
     485             :             }
     486             :         }
     487           0 :     }
     488           0 :     for (oper_next = oper_it; oper_it != terms()->end(); oper_it = oper_next) {
     489           0 :         ++oper_next;
     490           0 :         terms()->erase(oper_it);
     491           0 :         update_policy = true;
     492             :     }
     493           0 :     for (; config_it != config_->terms().end(); ++config_it) {
     494           0 :         PolicyTermPtr term = BuildTerm(*config_it);
     495           0 :         if (term)
     496           0 :             add_term(term);
     497           0 :         update_policy = true;
     498           0 :     }
     499             : 
     500           0 :     if (update_policy) generation_++;
     501           0 : }
     502             : 
     503           0 : void RoutingPolicy::ClearConfig() {
     504           0 :     CHECK_CONCURRENCY("bgp::Config");
     505           0 :     config_ = NULL;
     506           0 : }
     507             : 
     508           0 : void RoutingPolicy::ManagedDelete() {
     509           0 :     deleter_->Delete();
     510           0 : }
     511             : 
     512           0 : void RoutingPolicy::Shutdown() {
     513           0 :     CHECK_CONCURRENCY("bgp::Config");
     514           0 :     ClearConfig();
     515           0 : }
     516             : 
     517           0 : bool RoutingPolicy::MayDelete() const {
     518           0 :     return (refcount_ == 0);
     519             : }
     520             : 
     521           0 : LifetimeActor *RoutingPolicy::deleter() {
     522           0 :     return deleter_.get();
     523             : }
     524             : 
     525           0 : const LifetimeActor *RoutingPolicy::deleter() const {
     526           0 :     return deleter_.get();
     527             : }
     528             : 
     529           0 : bool RoutingPolicy::deleted() const {
     530           0 :     return deleter()->IsDeleted();
     531             : }
     532             : 
     533             : //
     534             : // Attempt to enqueue a delete for the RoutingPolicy.
     535             : //
     536           0 : void RoutingPolicy::RetryDelete() {
     537           0 :     if (!deleter_->IsDeleted())
     538           0 :         return;
     539           0 :     deleter_->RetryDelete();
     540             : }
     541             : 
     542           0 : RoutingPolicy::PolicyResult RoutingPolicy::operator()(const BgpRoute *route,
     543             :                                   const BgpPath *path, BgpAttr *attr) const {
     544           0 :     BOOST_FOREACH(PolicyTermPtr term, terms()) {
     545           0 :         bool terminal = term->terminal();
     546           0 :         bool matched = term->ApplyTerm(route, path, attr);
     547           0 :         if (matched && terminal) {
     548           0 :             return std::make_pair(terminal,
     549           0 :                                   (*term->actions().begin())->accept());
     550             :         }
     551           0 :     }
     552           0 :     return std::make_pair(false, true);
     553             : }
     554             : 
     555           0 : PolicyTerm::PolicyTerm() {
     556           0 : }
     557             : 
     558           0 : PolicyTerm::~PolicyTerm() {
     559           0 :     STLDeleteValues(&actions_);
     560           0 :     STLDeleteValues(&matches_);
     561           0 : }
     562             : 
     563           0 : bool PolicyTerm::terminal() const {
     564           0 :     if (!actions().empty())
     565           0 :         return (*actions().begin())->terminal();
     566           0 :     return false;
     567             : }
     568             : 
     569           0 : bool PolicyTerm::ApplyTerm(const BgpRoute *route, const BgpPath *path,
     570             :                            BgpAttr *attr) const {
     571           0 :     bool matched = true;
     572           0 :     BOOST_FOREACH(RoutingPolicyMatch *match, matches()) {
     573           0 :         if (!(*match)(route, path, attr)) {
     574           0 :             matched = false;
     575           0 :             break;
     576             :         }
     577             :     }
     578           0 :     if (matched) {
     579           0 :         bool first = true;
     580           0 :         BOOST_FOREACH(RoutingPolicyAction *action, actions()) {
     581             :             // First action defines what to do with the route
     582             :             // accept/reject/next-term
     583           0 :             if (first) {
     584           0 :                 if (action->terminal()) {
     585           0 :                     if (!action->accept()) {
     586             :                         // out_attr is unaltered
     587           0 :                         break;
     588             :                     }
     589             :                 }
     590           0 :                 first = false;
     591             :             } else {
     592           0 :                 RoutingPolicyUpdateAction *update =
     593             :                     static_cast<RoutingPolicyUpdateAction *>(action);
     594           0 :                 (*update)(attr);
     595             :             }
     596             :         }
     597             :     }
     598           0 :     return matched;
     599             : }
     600             : 
     601             : // Compare two terms
     602           0 : bool PolicyTerm::operator==(const PolicyTerm &rhs) const {
     603             :     // Different number of match conditions
     604           0 :     if (matches().size() != rhs.matches().size()) return false;
     605             :     // Different number of actions conditions
     606           0 :     if (actions().size() != rhs.actions().size()) return false;
     607             : 
     608             :     // Walk the list of match conditions and compare each match
     609           0 :     for (MatchList::const_iterator rhs_matches_cit = rhs.matches().begin(),
     610           0 :          lhs_matches_cit = matches().begin();
     611           0 :          lhs_matches_cit != matches().end();
     612           0 :          lhs_matches_cit++, rhs_matches_cit++) {
     613           0 :         if (**rhs_matches_cit != **lhs_matches_cit)
     614           0 :             return false;
     615             :     }
     616             : 
     617             :     // Walk the list of actions and compare each action
     618           0 :     for (ActionList::const_iterator lhs_actions_cit = actions().begin(),
     619           0 :          rhs_actions_cit = rhs.actions().begin();
     620           0 :          lhs_actions_cit != actions().end();
     621           0 :          lhs_actions_cit++, rhs_actions_cit++) {
     622           0 :         if (**rhs_actions_cit != **lhs_actions_cit)
     623           0 :             return false;
     624             :     }
     625           0 :     return true;
     626             : }

Generated by: LCOV version 1.14