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

Generated by: LCOV version 1.14