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

Generated by: LCOV version 1.14