LCOV - code coverage report
Current view: top level - bgp/routing-instance - routing_instance.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 1192 1224 97.4 %
Date: 2026-06-04 02:06:09 Functions: 128 129 99.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include "bgp/routing-instance/routing_instance.h"
       6             : 
       7             : #include <boost/foreach.hpp>
       8             : #include <boost/assign/list_of.hpp>
       9             : #include <boost/functional/hash.hpp>
      10             : 
      11             : #include <algorithm>
      12             : 
      13             : #include "base/set_util.h"
      14             : #include "base/task_annotations.h"
      15             : #include "base/task_trigger.h"
      16             : #include "bgp/bgp_config.h"
      17             : #include "bgp/bgp_factory.h"
      18             : #include "bgp/bgp_log.h"
      19             : #include "bgp/bgp_mvpn.h"
      20             : #include "bgp/bgp_server.h"
      21             : #include "bgp/mvpn/mvpn_table.h"
      22             : #include "bgp/routing-instance/iroute_aggregator.h"
      23             : #include "bgp/routing-instance/istatic_route_mgr.h"
      24             : #include "bgp/routing-instance/peer_manager.h"
      25             : #include "bgp/routing-instance/routepath_replicator.h"
      26             : #include "bgp/routing-instance/routing_instance_log.h"
      27             : #include "bgp/routing-instance/routing_table_types.h"
      28             : #include "bgp/routing-policy/routing_policy.h"
      29             : #include "bgp/routing-instance/rtarget_group_mgr.h"
      30             : #include "bgp/rtarget/rtarget_route.h"
      31             : 
      32             : using boost::assign::list_of;
      33             : using boost::system::error_code;
      34             : using boost::tie;
      35             : using std::make_pair;
      36             : using std::ostringstream;
      37             : using std::set;
      38             : using std::string;
      39             : using std::vector;
      40             : 
      41             : SandeshTraceBufferPtr RoutingInstanceTraceBuf(
      42             :         SandeshTraceBufferCreate(RTINSTANCE_TRACE_BUF, 1000));
      43             : 
      44             : class RoutingInstanceMgr::DeleteActor : public LifetimeActor {
      45             : public:
      46        9743 :     explicit DeleteActor(RoutingInstanceMgr *manager)
      47        9743 :         : LifetimeActor(manager->server_->lifetime_manager()),
      48        9743 :           manager_(manager) {
      49        9743 :     }
      50        9639 :     virtual bool MayDelete() const {
      51        9639 :         return manager_->MayDelete();
      52             :     }
      53        9639 :     virtual void Shutdown() {
      54        9639 :         manager_->Shutdown();
      55        9639 :     }
      56        9639 :     virtual void Destroy() {
      57        9639 :         manager_->server_delete_ref_.Reset(NULL);
      58        9639 :     }
      59             : 
      60             : private:
      61             :     RoutingInstanceMgr *manager_;
      62             : };
      63             : 
      64        9743 : RoutingInstanceMgr::RoutingInstanceMgr(BgpServer *server) :
      65        9743 :         server_(server),
      66       19486 :         instance_config_lists_(
      67        9743 :             TaskScheduler::GetInstance()->HardwareThreadCount()),
      68        9743 :         default_rtinstance_(NULL),
      69        9743 :         deleted_count_(0),
      70        9743 :         asn_listener_id_(server->RegisterASNUpdateCallback(
      71             :             boost::bind(&RoutingInstanceMgr::ASNUpdateCallback, this, _1, _2))),
      72        9743 :         identifier_listener_id_(server->RegisterIdentifierUpdateCallback(
      73             :             boost::bind(&RoutingInstanceMgr::IdentifierUpdateCallback,
      74             :                 this, _1))),
      75        9743 :         dormant_trace_buf_size_(
      76        9743 :                 GetEnvRoutingInstanceDormantTraceBufferCapacity()),
      77        9743 :         trace_buf_threshold_(
      78        9743 :                 GetEnvRoutingInstanceDormantTraceBufferThreshold()),
      79        9743 :         deleter_(new DeleteActor(this)),
      80       29229 :         server_delete_ref_(this, server->deleter()) {
      81        9743 :     int task_id = TaskScheduler::GetInstance()->GetTaskId("bgp::ConfigHelper");
      82        9743 :     int hw_thread_count = TaskScheduler::GetInstance()->HardwareThreadCount();
      83       48715 :     for (int idx = 0; idx < hw_thread_count; ++idx) {
      84       77944 :         instance_config_triggers_.push_back(new TaskTrigger(boost::bind(
      85             :             &RoutingInstanceMgr::ProcessInstanceConfigList, this, idx),
      86       38972 :             task_id, idx));
      87             :     }
      88       19486 :     neighbor_config_trigger_.reset(new TaskTrigger(
      89             :         boost::bind(&RoutingInstanceMgr::ProcessNeighborConfigList, this),
      90       19486 :         TaskScheduler::GetInstance()->GetTaskId("bgp::Config"), 0));
      91        9743 : }
      92             : 
      93       19486 : RoutingInstanceMgr::~RoutingInstanceMgr() {
      94        9743 :     assert(mvpn_project_managers_.empty());
      95        9743 :     assert(virtual_networks_.empty());
      96        9743 :     assert(deleted_count_ == 0);
      97        9743 :     server_->UnregisterASNUpdateCallback(asn_listener_id_);
      98        9743 :     server_->UnregisterIdentifierUpdateCallback(identifier_listener_id_);
      99        9743 :     STLDeleteValues(&instance_config_triggers_);
     100       19486 : }
     101             : 
     102         190 : size_t RoutingInstanceMgr::GetMvpnProjectManagerCount(
     103             :             const string &network) const {
     104         190 :     std::scoped_lock lock(mutex_);
     105             : 
     106             :     MvpnProjectManagerNetworks::const_iterator iter =
     107         190 :         mvpn_project_managers_.find(network);
     108         190 :     if (iter == mvpn_project_managers_.end())
     109         184 :         return 0;
     110           6 :     return iter->second.size();
     111         190 : }
     112             : 
     113        9639 : void RoutingInstanceMgr::ManagedDelete() {
     114        9639 :     deleter_->Delete();
     115        9639 : }
     116             : 
     117        9639 : void RoutingInstanceMgr::Shutdown() {
     118       50537 :     for (RoutingInstanceIterator it = begin(); it != end(); ++it) {
     119       40898 :         InstanceTargetRemove(it->second);
     120       40898 :         InstanceVnIndexRemove(it->second);
     121             :     }
     122        9639 : }
     123             : 
     124        9639 : bool RoutingInstanceMgr::MayDelete() const {
     125        9639 :     if (!neighbor_config_list_.empty())
     126           0 :         return false;
     127       48195 :     for (size_t idx = 0; idx < instance_config_lists_.size(); ++idx) {
     128       38556 :         if (!instance_config_lists_[idx].empty())
     129           0 :             return false;
     130             :     }
     131        9639 :     return true;
     132             : }
     133             : 
     134      131662 : LifetimeActor *RoutingInstanceMgr::deleter() {
     135      131662 :     return deleter_.get();
     136             : }
     137             : 
     138       80538 : bool RoutingInstanceMgr::deleted() {
     139       80538 :     return deleter()->IsDeleted();
     140             : }
     141             : 
     142             : //
     143             : // Go through all export targets for the RoutingInstance and add an entry for
     144             : // each one to the InstanceTargetMap.
     145             : //
     146             : // Ignore export targets that are not in the import list.  This is done since
     147             : // export only targets are managed by user and the same export only target can
     148             : // be configured on multiple virtual networks.
     149             : //
     150       70034 : void RoutingInstanceMgr::InstanceTargetAdd(RoutingInstance *rti) {
     151       70034 :     std::scoped_lock lock(mutex_);
     152       70035 :     for (RoutingInstance::RouteTargetList::const_iterator it =
     153      579379 :          rti->GetExportList().begin(); it != rti->GetExportList().end(); ++it) {
     154      439309 :         if (rti->GetImportList().find(*it) == rti->GetImportList().end())
     155         448 :             continue;
     156      438861 :         target_map_.insert(make_pair(*it, rti));
     157             :     }
     158       70035 : }
     159             : 
     160             : //
     161             : // Go through all export targets for the RoutingInstance and remove the entry
     162             : // for each one from the InstanceTargetMap.  Note that there may be multiple
     163             : // entries in the InstanceTargetMap for a given export target.  Hence we need
     164             : // to make sure that we only remove the entry that matches the RoutingInstance.
     165             : //
     166             : // Ignore export targets that are not in the import list. They shouldn't be in
     167             : // in the map because of the same check in InstanceTargetAdd.
     168             : //
     169       70035 : void RoutingInstanceMgr::InstanceTargetRemove(const RoutingInstance *rti) {
     170       70035 :     std::scoped_lock lock(mutex_);
     171       70035 :     for (RoutingInstance::RouteTargetList::const_iterator it =
     172      579379 :          rti->GetExportList().begin(); it != rti->GetExportList().end(); ++it) {
     173      439309 :         if (rti->GetImportList().find(*it) == rti->GetImportList().end())
     174         448 :             continue;
     175      438861 :         for (InstanceTargetMap::iterator loc = target_map_.find(*it);
     176      442104 :              loc != target_map_.end() && loc->first == *it; ++loc) {
     177      442104 :             if (loc->second == rti) {
     178      438861 :                 target_map_.erase(loc);
     179      438861 :                 break;
     180             :             }
     181             :         }
     182             :     }
     183       70035 : }
     184             : 
     185             : //
     186             : // Lookup the RoutingInstance for the given RouteTarget.
     187             : //
     188         432 : const RoutingInstance *RoutingInstanceMgr::GetInstanceByTarget(
     189             :         const RouteTarget &rtarget) const {
     190         432 :     InstanceTargetMap::const_iterator loc = target_map_.find(rtarget);
     191         432 :     if (loc == target_map_.end()) {
     192           0 :         return NULL;
     193             :     }
     194         432 :     return loc->second;
     195             : }
     196             : 
     197             : //
     198             : // Add an entry for the vn index to the VnIndexMap.
     199             : //
     200       70035 : void RoutingInstanceMgr::InstanceVnIndexAdd(RoutingInstance *rti) {
     201       70035 :     std::scoped_lock lock(mutex_);
     202       70035 :     if (rti->virtual_network_index())
     203       27233 :         vn_index_map_.insert(make_pair(rti->virtual_network_index(), rti));
     204       70035 : }
     205             : 
     206             : //
     207             : // Remove the entry for the vn index from the VnIndexMap.  Note that there may
     208             : // be multiple entries in the VnIndexMap for a given vn index target. Hence we
     209             : // need to make sure that we remove the entry that matches the RoutingInstance.
     210             : //
     211       70035 : void RoutingInstanceMgr::InstanceVnIndexRemove(const RoutingInstance *rti) {
     212       70035 :     std::scoped_lock lock(mutex_);
     213       70035 :     if (!rti->virtual_network_index())
     214       42802 :         return;
     215             : 
     216       27233 :     int vn_index = rti->virtual_network_index();
     217       27233 :     for (VnIndexMap::iterator loc = vn_index_map_.find(vn_index);
     218       28692 :          loc != vn_index_map_.end() && loc->first == vn_index; ++loc) {
     219       28692 :         if (loc->second == rti) {
     220       27233 :             vn_index_map_.erase(loc);
     221       27233 :             break;
     222             :         }
     223             :     }
     224       70035 : }
     225             : 
     226             : //
     227             : // Lookup the RoutingInstance for the given vn index.
     228             : //
     229       77686 : const RoutingInstance *RoutingInstanceMgr::GetInstanceByVnIndex(
     230             :         int vn_index) const {
     231       77686 :     VnIndexMap::const_iterator loc = vn_index_map_.find(vn_index);
     232       77687 :     if (loc == vn_index_map_.end())
     233          18 :         return NULL;
     234       77669 :     return loc->second;
     235             : }
     236             : 
     237             : //
     238             : // Lookup the VN name for the given vn index.
     239             : //
     240       77686 : string RoutingInstanceMgr::GetVirtualNetworkByVnIndex(
     241             :         int vn_index) const {
     242       77686 :     const RoutingInstance *rti = GetInstanceByVnIndex(vn_index);
     243       77687 :     return rti ? rti->GetVirtualNetworkName() : "unresolved";
     244             : }
     245             : 
     246             : //
     247             : // Lookup the vn index for the given RouteTarget.
     248             : //
     249             : // Return 0 if the RouteTarget does not map to a RoutingInstance.
     250             : // Return -1 if the RouteTarget maps to multiple RoutingInstances
     251             : // that belong to different VNs.
     252             : //
     253      637699 : int RoutingInstanceMgr::GetVnIndexByRouteTarget(
     254             :         const RouteTarget &rtarget) const {
     255      637699 :     int vn_index = 0;
     256      637699 :     for (InstanceTargetMap::const_iterator loc = target_map_.find(rtarget);
     257     3079040 :          loc != target_map_.end() && loc->first == rtarget; ++loc) {
     258     2441325 :         int ri_vn_index = loc->second->virtual_network_index();
     259     2441149 :         if (vn_index && ri_vn_index && ri_vn_index != vn_index)
     260          11 :             return -1;
     261     2441138 :         vn_index = ri_vn_index;
     262             :     }
     263             : 
     264      637967 :     return vn_index;
     265             : }
     266             : 
     267             : //
     268             : // Derive the vn index from the route targets in the ExtCommunity.
     269             : //
     270             : // If the result is ambiguous i.e. we have a RouteTarget that maps
     271             : // to multiple vn indexes or we have multiple RouteTargets that map
     272             : // to different vn indexes, return 0.
     273             : //
     274      176261 : int RoutingInstanceMgr::GetVnIndexByExtCommunity(
     275             :         const ExtCommunity *ext_community) const {
     276      176261 :     int vn_index = 0;
     277     2008500 :     BOOST_FOREACH(const ExtCommunity::ExtCommunityValue &comm,
     278             :                   ext_community->communities()) {
     279      915903 :         if (!ExtCommunity::is_route_target(comm))
     280      278319 :             continue;
     281             : 
     282      637580 :         RouteTarget rtarget(comm);
     283      637704 :         int rtgt_vn_index = GetVnIndexByRouteTarget(rtarget);
     284      637977 :         if (rtgt_vn_index < 0 ||
     285         179 :             (vn_index && rtgt_vn_index && rtgt_vn_index != vn_index)) {
     286         119 :             vn_index = 0;
     287         119 :             break;
     288      637858 :         } else if (rtgt_vn_index) {
     289        6311 :             vn_index = rtgt_vn_index;
     290             :         }
     291             :     }
     292             : 
     293      176392 :     return vn_index;
     294             : }
     295             : 
     296             : int
     297       41170 : RoutingInstanceMgr::RegisterInstanceOpCallback(RoutingInstanceCb callback) {
     298       41170 :     std::scoped_lock lock(mutex_);
     299       41170 :     size_t i = bmap_.find_first();
     300       41170 :     if (i == bmap_.npos) {
     301       41169 :         i = callbacks_.size();
     302       41169 :         callbacks_.push_back(callback);
     303             :     } else {
     304           1 :         bmap_.reset(i);
     305           1 :         if (bmap_.none()) {
     306           1 :             bmap_.clear();
     307             :         }
     308           1 :         callbacks_[i] = callback;
     309             :     }
     310       41170 :     return i;
     311       41170 : }
     312             : 
     313       40752 : void RoutingInstanceMgr::UnregisterInstanceOpCallback(int listener) {
     314       40752 :     std::scoped_lock lock(mutex_);
     315       40752 :     callbacks_[listener] = NULL;
     316       40752 :     if ((size_t) listener == callbacks_.size() - 1) {
     317       51781 :         while (!callbacks_.empty() && callbacks_.back() == NULL) {
     318       40743 :             callbacks_.pop_back();
     319             :         }
     320       11038 :         if (bmap_.size() > callbacks_.size()) {
     321       10152 :             bmap_.resize(callbacks_.size());
     322             :         }
     323             :     } else {
     324       29714 :         if ((size_t) listener >= bmap_.size()) {
     325       29354 :             bmap_.resize(listener + 1);
     326             :         }
     327       29714 :         bmap_.set(listener);
     328             :     }
     329       40752 : }
     330             : 
     331      131408 : void RoutingInstanceMgr::NotifyInstanceOp(string name, Operation op) {
     332      131408 :     std::scoped_lock lock(mutex_);
     333      131409 :     for (InstanceOpListenersList::iterator iter = callbacks_.begin();
     334      567457 :          iter != callbacks_.end(); ++iter) {
     335      436050 :         if (*iter != NULL) {
     336      394334 :             RoutingInstanceCb cb = *iter;
     337      394333 :             (cb)(name, op);
     338      394334 :         }
     339             :     }
     340      131409 : }
     341             : 
     342       29339 : bool RoutingInstanceMgr::ProcessInstanceConfigList(int idx) {
     343       29339 :     if (deleted()) {
     344           0 :         deleter()->RetryDelete();
     345             :     } else {
     346      127549 :         BOOST_FOREACH(const string &name, instance_config_lists_[idx]) {
     347             :             const BgpInstanceConfig *config =
     348       48935 :                 server()->config_manager()->FindInstance(name);
     349       49051 :             if (!config)
     350           1 :                 continue;
     351       49050 :             LocateRoutingInstance(config);
     352             :         }
     353             :     }
     354             : 
     355       29525 :     instance_config_lists_[idx].clear();
     356       29525 :     return true;
     357             : }
     358             : 
     359      353820 : RoutingInstance *RoutingInstanceMgr::GetDefaultRoutingInstance() {
     360      353820 :     return default_rtinstance_;
     361             : }
     362             : 
     363           0 : const RoutingInstance *RoutingInstanceMgr::GetDefaultRoutingInstance() const {
     364           0 :     return default_rtinstance_;
     365             : }
     366             : 
     367      360368 : RoutingInstance *RoutingInstanceMgr::GetRoutingInstance(const string &name) {
     368      360368 :     RoutingInstanceList::iterator iter = instances_.find(name);
     369      360364 :     if (iter != instances_.end())
     370      342477 :         return iter->second;
     371       17888 :     return NULL;
     372             : }
     373             : 
     374      162702 : const RoutingInstance *RoutingInstanceMgr::GetRoutingInstance(
     375             :     const string &name) const {
     376      162702 :     RoutingInstanceList::const_iterator iter = instances_.find(name);
     377      162702 :     if (iter != instances_.end())
     378      157894 :         return iter->second;
     379        4808 :     return NULL;
     380             : }
     381             : 
     382       69156 : RoutingInstance *RoutingInstanceMgr::GetRoutingInstanceLocked(
     383             :     const string &name) {
     384       69156 :     std::scoped_lock lock(mutex_);
     385       69394 :     RoutingInstanceList::iterator iter = instances_.find(name);
     386       69394 :     if (iter != instances_.end())
     387       18931 :         return iter->second;
     388       50463 :     return NULL;
     389       69394 : }
     390             : 
     391       51134 : void RoutingInstanceMgr::InsertRoutingInstance(RoutingInstance *rtinstance) {
     392       51134 :     std::scoped_lock lock(mutex_);
     393       51136 :     instances_.insert(make_pair(rtinstance->config()->name(),
     394             :                 rtinstance));
     395       51136 : }
     396             : 
     397       69122 : void RoutingInstanceMgr::LocateRoutingInstance(
     398             :     const BgpInstanceConfig *config) {
     399       69122 :     RoutingInstance *rtinstance = GetRoutingInstanceLocked(config->name());
     400       69357 :     if (rtinstance) {
     401       18895 :         if (rtinstance->deleted()) {
     402          16 :             RTINSTANCE_LOG_WARNING_MESSAGE(server_,
     403             :                 RTINSTANCE_LOG_FLAG_ALL, rtinstance->GetVirtualNetworkName(),
     404             :                 config->name(),
     405             :                 "Instance recreated before pending deletion is complete");
     406             :         } else {
     407       18887 :             UpdateRoutingInstance(rtinstance, config);
     408             :         }
     409             :     } else {
     410       50462 :         rtinstance = CreateRoutingInstance(config);
     411             :     }
     412       69357 : }
     413             : 
     414      150648 : void RoutingInstanceMgr::LocateRoutingInstance(const string &name) {
     415             :     static boost::hash<string> string_hash;
     416             : 
     417      150648 :     if (name == BgpConfigManager::kMasterInstance) {
     418             :         const BgpInstanceConfig *config =
     419       20072 :             server()->config_manager()->FindInstance(name);
     420       20072 :         assert(config);
     421       20072 :         LocateRoutingInstance(config);
     422             :     } else {
     423      130576 :         size_t idx = string_hash(name) % instance_config_lists_.size();
     424      130576 :         instance_config_lists_[idx].insert(name);
     425      130576 :         instance_config_triggers_[idx]->Set();
     426             :     }
     427      150648 : }
     428             : 
     429             : // Update VirtualNetwork to RoutingInstance name mapping.
     430       51149 : bool RoutingInstanceMgr::CreateVirtualNetworkMapping(
     431             :         const string &virtual_network, const string &instance_name) {
     432       51149 :     std::scoped_lock lock(mutex_);
     433             : 
     434       51149 :     VirtualNetworksMap::iterator iter;
     435             :     bool inserted;
     436      102298 :     tie(iter, inserted) = virtual_networks_.insert(make_pair(virtual_network,
     437      153447 :                                                              set<string>()));
     438       51149 :     assert(iter->second.insert(instance_name).second);
     439       51149 :     return true;
     440       51149 : }
     441             : 
     442       51149 : bool RoutingInstanceMgr::DeleteVirtualNetworkMapping(
     443             :         const string &virtual_network, const string &instance_name) {
     444       51149 :     std::scoped_lock lock(mutex_);
     445             : 
     446       51149 :     VirtualNetworksMap::iterator iter = virtual_networks_.find(virtual_network);
     447       51149 :     assert(iter != virtual_networks_.end());
     448             : 
     449             :     // Delete this instance from the set of virtual-network to instances map.
     450       51149 :     assert(iter->second.erase(instance_name) == 1);
     451             : 
     452      102298 :     RoutingInstanceStatsData instance_info;
     453       51149 :     bool mapping_deleted = iter->second.empty();
     454             : 
     455             :     // Delete the mapping if the member set is empty.
     456       51149 :     if (mapping_deleted) {
     457       37409 :         virtual_networks_.erase(iter);
     458             : 
     459             :         // Delete the virtual-network specific UVE.
     460       37409 :         instance_info.set_deleted(true);
     461             :     } else {
     462             : 
     463             :         // Delete this instance's uve, by deleting all table stats.
     464       13740 :         map<string, RoutingTableStats> stats_map;
     465       13740 :         stats_map.insert(make_pair(instance_name, RoutingTableStats()));
     466       13740 :         stats_map[instance_name].set_deleted(true);
     467             : 
     468             :         // Delete all uve stats across all address families.
     469      151140 :         for (Address::Family i = Address::UNSPEC; i < Address::NUM_FAMILIES;
     470      137400 :                 i = static_cast<Address::Family>(i + 1)) {
     471      137400 :             SetTableStatsUve(i, stats_map, &instance_info);
     472             :         }
     473       13740 :     }
     474             : 
     475             :     // Send delete uve.
     476       51149 :     instance_info.set_name(virtual_network);
     477       51149 :     assert(!instance_info.get_name().empty());
     478       51149 :     BGP_UVE_SEND(RoutingInstanceStats, instance_info);
     479             : 
     480       51149 :     return mapping_deleted;
     481       51149 : }
     482             : 
     483      140196 : void RoutingInstanceMgr::SetTableStatsUve(Address::Family family,
     484             :                              const map<string, RoutingTableStats> &stats_map,
     485             :                              RoutingInstanceStatsData *instance_info) const {
     486             :     // By switching over all families, we get compiler to tell us in future,
     487             :     // when ever familiy enum list gets modified.
     488      140196 :     switch (family) {
     489       13740 :     case Address::UNSPEC:
     490       13740 :         break;
     491       28083 :     case Address::INET:
     492             :     case Address::INETMPLS:
     493       28083 :         instance_info->set_raw_ipv4_stats(stats_map);
     494       28083 :         break;
     495       14124 :     case Address::INET6:
     496       14124 :         instance_info->set_raw_ipv6_stats(stats_map);
     497       14124 :         break;
     498       13959 :     case Address::INETVPN:
     499       13959 :         instance_info->set_raw_inetvpn_stats(stats_map);
     500       13959 :         break;
     501       13959 :     case Address::INET6VPN:
     502       13959 :         instance_info->set_raw_inet6vpn_stats(stats_map);
     503       13959 :         break;
     504       13959 :     case Address::RTARGET:
     505       13959 :         instance_info->set_raw_rtarget_stats(stats_map);
     506       13959 :         break;
     507       14124 :     case Address::EVPN:
     508       14124 :         instance_info->set_raw_evpn_stats(stats_map);
     509       14124 :         break;
     510       14124 :     case Address::ERMVPN:
     511       14124 :         instance_info->set_raw_ermvpn_stats(stats_map);
     512       14124 :         break;
     513       14124 :     case Address::MVPN:
     514       14124 :         instance_info->set_raw_mvpn_stats(stats_map);
     515       14124 :         break;
     516           0 :     case Address::NUM_FAMILIES:
     517           0 :         break;
     518             :     }
     519      140196 : }
     520             : 
     521         219 : uint32_t RoutingInstanceMgr::SendTableStatsUve() {
     522         219 :     uint32_t out_q_depth = 0;
     523             : 
     524         603 :     for (RoutingInstanceIterator rit = begin(); rit != end(); ++rit) {
     525         768 :         RoutingInstanceStatsData instance_info;
     526         384 :         map<string, RoutingTableStats> stats_map;
     527             : 
     528         384 :         stats_map.insert(make_pair(rit->second->name(), RoutingTableStats()));
     529             :         RoutingInstance::RouteTableList const rt_list =
     530         384 :                                          rit->second->GetTables();
     531             : 
     532             :         // Prepare and send Statistics UVE for each routing-instance.
     533         384 :         for (RoutingInstance::RouteTableList::const_iterator it =
     534        3564 :              rt_list.begin(); it != rt_list.end(); ++it) {
     535        2796 :             BgpTable *table = it->second;
     536             : 
     537             :             size_t markers;
     538        2796 :             out_q_depth += table->GetPendingRiboutsCount(&markers);
     539             : 
     540        2796 :             stats_map[rit->second->name()].set_prefixes(table->Size());
     541        2796 :             stats_map[rit->second->name()].set_primary_paths(
     542             :                 table->GetPrimaryPathCount());
     543        2796 :             stats_map[rit->second->name()].set_secondary_paths(
     544             :                 table->GetSecondaryPathCount());
     545        2796 :             stats_map[rit->second->name()].set_infeasible_paths(
     546             :                 table->GetInfeasiblePathCount());
     547             : 
     548        2796 :             uint64_t total_paths = table->GetPrimaryPathCount() +
     549        2796 :                                    table->GetSecondaryPathCount() +
     550        2796 :                                    table->GetInfeasiblePathCount();
     551        2796 :             stats_map[rit->second->name()].set_total_paths(total_paths);
     552        2796 :             SetTableStatsUve(table->family(), stats_map, &instance_info);
     553             :         }
     554             : 
     555             :         // Set the primary key and trigger uve send.
     556         384 :         instance_info.set_name(rit->second->GetVirtualNetworkName());
     557         384 :         assert(!instance_info.get_name().empty());
     558         384 :         BGP_UVE_SEND(RoutingInstanceStats, instance_info);
     559         384 :     }
     560             : 
     561         219 :     return out_q_depth;
     562             : }
     563             : 
     564       51132 : RoutingInstance *RoutingInstanceMgr::CreateRoutingInstance(
     565             :     const BgpInstanceConfig *config) {
     566       51135 :     RoutingInstance *rtinstance = BgpStaticObjectFactory::Create<RoutingInstance>(
     567       51132 :         config->name(), server_, this, config);
     568       51127 :     uint32_t ri_index = config->index();
     569       51129 :     if (config->name() == BgpConfigManager::kMasterInstance) {
     570        8228 :         default_rtinstance_ = rtinstance;
     571        8228 :         ri_index = 0;
     572             :     }
     573             : 
     574       51123 :     rtinstance->ProcessConfig();
     575       51134 :     InsertRoutingInstance(rtinstance);
     576       51136 :     rtinstance->set_index(ri_index);
     577             : 
     578       51134 :     InstanceTargetAdd(rtinstance);
     579       51136 :     InstanceVnIndexAdd(rtinstance);
     580       51136 :     rtinstance->InitAllRTargetRoutes(server_->local_autonomous_system());
     581             : 
     582             :     // Notify clients about routing instance create
     583       51136 :     NotifyInstanceOp(config->name(), INSTANCE_ADD);
     584             : 
     585       51136 :     vector<string> import_rt(config->import_list().begin(),
     586      102272 :                                   config->import_list().end());
     587       51136 :     vector<string> export_rt(config->export_list().begin(),
     588      102272 :                                   config->export_list().end());
     589       51136 :     RTINSTANCE_LOG(Create, rtinstance,
     590             :         SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL,
     591             :         import_rt, export_rt, rtinstance->virtual_network_index());
     592             : 
     593             :     // Schedule creation of neighbors for this instance.
     594       51136 :     CreateRoutingInstanceNeighbors(config);
     595             : 
     596             :     //  Update instance to virtual-network mapping structures.
     597       51134 :     CreateVirtualNetworkMapping(rtinstance->GetVirtualNetworkName(),
     598             :                                 rtinstance->name());
     599             : 
     600             :     // Create MvpnManager for all children mvpn networks.
     601             :     MvpnTable *mvpn_table =
     602       51136 :         dynamic_cast<MvpnTable *>(rtinstance->GetTable(Address::MVPN));
     603       51136 :     mvpn_table->CreateMvpnManagers();
     604       51136 :     return rtinstance;
     605       51136 : }
     606             : 
     607       18899 : void RoutingInstanceMgr::UpdateRoutingInstance(RoutingInstance *rtinstance,
     608             :     const BgpInstanceConfig *config) {
     609       18899 :     bool old_always_subscribe = rtinstance->always_subscribe();
     610             : 
     611             :     // Note that InstanceTarget[Remove|Add] depend on the RouteTargetList in
     612             :     // the RoutingInstance.
     613       18899 :     InstanceTargetRemove(rtinstance);
     614       18899 :     InstanceVnIndexRemove(rtinstance);
     615       18899 :     rtinstance->UpdateConfig(config);
     616       18898 :     InstanceTargetAdd(rtinstance);
     617       18899 :     InstanceVnIndexAdd(rtinstance);
     618             : 
     619       18899 :     if (old_always_subscribe != rtinstance->always_subscribe()) {
     620          56 :         rtinstance->FlushAllRTargetRoutes(server_->local_autonomous_system());
     621          56 :         rtinstance->InitAllRTargetRoutes(server_->local_autonomous_system());
     622             :     }
     623             : 
     624             :     // Notify clients about routing instance create
     625       18899 :     NotifyInstanceOp(config->name(), INSTANCE_UPDATE);
     626             : 
     627       18899 :     vector<string> import_rt(config->import_list().begin(),
     628       37798 :                                   config->import_list().end());
     629       18899 :     vector<string> export_rt(config->export_list().begin(),
     630       37798 :                                   config->export_list().end());
     631       18899 :     RTINSTANCE_LOG(Update, rtinstance,
     632             :         SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL, import_rt, export_rt,
     633             :         rtinstance->virtual_network_index());
     634       18899 : }
     635             : 
     636             : //
     637             : // Concurrency: BGP Config task
     638             : //
     639             : // Trigger deletion of a particular routing-instance
     640             : //
     641             : // This involves several asynchronous steps such as deleting all tables in
     642             : // routing-instance (flush all notifications, registrations and user data).
     643             : //
     644       10370 : void RoutingInstanceMgr::DeleteRoutingInstance(const string &name) {
     645       10370 :     CHECK_CONCURRENCY("bgp::Config");
     646             : 
     647       10370 :     RoutingInstance *rtinstance = GetRoutingInstance(name);
     648             : 
     649             :     // Ignore if instance is not found as it might already have been deleted.
     650       10370 :     if (rtinstance && rtinstance->deleted()) {
     651           4 :         RTINSTANCE_LOG_WARNING_MESSAGE(server_, RTINSTANCE_LOG_FLAG_ALL,
     652             :             rtinstance->GetVirtualNetworkName(), name,
     653             :             "Duplicate instance delete while pending deletion");
     654           2 :         return;
     655       10368 :     } else if (!rtinstance) {
     656         260 :         RTINSTANCE_LOG_WARNING_MESSAGE(server_, RTINSTANCE_LOG_FLAG_ALL,
     657             :             name, name, "Instance not found during delete");
     658         130 :         return;
     659             :     }
     660             : 
     661       10238 :     InstanceVnIndexRemove(rtinstance);
     662       10238 :     InstanceTargetRemove(rtinstance);
     663       10238 :     rtinstance->ClearConfig();
     664             : 
     665       10238 :     RTINSTANCE_LOG(Delete, rtinstance,
     666             :         SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
     667             : 
     668       10238 :     rtinstance->ProcessServiceChainConfig();
     669       10238 :     rtinstance->FlushStaticRouteConfig();
     670       10238 :     rtinstance->FlushRouteAggregationConfig();
     671             : 
     672       10238 :     NotifyInstanceOp(name, INSTANCE_DELETE);
     673       10238 :     rtinstance->ManagedDelete();
     674             : }
     675             : 
     676             : //
     677             : // Concurrency: Called from BGP config task manager
     678             : //
     679             : // Destroy a routing instance from the data structures
     680             : //
     681       51136 : void RoutingInstanceMgr::DestroyRoutingInstance(RoutingInstance *rtinstance) {
     682       51136 :     CHECK_CONCURRENCY("bgp::Config");
     683             : 
     684       51136 :     RTINSTANCE_LOG(Destroy, rtinstance,
     685             :         SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
     686             : 
     687       51136 :     DeleteVirtualNetworkMapping(rtinstance->GetVirtualNetworkName(),
     688             :                                 rtinstance->name());
     689             : 
     690             :     // instance should also be deleted here
     691       51136 :     const string name = rtinstance->name();
     692       51136 :     RoutingInstanceList::iterator loc = instances_.find(rtinstance->name());
     693       51136 :     assert(loc != instances_.end());
     694       51136 :     instances_.erase(loc);
     695       51136 :     int index = rtinstance->index();
     696       51136 :     delete rtinstance;
     697             :     // disable the TraceBuf for the deleted RoutingInstance
     698       51136 :     DisableTraceBuffer(name);
     699             :     // index was allocated in Config Manager so needs to be freed
     700       51136 :     if (index >= 0)
     701       50663 :         server()->config_manager()->ResetRoutingInstanceIndexBit(index);
     702             : 
     703       51136 :     if (deleted())
     704       40898 :         return;
     705             : 
     706       10238 :     if (rtinstance == default_rtinstance_) {
     707           0 :         default_rtinstance_ = NULL;
     708           0 :         return;
     709             :     }
     710             : 
     711             :     const BgpInstanceConfig *config
     712       10238 :         = server()->config_manager()->FindInstance(name);
     713       10238 :     if (config) {
     714           5 :         CreateRoutingInstance(config);
     715           5 :         return;
     716             :     }
     717       51136 : }
     718             : 
     719      828191 : SandeshTraceBufferPtr RoutingInstanceMgr::LocateTraceBuffer(
     720             :         const std::string &name) {
     721      828191 :     SandeshTraceBufferPtr trace_buf;
     722             : 
     723      828191 :     trace_buf = GetActiveTraceBuffer(name);
     724      828171 :     if (trace_buf == NULL) {
     725       29452 :         trace_buf = GetTraceBuffer(name);
     726             :     }
     727             : 
     728      828193 :     return trace_buf;
     729           0 : }
     730             : 
     731       29450 : SandeshTraceBufferPtr RoutingInstanceMgr::GetTraceBuffer(
     732             :         const std::string &name) {
     733       29450 :     tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
     734       29463 :     SandeshTraceBufferPtr trace_buf;
     735       29463 :     RoutingInstanceTraceBufferMap::iterator iter;
     736             : 
     737       29463 :     iter = trace_buffer_active_.find(name);
     738       29463 :     if (iter != trace_buffer_active_.end()) {
     739           0 :         return iter->second;
     740             :     }
     741             : 
     742       29463 :     iter = trace_buffer_dormant_.find(name);
     743       29463 :     if (iter != trace_buffer_dormant_.end()) {
     744             :         // tracebuf was created for this RoutingInstance in its prior
     745             :         // incarnation
     746           2 :         trace_buf = iter->second;
     747           2 :         trace_buffer_dormant_.erase(iter);
     748           2 :         trace_buffer_dormant_list_.remove(name);
     749           2 :         trace_buffer_active_.insert(make_pair(name, trace_buf));
     750           2 :         return trace_buf;
     751             :     }
     752             : 
     753             :     // create new sandesh Buffer
     754       58922 :     trace_buf = SandeshTraceBufferCreate(
     755       88383 :                                   name + RTINSTANCE_TRACE_BUF, 1000);
     756       29461 :     trace_buffer_active_.insert(make_pair(name, trace_buf));
     757             : 
     758       29461 :     return trace_buf;
     759       29463 : }
     760             : 
     761       51136 : void RoutingInstanceMgr::DisableTraceBuffer(const std::string &name) {
     762       51136 :     tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
     763       51136 :     SandeshTraceBufferPtr trace_buf;
     764       51136 :     SandeshTraceBufferPtr trace_buf_delete;
     765       51136 :     RoutingInstanceTraceBufferMap::iterator iter;
     766       51136 :     std::pair<RoutingInstanceTraceBufferMap::iterator, bool> ret;
     767       51136 :     std::string ri_name;
     768             : 
     769             :     // Moving the trace buff from Active map to Dormant map
     770       51136 :     iter = trace_buffer_active_.find(name);
     771       51136 :     if (iter != trace_buffer_active_.end()) {
     772       29463 :         trace_buf = iter->second;
     773       29463 :         trace_buffer_active_.erase(iter);
     774       29463 :         if (dormant_trace_buf_size_) {
     775             :             // Move to Dormant map.
     776          43 :             if (trace_buffer_dormant_.size() >= dormant_trace_buf_size_) {
     777             :                 // Make room in the Dormant map, so creating by:
     778             :                 // 1. Delete oldest entries in dormant map
     779             :                 // 2. Insert the new entry.
     780           5 :                 size_t del_count = std::min(trace_buffer_dormant_list_.size(),
     781           5 :                                                trace_buf_threshold_);
     782           5 :                 if (!del_count) {
     783             :                     // retain the latest deleted RI's TraceBuf
     784           3 :                     del_count = 1;
     785             :                 }
     786          12 :                 for (size_t i = 0; i < del_count; i++) {
     787           7 :                     iter = trace_buffer_dormant_.find(
     788           7 :                             trace_buffer_dormant_list_.front());
     789           7 :                     assert(iter != trace_buffer_dormant_.end());
     790           7 :                     trace_buf_delete = iter->second;
     791           7 :                     trace_buffer_dormant_.erase(iter);
     792           7 :                     trace_buffer_dormant_list_.pop_front();
     793           7 :                     trace_buf_delete.reset();
     794             :                 }
     795             :             }
     796          43 :             ret = trace_buffer_dormant_.insert(make_pair(name, trace_buf));
     797          43 :             assert(ret.second == true);
     798          43 :             trace_buffer_dormant_list_.push_back(name);
     799             :         }
     800             :     }
     801             : 
     802      102272 :     return;
     803       51136 : }
     804             : 
     805             : SandeshTraceBufferPtr
     806      828202 : RoutingInstanceMgr::GetActiveTraceBuffer(const std::string &name) const {
     807      828202 :     tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
     808             :     RoutingInstanceTraceBufferMap::const_iterator iter =
     809      828198 :                                          trace_buffer_active_.find(name);
     810             : 
     811      828140 :     if (iter != trace_buffer_active_.end()) {
     812      798721 :         return iter->second;
     813             :     } else {
     814       29440 :         return SandeshTraceBufferPtr();
     815             :     }
     816      828181 : }
     817             : 
     818             : SandeshTraceBufferPtr
     819           2 : RoutingInstanceMgr::GetDormantTraceBuffer(const std::string &name) const {
     820           2 :     tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
     821             :     RoutingInstanceTraceBufferMap::const_iterator iter =
     822           2 :                                          trace_buffer_dormant_.find(name);
     823             : 
     824           2 :     if (iter != trace_buffer_dormant_.end()) {
     825           1 :         return iter->second;
     826             :     } else {
     827           1 :         return SandeshTraceBufferPtr();
     828             :     }
     829           2 : }
     830             : 
     831          15 : bool RoutingInstanceMgr::HasRoutingInstanceActiveTraceBuf(const std::string
     832             :                                                           &name) const {
     833          15 :     tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
     834             :     RoutingInstanceTraceBufferMap::const_iterator iter =
     835          15 :                                           trace_buffer_active_.find(name);
     836             : 
     837          30 :     return (iter != trace_buffer_active_.end());
     838          15 : }
     839             : 
     840          19 : bool RoutingInstanceMgr::HasRoutingInstanceDormantTraceBuf(const std::string
     841             :                                                            &name) const {
     842          19 :     tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
     843             :     RoutingInstanceTraceBufferMap::const_iterator iter =
     844          19 :                                           trace_buffer_dormant_.find(name);
     845          38 :     return (iter != trace_buffer_dormant_.end());
     846          19 : }
     847             : 
     848             : size_t
     849        9744 : RoutingInstanceMgr::GetEnvRoutingInstanceDormantTraceBufferCapacity() const {
     850        9744 :     char *buffer_capacity_str = getenv(
     851             :             "CONTRAIL_ROUTING_INSTANCE_DORMANT_TRACE_BUFFER_SIZE");
     852             :     // return Trace buf capacity 0, if not set in env variable.
     853        9744 :     if (buffer_capacity_str) {
     854          17 :         size_t env_buffer_capacity = strtoul(buffer_capacity_str, NULL, 0);
     855          17 :         return env_buffer_capacity;
     856             :     }
     857        9727 :     return 0;
     858             : }
     859             : 
     860             : size_t
     861        9743 : RoutingInstanceMgr::GetEnvRoutingInstanceDormantTraceBufferThreshold() const {
     862        9743 :     char *buffer_threshold_str = getenv(
     863             :             "CONTRAIL_ROUTING_INSTANCE_DORMANT_TRACE_BUFFER_THRESHOLD");
     864        9743 :     if (buffer_threshold_str) {
     865          16 :         size_t env_buffer_threshold = strtoul(buffer_threshold_str, NULL, 0);
     866          16 :         return env_buffer_threshold;
     867             :     }
     868        9727 :     return ROUTING_INSTANCE_DORMANT_TRACE_BUFFER_THRESHOLD_1K;
     869             : }
     870             : 
     871          10 : size_t RoutingInstanceMgr::GetRoutingInstanceActiveTraceBufSize() const {
     872          10 :     tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
     873          20 :     return trace_buffer_active_.size();
     874          10 : }
     875             : 
     876          13 : size_t RoutingInstanceMgr::GetRoutingInstanceDormantTraceBufSize() const {
     877          13 :     tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
     878          26 :     return trace_buffer_dormant_.size();
     879          13 : }
     880             : 
     881       51136 : void RoutingInstanceMgr::CreateRoutingInstanceNeighbors(
     882             :     const BgpInstanceConfig *config) {
     883       51136 :     if (config->neighbor_list().empty())
     884       51076 :         return;
     885          60 :     std::scoped_lock lock(mutex_);
     886          60 :     neighbor_config_list_.insert(config->name());
     887          60 :     neighbor_config_trigger_->Set();
     888          60 : }
     889             : 
     890          60 : bool RoutingInstanceMgr::ProcessNeighborConfigList() {
     891          60 :     if (deleted()) {
     892           0 :         deleter()->RetryDelete();
     893             :     } else {
     894         180 :         BOOST_FOREACH(const string &name, neighbor_config_list_) {
     895          60 :             RoutingInstance *rtinstance = GetRoutingInstance(name);
     896          60 :             if (!rtinstance || rtinstance->deleted())
     897           2 :                 continue;
     898          58 :             rtinstance->CreateNeighbors();
     899             :         }
     900             :     }
     901             : 
     902          60 :     neighbor_config_list_.clear();
     903          60 :     return true;
     904             : }
     905             : 
     906        7398 : void RoutingInstanceMgr::ASNUpdateCallback(as_t old_asn, as_t old_local_asn) {
     907        7398 :     if (server_->local_autonomous_system() == old_local_asn)
     908           0 :         return;
     909       18381 :     for (RoutingInstanceIterator it = begin(); it != end(); ++it) {
     910       10983 :         it->second->FlushAllRTargetRoutes(old_local_asn);
     911       10983 :         it->second->InitAllRTargetRoutes(server_->local_autonomous_system());
     912             :     }
     913        7398 :     RoutingInstance *master = GetDefaultRoutingInstance();
     914        7398 :     const Ip4Address old_identifier(server()->bgp_identifier());
     915        7398 :     master->DeleteMvpnRTargetRoute(old_local_asn, old_identifier);
     916        7398 :     master->AddMvpnRTargetRoute(server_->local_autonomous_system());
     917             : }
     918             : 
     919        7439 : void RoutingInstanceMgr::IdentifierUpdateCallback(Ip4Address old_identifier) {
     920       19624 :     for (RoutingInstanceIterator it = begin(); it != end(); ++it) {
     921       12185 :         it->second->ProcessIdentifierUpdate(server_->local_autonomous_system());
     922             :     }
     923        7439 :     RoutingInstance *master = GetDefaultRoutingInstance();
     924        7439 :     master->DeleteMvpnRTargetRoute(server_->local_autonomous_system(),
     925             :             old_identifier);
     926        7439 :     master->AddMvpnRTargetRoute(server_->local_autonomous_system());
     927        7439 : }
     928             : 
     929             : //
     930             : // Disable processing of all instance config lists.
     931             : // For testing only.
     932             : //
     933          12 : void RoutingInstanceMgr::DisableInstanceConfigListProcessing() {
     934          60 :     for (size_t idx = 0; idx < instance_config_triggers_.size(); ++idx) {
     935          48 :         instance_config_triggers_[idx]->set_disable();
     936             :     }
     937          12 : }
     938             : 
     939             : //
     940             : // Enable processing of all instance config lists.
     941             : // For testing only.
     942             : //
     943          12 : void RoutingInstanceMgr::EnableInstanceConfigListProcessing() {
     944          60 :     for (size_t idx = 0; idx < instance_config_triggers_.size(); ++idx) {
     945          48 :         instance_config_triggers_[idx]->set_enable();
     946             :     }
     947          12 : }
     948             : 
     949             : //
     950             : // Disable processing of neighbor config list.
     951             : // For testing only.
     952             : //
     953           4 : void RoutingInstanceMgr::DisableNeighborConfigListProcessing() {
     954           4 :     neighbor_config_trigger_->set_disable();
     955           4 : }
     956             : 
     957             : //
     958             : // Enable processing of neighbor config list.
     959             : // For testing only.
     960             : //
     961           4 : void RoutingInstanceMgr::EnableNeighborConfigListProcessing() {
     962           4 :     neighbor_config_trigger_->set_enable();
     963           4 : }
     964             : 
     965             : class RoutingInstance::DeleteActor : public LifetimeActor {
     966             : public:
     967       51099 :     DeleteActor(BgpServer *server, RoutingInstance *parent)
     968       51065 :             : LifetimeActor(server ? server->lifetime_manager() : NULL),
     969      102160 :                             parent_(parent) {
     970       51168 :     }
     971       51136 :     virtual bool MayDelete() const {
     972       51136 :         return parent_->MayDelete();
     973             :     }
     974       51136 :     virtual void Shutdown() {
     975       51136 :         parent_->mgr_->increment_deleted_count();
     976       51136 :         parent_->mgr_->NotifyInstanceOp(parent_->name(),
     977             :                                         RoutingInstanceMgr::INSTANCE_DELETE);
     978       51136 :         parent_->Shutdown();
     979       51136 :     }
     980       51136 :     virtual void Destroy() {
     981       51136 :         parent_->mgr_->decrement_deleted_count();
     982       51136 :         parent_->mgr_->DestroyRoutingInstance(parent_);
     983       51136 :     }
     984             : 
     985             : private:
     986             :     RoutingInstance *parent_;
     987             : };
     988             : 
     989       51128 : RoutingInstance::RoutingInstance(string name, BgpServer *server,
     990             :                                  RoutingInstanceMgr *mgr,
     991       51128 :                                  const BgpInstanceConfig *config)
     992      153326 :     : name_(name), index_(-1), server_(server), mgr_(mgr), config_(config),
     993      102148 :       is_master_(false), always_subscribe_(false), virtual_network_index_(0),
     994       51074 :       virtual_network_allow_transit_(false),
     995       51074 :       virtual_network_pbb_evpn_enable_(false),
     996       51074 :       vxlan_id_(0),
     997       51082 :       deleter_(new DeleteActor(server, this)),
     998       51156 :       manager_delete_ref_(this, NULL),
     999      102267 :       mvpn_project_manager_network_(BgpConfigManager::kFabricInstance) {
    1000       51087 :     if (mgr) {
    1001       51051 :         std::scoped_lock lock(mgr->mutex());
    1002       51136 :         manager_delete_ref_.Reset(mgr->deleter());
    1003       51136 :     }
    1004       51172 : }
    1005             : 
    1006       82364 : RoutingInstance::~RoutingInstance() {
    1007       82364 : }
    1008             : 
    1009          58 : void RoutingInstance::CreateNeighbors() {
    1010          58 :     CHECK_CONCURRENCY("bgp::Config");
    1011             : 
    1012          58 :     if (config_->neighbor_list().empty())
    1013           1 :         return;
    1014          57 :     PeerManager *peer_manager = LocatePeerManager();
    1015         275 :     BOOST_FOREACH(const string &name, config_->neighbor_list()) {
    1016         109 :         if (peer_manager->PeerLookup(name))
    1017           2 :             continue;
    1018         107 :         peer_manager->PeerResurrect(name);
    1019             :     }
    1020             : }
    1021             : 
    1022       51133 : void RoutingInstance::ProcessRoutingPolicyConfig() {
    1023       51133 :     RoutingPolicyMgr *policy_mgr = server()->routing_policy_mgr();
    1024       51447 :     BOOST_FOREACH(RoutingPolicyAttachInfo info,
    1025             :                   config_->routing_policy_list()) {
    1026             :         RoutingPolicy *policy =
    1027         157 :             policy_mgr->GetRoutingPolicy(info.routing_policy_);
    1028         157 :         if (policy) {
    1029         157 :             routing_policies_.push_back(make_pair(policy,
    1030         314 :                                                   policy->generation()));
    1031             :         }
    1032         157 :     }
    1033       51132 : }
    1034             : 
    1035      828195 : SandeshTraceBufferPtr RoutingInstance::trace_buffer() const {
    1036      828195 :     return mgr_->LocateTraceBuffer(name_);
    1037             : }
    1038             : 
    1039             : //
    1040             : // Update the routing policy on the instance
    1041             : // 1. New policy is added
    1042             : // 2. Policy order changed
    1043             : // 3. Policy is removed
    1044             : // 4. Existing policy gets updated(terms in the policy got modified)
    1045             : // In any of the above cases, we call routing policy manager to re-evaluate the
    1046             : // routes in the BgpTables of this routing instance with new set of policies
    1047             : //
    1048        6854 : void RoutingInstance::UpdateRoutingPolicyConfig() {
    1049        6854 :     CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
    1050        6853 :     RoutingPolicyMgr *policy_mgr = server()->routing_policy_mgr();
    1051        6853 :     if (policy_mgr->UpdateRoutingPolicyList(config_->routing_policy_list(),
    1052             :                                             routing_policies())) {
    1053             :         // Let RoutingPolicyMgr handle update of routing policy on the instance
    1054          38 :         policy_mgr->ApplyRoutingPolicy(this);
    1055             :     }
    1056        6858 : }
    1057             : 
    1058      119363 : void RoutingInstance::ProcessServiceChainConfig() {
    1059      119363 :     if (is_master_)
    1060       16456 :         return;
    1061             : 
    1062             :     /**
    1063             :       * If any VN (both internal and non-internal) is connnected to an internal
    1064             :       * VN via a service-chain, we will create a service chain for EVPN address
    1065             :       * family as well so that we can re-originate routes from the internal VN
    1066             :       * RI's EVPN table.
    1067             :       * For other cases (any VN communicating with a non-internal VN via service
    1068             :       * chain), we do not need a service chain to watch the EVPN table.
    1069             :       * Schema-transformer needs to make sure to add the service chain config for
    1070             :       * EVPN address family to all VNs which need to communicate via a
    1071             :       * service-chain with an internal VN.
    1072             :       */
    1073             :     vector<SCAddress::Family> families = list_of
    1074      102907 :         (SCAddress::INET) (SCAddress::INET6)
    1075      102910 :         (SCAddress::EVPN) (SCAddress::EVPN6);
    1076             : 
    1077      926195 :     BOOST_FOREACH(SCAddress::Family family, families) {
    1078             :         const ServiceChainConfig *sc_config =
    1079      411636 :             config_ ? config_->service_chain_info(family) : NULL;
    1080      411632 :         IServiceChainMgr *manager = server_->service_chain_mgr(family);
    1081      411628 :         if (sc_config && !sc_config->routing_instance.empty()) {
    1082        2810 :             manager->LocateServiceChain(this, *sc_config);
    1083             :         } else {
    1084      408820 :             manager->StopServiceChain(this);
    1085             :         }
    1086             :     }
    1087      102912 : }
    1088             : 
    1089       51136 : void RoutingInstance::ProcessStaticRouteConfig() {
    1090       51136 :     if (is_master_)
    1091        8228 :         return;
    1092             : 
    1093       42908 :     vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
    1094      214536 :     BOOST_FOREACH(Address::Family family, families) {
    1095       85814 :         IStaticRouteMgr *manager = static_route_mgr(family);
    1096       85814 :         if (!manager && !config_->static_routes(family).empty())
    1097          36 :             manager = LocateStaticRouteMgr(family);
    1098       85814 :         if (manager)
    1099          36 :             manager->ProcessStaticRouteConfig();
    1100             :     }
    1101       42907 : }
    1102             : 
    1103        6857 : void RoutingInstance::UpdateStaticRouteConfig() {
    1104        6857 :     if (is_master_)
    1105           0 :         return;
    1106             : 
    1107        6857 :     vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
    1108       34289 :     BOOST_FOREACH(Address::Family family, families) {
    1109       13715 :         IStaticRouteMgr *manager = static_route_mgr(family);
    1110       13716 :         if (!manager && !config_->static_routes(family).empty())
    1111          86 :             manager = LocateStaticRouteMgr(family);
    1112       13715 :         if (manager)
    1113         138 :             manager->UpdateStaticRouteConfig();
    1114             :     }
    1115        6858 : }
    1116             : 
    1117       61374 : void RoutingInstance::FlushStaticRouteConfig() {
    1118       61374 :     if (is_master_)
    1119        8228 :         return;
    1120             : 
    1121       53146 :     vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
    1122      265730 :     BOOST_FOREACH(Address::Family family, families) {
    1123      106292 :         IStaticRouteMgr *manager = static_route_mgr(family);
    1124      106292 :         if (manager)
    1125         167 :             manager->FlushStaticRouteConfig();
    1126             :     }
    1127       53146 : }
    1128             : 
    1129         371 : void RoutingInstance::UpdateAllStaticRoutes() {
    1130         371 :     if (is_master_)
    1131          88 :         return;
    1132             : 
    1133         283 :     vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
    1134        1412 :     BOOST_FOREACH(Address::Family family, families) {
    1135         565 :         IStaticRouteMgr *manager = static_route_mgr(family);
    1136         565 :         if (manager)
    1137           2 :             manager->UpdateAllRoutes();
    1138             :     }
    1139         282 : }
    1140             : 
    1141       51131 : void RoutingInstance::ProcessRouteAggregationConfig() {
    1142       51131 :     if (is_master_)
    1143        8228 :         return;
    1144             : 
    1145       42903 :     vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
    1146      214514 :     BOOST_FOREACH(Address::Family family, families) {
    1147       85808 :         IRouteAggregator *aggregator = route_aggregator(family);
    1148       85808 :         if (!aggregator && !config_->aggregate_routes(family).empty())
    1149         157 :             aggregator = LocateRouteAggregator(family);
    1150       85806 :         if (aggregator)
    1151         157 :             aggregator->ProcessAggregateRouteConfig();
    1152             :     }
    1153       42904 : }
    1154             : 
    1155        6857 : void RoutingInstance::UpdateRouteAggregationConfig() {
    1156        6857 :     if (is_master_)
    1157           0 :         return;
    1158             : 
    1159        6857 :     vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
    1160       34273 :     BOOST_FOREACH(Address::Family family, families) {
    1161       13708 :         IRouteAggregator *aggregator = route_aggregator(family);
    1162       13708 :         if (!aggregator && !config_->aggregate_routes(family).empty())
    1163           3 :             aggregator = LocateRouteAggregator(family);
    1164       13708 :         if (aggregator)
    1165          74 :             aggregator->UpdateAggregateRouteConfig();
    1166             :     }
    1167        6855 : }
    1168             : 
    1169       61374 : void RoutingInstance::FlushRouteAggregationConfig() {
    1170       61374 :     if (is_master_)
    1171        8228 :         return;
    1172             : 
    1173       53146 :     vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
    1174      265730 :     BOOST_FOREACH(Address::Family family, families) {
    1175      106292 :         IRouteAggregator *aggregator = route_aggregator(family);
    1176      106292 :         if (aggregator)
    1177         277 :             aggregator->FlushAggregateRouteConfig();
    1178             :     }
    1179       53146 : }
    1180             : 
    1181       23065 : void RoutingInstance::DeleteMvpnRTargetRoute(as_t asn, Ip4Address old_ip) {
    1182       23065 :     if (asn == 0)
    1183       14670 :         return;
    1184       16790 :     string id_str = "target:" + old_ip.to_string() + ":0";
    1185        8395 :     RouteTarget rtarget = RouteTarget::FromString(id_str);
    1186        8395 :     DeleteRTargetRoute(asn, rtarget);
    1187        8395 : }
    1188             : 
    1189       14837 : void RoutingInstance::AddMvpnRTargetRoute(as_t asn) {
    1190       14837 :     if (asn == 0)
    1191        7280 :         return;
    1192        7557 :     const Ip4Address server_ip(server()->bgp_identifier());
    1193       15114 :     string id_str = "target:" + server_ip.to_string() + ":0";
    1194        7557 :     RouteTarget rtarget = RouteTarget::FromString(id_str);
    1195        7557 :     AddRTargetRoute(asn, rtarget);
    1196        7557 : }
    1197             : 
    1198       51122 : void RoutingInstance::ProcessConfig() {
    1199       51122 :     RoutingInstanceInfo info = GetDataCollection("");
    1200             : 
    1201             :     // Initialize virtual network info.
    1202       51093 :     virtual_network_ = config_->virtual_network();
    1203       51093 :     virtual_network_index_ = config_->virtual_network_index();
    1204       51088 :     virtual_network_allow_transit_ = config_->virtual_network_allow_transit();
    1205       51086 :     virtual_network_pbb_evpn_enable_ =
    1206       51087 :         config_->virtual_network_pbb_evpn_enable();
    1207       51086 :     vxlan_id_ = config_->vxlan_id();
    1208       51086 :     routing_instance_vxlan_ = config_->routing_instance_vxlan();
    1209             : 
    1210             :     // Always subscribe (using RTF) for RTs of PNF service chain instances.
    1211       51085 :     always_subscribe_ = config_->has_pnf();
    1212             : 
    1213       51084 :     vector<string> import_rt, export_rt;
    1214      321117 :     BOOST_FOREACH(string irt, config_->import_list()) {
    1215      134999 :         error_code error;
    1216      134999 :         RouteTarget rt = RouteTarget::FromString(irt, &error);
    1217      134929 :         if (!error) {
    1218      134924 :             import_.insert(rt);
    1219      135551 :             import_rt.push_back(irt);
    1220             :         }
    1221      135008 :     }
    1222      143610 :     BOOST_FOREACH(string ert, config_->export_list()) {
    1223       46233 :         error_code error;
    1224       46233 :         RouteTarget rt = RouteTarget::FromString(ert, &error);
    1225       46283 :         if (!error) {
    1226       46283 :             export_.insert(rt);
    1227       46350 :             export_rt.push_back(ert);
    1228             :         }
    1229       46280 :     }
    1230       51057 :     RTINSTANCE_LOG(Update, this,
    1231             :                 SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL,
    1232             :                 import_rt, export_rt, this->virtual_network_index());
    1233             : 
    1234       51113 :     if (import_rt.size())
    1235       42773 :         info.set_add_import_rt(import_rt);
    1236       51117 :     if (export_rt.size())
    1237       42550 :         info.set_add_export_rt(export_rt);
    1238       51113 :     if (import_rt.size() || export_rt.size())
    1239       42770 :         ROUTING_INSTANCE_COLLECTOR_INFO(info);
    1240             : 
    1241             :     // Create BGP Table
    1242       51116 :     if (name_ == BgpConfigManager::kMasterInstance) {
    1243        8228 :         assert(mgr_->count() == 0);
    1244        8228 :         is_master_ = true;
    1245             : 
    1246        8228 :         LocatePeerManager();
    1247        8228 :         VpnTableCreate(Address::INETVPN);
    1248        8228 :         VpnTableCreate(Address::INET6VPN);
    1249        8228 :         VpnTableCreate(Address::ERMVPN);
    1250        8228 :         VpnTableCreate(Address::MVPN);
    1251        8228 :         VpnTableCreate(Address::EVPN);
    1252        8228 :         RTargetTableCreate();
    1253             : 
    1254             :         BgpTable *table_inet = static_cast<BgpTable *>(
    1255        8228 :             server_->database()->CreateTable("inet.0"));
    1256        8228 :         assert(table_inet);
    1257        8228 :         AddTable(table_inet);
    1258             : 
    1259             :         BgpTable *table_inetmpls = static_cast<BgpTable *>(
    1260        8228 :             server_->database()->CreateTable("inet.3"));
    1261        8228 :         assert(table_inetmpls);
    1262        8228 :         AddTable(table_inetmpls);
    1263             : 
    1264             :         BgpTable *table_inet6 = static_cast<BgpTable *>(
    1265        8228 :             server_->database()->CreateTable("inet6.0"));
    1266        8228 :         assert(table_inet6);
    1267        8228 :         AddTable(table_inet6);
    1268             :     } else {
    1269             :         // Create foo.family.0.
    1270             :         // Create path-resolver in INET, INET6 and EVPN VRF tables to enable
    1271             :         // nh_reachability check for fast convergence.
    1272       42884 :         BgpTable *inet_table = VrfTableCreate(Address::INET, Address::INETVPN);
    1273       42908 :         inet_table->LocatePathResolver();
    1274             : 
    1275             :         BgpTable *inet6_table =
    1276       42906 :             VrfTableCreate(Address::INET6, Address::INET6VPN);
    1277       42908 :         inet6_table->LocatePathResolver();
    1278             : 
    1279       42908 :         VrfTableCreate(Address::ERMVPN, Address::ERMVPN);
    1280             : 
    1281       42908 :         BgpTable *evpn_table = VrfTableCreate(Address::EVPN, Address::EVPN);
    1282       42908 :         evpn_table->LocatePathResolver();
    1283             : 
    1284       42908 :         BgpTable *table = VrfTableCreate(Address::MVPN, Address::MVPN);
    1285             : 
    1286             :         // Create path-resolver in mvpn table.
    1287       42908 :         table->LocatePathResolver();
    1288             :     }
    1289             : 
    1290       51136 :     ProcessServiceChainConfig();
    1291       51136 :     ProcessStaticRouteConfig();
    1292       51135 :     ProcessRouteAggregationConfig();
    1293       51133 :     ProcessRoutingPolicyConfig();
    1294       51132 : }
    1295             : 
    1296       18899 : void RoutingInstance::UpdateConfig(const BgpInstanceConfig *cfg) {
    1297       18899 :     CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
    1298             : 
    1299             :     // This is a noop in production code. However unit tests may pass a
    1300             :     // new object.
    1301       18898 :     config_ = cfg;
    1302             : 
    1303             :     // Always subscribe (using RTF) for RTs of PNF service chain instances.
    1304       18898 :     always_subscribe_ = config_->has_pnf();
    1305             : 
    1306             :     // Figure out if there's a significant configuration change that requires
    1307             :     // notifying routes to all listeners.
    1308       18898 :     bool notify_routes = false;
    1309       18898 :     if (virtual_network_allow_transit_ != cfg->virtual_network_allow_transit())
    1310         128 :         notify_routes = true;
    1311       18898 :     if (virtual_network_pbb_evpn_enable_ !=
    1312       18898 :         cfg->virtual_network_pbb_evpn_enable())
    1313           0 :         notify_routes = true;
    1314       18898 :     if (virtual_network_ != cfg->virtual_network())
    1315         360 :         notify_routes = true;
    1316       18899 :     if (virtual_network_index_ != cfg->virtual_network_index())
    1317         371 :         notify_routes = true;
    1318             : 
    1319             :     // Trigger notification of all routes in each table.
    1320       18899 :     if (notify_routes) {
    1321        6190 :         BOOST_FOREACH(RouteTableList::value_type &entry, vrf_tables_by_name_) {
    1322        2845 :             BgpTable *table = entry.second;
    1323        2845 :             table->NotifyAllEntries();
    1324             :         }
    1325             :     }
    1326             : 
    1327             :     // Update all static routes so that they reflect the new OriginVn.
    1328       18899 :     if (virtual_network_index_ != cfg->virtual_network_index())
    1329         371 :         UpdateAllStaticRoutes();
    1330             : 
    1331       18898 :     string prev_vn_name = GetVirtualNetworkName();
    1332             : 
    1333             :     // Update virtual network info.
    1334       18897 :     virtual_network_ = cfg->virtual_network();
    1335             : 
    1336             :     // Recreate instance stats' UVE, if its key: virtual_network is modified.
    1337       18897 :     if (prev_vn_name != GetVirtualNetworkName()) {
    1338           4 :         mgr_->DeleteVirtualNetworkMapping(prev_vn_name, name_);
    1339           4 :         mgr_->CreateVirtualNetworkMapping(GetVirtualNetworkName(), name_);
    1340             :     }
    1341             : 
    1342       18898 :     virtual_network_index_ = cfg->virtual_network_index();
    1343       18898 :     virtual_network_allow_transit_ = cfg->virtual_network_allow_transit();
    1344       18898 :     virtual_network_pbb_evpn_enable_ = cfg->virtual_network_pbb_evpn_enable();
    1345       18898 :     vxlan_id_ = cfg->vxlan_id();
    1346       18898 :     routing_instance_vxlan_ = cfg->routing_instance_vxlan();
    1347             : 
    1348             :     // Master routing instance doesn't have import & export list
    1349             :     // Master instance imports and exports all RT
    1350       18898 :     if (IsMasterRoutingInstance())
    1351       12041 :         return;
    1352             : 
    1353        6857 :     RouteTargetList future_import;
    1354        6857 :     vector<string> add_import_rt, remove_import_rt;
    1355      821005 :     BOOST_FOREACH(const string &rtarget_str, cfg->import_list()) {
    1356      407067 :         error_code error;
    1357      407067 :         RouteTarget rt = RouteTarget::FromString(rtarget_str, &error);
    1358      407071 :         if (!error)
    1359      407070 :             future_import.insert(rt);
    1360             :     }
    1361        6857 :     set_synchronize(&import_, &future_import,
    1362             :         boost::bind(&RoutingInstance::AddRouteTarget, this, true,
    1363             :             &add_import_rt, _1),
    1364             :         boost::bind(&RoutingInstance::DeleteRouteTarget, this, true,
    1365             :             &remove_import_rt, _1));
    1366             : 
    1367        6856 :     RouteTargetList future_export;
    1368        6856 :     vector<string> add_export_rt, remove_export_rt;
    1369      792757 :     BOOST_FOREACH(const string &rtarget_str, cfg->export_list()) {
    1370      392950 :         error_code error;
    1371      392950 :         RouteTarget rt = RouteTarget::FromString(rtarget_str, &error);
    1372      392951 :         if (!error)
    1373      392950 :             future_export.insert(rt);
    1374             :     }
    1375        6858 :     set_synchronize(&export_, &future_export,
    1376             :         boost::bind(&RoutingInstance::AddRouteTarget, this, false,
    1377             :             &add_export_rt, _1),
    1378             :         boost::bind(&RoutingInstance::DeleteRouteTarget, this, false,
    1379             :             &remove_export_rt, _1));
    1380             : 
    1381        6858 :     RoutingInstanceInfo info = GetDataCollection("");
    1382        6858 :     if (add_import_rt.size())
    1383        2340 :         info.set_add_import_rt(add_import_rt);
    1384        6858 :     if (remove_import_rt.size())
    1385        1014 :         info.set_remove_import_rt(remove_import_rt);
    1386        6858 :     if (add_export_rt.size())
    1387        1352 :         info.set_add_export_rt(add_export_rt);
    1388        6858 :     if (remove_export_rt.size())
    1389         697 :         info.set_remove_export_rt(remove_export_rt);
    1390       15056 :     if (add_import_rt.size() || remove_import_rt.size() ||
    1391       15056 :         add_export_rt.size() || remove_export_rt.size())
    1392        3191 :         ROUTING_INSTANCE_COLLECTOR_INFO(info);
    1393             : 
    1394        6857 :     ProcessServiceChainConfig();
    1395        6858 :     UpdateStaticRouteConfig();
    1396        6858 :     UpdateRouteAggregationConfig();
    1397        6855 :     UpdateRoutingPolicyConfig();
    1398       18899 : }
    1399             : 
    1400       61374 : void RoutingInstance::ClearConfig() {
    1401       61374 :     CHECK_CONCURRENCY("bgp::Config");
    1402       61374 :     config_ = NULL;
    1403       61374 : }
    1404             : 
    1405       51136 : void RoutingInstance::ManagedDelete() {
    1406             :     // RoutingInstanceMgr logs the delete for non-master instances.
    1407       51136 :     if (IsMasterRoutingInstance()) {
    1408        8228 :         RTINSTANCE_LOG(Delete, this,
    1409             :             SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
    1410             :     }
    1411       51136 :     deleter_->Delete();
    1412       51136 : }
    1413             : 
    1414       51136 : void RoutingInstance::Shutdown() {
    1415       51136 :     CHECK_CONCURRENCY("bgp::Config");
    1416             : 
    1417       51136 :     RTINSTANCE_LOG(Shutdown, this,
    1418             :         SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
    1419             : 
    1420       51136 :     ClearConfig();
    1421       51136 :     FlushAllRTargetRoutes(server_->local_autonomous_system());
    1422       51136 :     if (is_master_) {
    1423        8228 :         const Ip4Address old_identifier(server()->bgp_identifier());
    1424        8228 :         DeleteMvpnRTargetRoute(server_->local_autonomous_system(),
    1425             :                 old_identifier);
    1426             :     }
    1427       51136 :     ClearRouteTarget();
    1428             : 
    1429       51136 :     ProcessServiceChainConfig();
    1430       51136 :     FlushStaticRouteConfig();
    1431       51136 :     FlushRouteAggregationConfig();
    1432       51136 : }
    1433             : 
    1434       51136 : bool RoutingInstance::MayDelete() const {
    1435       51136 :     return true;
    1436             : }
    1437             : 
    1438      305043 : LifetimeActor *RoutingInstance::deleter() {
    1439      305043 :     return deleter_.get();
    1440             : }
    1441             : 
    1442      693564 : const LifetimeActor *RoutingInstance::deleter() const {
    1443      693564 :     return deleter_.get();
    1444             : }
    1445             : 
    1446      693135 : bool RoutingInstance::deleted() const {
    1447      693135 :     return deleter()->IsDeleted();
    1448             : }
    1449             : 
    1450     2594811 : const string RoutingInstance::GetVirtualNetworkName() const {
    1451     2594811 :     if (!virtual_network_.empty())
    1452      494651 :         return virtual_network_;
    1453     2100188 :     size_t pos = name_.rfind(':');
    1454     2100195 :     if (pos == string::npos) {
    1455      809431 :         return name_;
    1456             :     } else {
    1457     1290764 :         return name_.substr(0, pos);
    1458             :     }
    1459             : }
    1460             : 
    1461     4239016 : int RoutingInstance::virtual_network_index() const {
    1462     4239016 :     return virtual_network_index_;
    1463             : }
    1464             : 
    1465        2393 : bool RoutingInstance::virtual_network_allow_transit() const {
    1466        2393 :     return virtual_network_allow_transit_;
    1467             : }
    1468             : 
    1469        7471 : bool RoutingInstance::virtual_network_pbb_evpn_enable() const {
    1470        7471 :     return virtual_network_pbb_evpn_enable_;
    1471             : }
    1472             : 
    1473        8657 : int RoutingInstance::vxlan_id() const {
    1474        8657 :     return vxlan_id_;
    1475             : }
    1476             : 
    1477      214540 : void RoutingInstance::ClearFamilyRouteTarget(Address::Family vrf_family,
    1478             :                                              Address::Family vpn_family) {
    1479      214540 :     BgpTable *table = GetTable(vrf_family);
    1480      214540 :     if (table) {
    1481      214540 :         RoutePathReplicator *replicator = server_->replicator(vpn_family);
    1482     1583380 :         BOOST_FOREACH(RouteTarget rt, import_) {
    1483      684420 :             replicator->Leave(table, rt, true);
    1484             :         }
    1485      684780 :         BOOST_FOREACH(RouteTarget rt, export_) {
    1486      235120 :             replicator->Leave(table, rt, false);
    1487             :         }
    1488             :     }
    1489      214540 : }
    1490             : 
    1491        7953 : void RoutingInstance::AddRTargetRoute(uint32_t asn,
    1492             :     const RouteTarget &rtarget) {
    1493        7953 :     CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
    1494             : 
    1495        7953 :     RTargetPrefix prefix(asn, rtarget);
    1496        7953 :     RTargetRoute rt_key(prefix);
    1497             : 
    1498        7953 :     RoutingInstance *master = mgr_->GetDefaultRoutingInstance();
    1499        7953 :     BgpTable *table = master->GetTable(Address::RTARGET);
    1500             :     DBTablePartition *tbl_partition =
    1501        7953 :         static_cast<DBTablePartition *>(table->GetTablePartition(0));
    1502             : 
    1503        7953 :     std::scoped_lock lock(mgr_->mutex());
    1504             :     RTargetRoute *route =
    1505        7953 :         static_cast<RTargetRoute *>(tbl_partition->Find(&rt_key));
    1506        7953 :     if (!route) {
    1507        7820 :         route = new RTargetRoute(prefix);
    1508        7820 :         tbl_partition->Add(route);
    1509             :     } else {
    1510         133 :         route->ClearDelete();
    1511             :     }
    1512             : 
    1513        7953 :     if (route->FindPath(BgpPath::Local, index_))
    1514           0 :         return;
    1515             : 
    1516        7953 :     BgpAttrSpec attr_spec;
    1517        7953 :     BgpAttrNextHop nexthop(server_->bgp_identifier());
    1518        7953 :     attr_spec.push_back(&nexthop);
    1519        7953 :     BgpAttrOrigin origin(BgpAttrOrigin::IGP);
    1520        7953 :     attr_spec.push_back(&origin);
    1521        7953 :     BgpAttrPtr attr = server_->attr_db()->Locate(attr_spec);
    1522             : 
    1523        7953 :     BgpPath *path = new BgpPath(index_, BgpPath::Local, attr);
    1524        7953 :     route->InsertPath(path);
    1525        7953 :     tbl_partition->Notify(route);
    1526        7953 :     BGP_LOG_ROUTE(table, static_cast<IPeer *>(NULL),
    1527             :         route, "Insert Local path with path id " << index_);
    1528        7953 : }
    1529             : 
    1530      176425 : void RoutingInstance::DeleteRTargetRoute(as_t asn,
    1531             :     const RouteTarget &rtarget) {
    1532      176425 :     CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
    1533             : 
    1534      176425 :     if (asn == 0)
    1535      168472 :         return;
    1536             : 
    1537      144603 :     RTargetPrefix prefix(asn, rtarget);
    1538      144603 :     RTargetRoute rt_key(prefix);
    1539             : 
    1540      144603 :     RoutingInstance *master = mgr_->GetDefaultRoutingInstance();
    1541      144603 :     BgpTable *table = master->GetTable(Address::RTARGET);
    1542             :     DBTablePartition *tbl_partition =
    1543      144603 :         static_cast<DBTablePartition *>(table->GetTablePartition(0));
    1544             : 
    1545      144603 :     std::scoped_lock lock(mgr_->mutex());
    1546             :     RTargetRoute *route =
    1547      144603 :         static_cast<RTargetRoute *>(tbl_partition->Find(&rt_key));
    1548      144603 :     if (!route || !route->RemovePath(BgpPath::Local, index_))
    1549      136650 :         return;
    1550             : 
    1551        7953 :     BGP_LOG_ROUTE(table, static_cast<IPeer *>(NULL),
    1552             :         route, "Delete Local path with path id " << index_);
    1553        7953 :     if (!route->HasPaths()) {
    1554        7821 :         tbl_partition->Delete(route);
    1555             :     } else {
    1556         132 :         tbl_partition->Notify(route);
    1557             :     }
    1558      281253 : }
    1559             : 
    1560       74360 : void RoutingInstance::InitAllRTargetRoutes(as_t asn) {
    1561       74360 :     if (is_master_)
    1562       23065 :         return;
    1563             : 
    1564       51295 :     CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
    1565      382617 :     BOOST_FOREACH(RouteTarget rtarget, import_) {
    1566      165661 :         if (asn != 0 && always_subscribe_)
    1567         350 :             AddRTargetRoute(asn, rtarget);
    1568             :     }
    1569             : }
    1570             : 
    1571       74360 : void RoutingInstance::FlushAllRTargetRoutes(as_t asn) {
    1572       74360 :     if (is_master_)
    1573       23065 :         return;
    1574             : 
    1575       51295 :     CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
    1576      385141 :     BOOST_FOREACH(RouteTarget rtarget, import_) {
    1577      166923 :         DeleteRTargetRoute(asn, rtarget);
    1578             :     }
    1579             : }
    1580             : 
    1581       12185 : void RoutingInstance::ProcessIdentifierUpdate(as_t asn) {
    1582       12185 :     FlushAllRTargetRoutes(asn);
    1583       12185 :     InitAllRTargetRoutes(asn);
    1584       12185 :     rd_.reset(new RouteDistinguisher(server_->bgp_identifier(), index_));
    1585       12185 : }
    1586             : 
    1587        3732 : void RoutingInstance::AddRouteTarget(bool import,
    1588             :     vector<string> *change_list, RouteTargetList::const_iterator it) {
    1589        3732 :     BgpTable *ermvpn_table = GetTable(Address::ERMVPN);
    1590             :     RoutePathReplicator *ermvpn_replicator =
    1591        3730 :         server_->replicator(Address::ERMVPN);
    1592        3730 :     BgpTable *mvpn_table = GetTable(Address::MVPN);
    1593             :     RoutePathReplicator *mvpn_replicator =
    1594        3729 :         server_->replicator(Address::MVPN);
    1595        3729 :     BgpTable *evpn_table = GetTable(Address::EVPN);
    1596             :     RoutePathReplicator *evpn_replicator =
    1597        3729 :         server_->replicator(Address::EVPN);
    1598        3729 :     BgpTable *inet_table = GetTable(Address::INET);
    1599             :     RoutePathReplicator *inetvpn_replicator =
    1600        3730 :         server_->replicator(Address::INETVPN);
    1601        3730 :     BgpTable *inet6_table = GetTable(Address::INET6);
    1602             :     RoutePathReplicator *inet6vpn_replicator =
    1603        3730 :         server_->replicator(Address::INET6VPN);
    1604             : 
    1605        3730 :     change_list->push_back(it->ToString());
    1606        3730 :     if (import) {
    1607        2367 :         import_.insert(*it);
    1608        2369 :         if (server_->local_autonomous_system() != 0 && always_subscribe_)
    1609          46 :             AddRTargetRoute(server_->local_autonomous_system(), *it);
    1610             :     } else {
    1611        1363 :         export_.insert(*it);
    1612             :     }
    1613             : 
    1614        3732 :     ermvpn_replicator->Join(ermvpn_table, *it, import);
    1615        3732 :     mvpn_replicator->Join(mvpn_table, *it, import);
    1616        3732 :     evpn_replicator->Join(evpn_table, *it, import);
    1617        3732 :     inetvpn_replicator->Join(inet_table, *it, import);
    1618        3732 :     inet6vpn_replicator->Join(inet6_table, *it, import);
    1619        3732 : }
    1620             : 
    1621        1805 : void RoutingInstance::DeleteRouteTarget(bool import,
    1622             :     vector<string> *change_list, RouteTargetList::iterator it) {
    1623        1805 :     BgpTable *ermvpn_table = GetTable(Address::ERMVPN);
    1624             :     RoutePathReplicator *ermvpn_replicator =
    1625        1805 :         server_->replicator(Address::ERMVPN);
    1626        1805 :     BgpTable *mvpn_table = GetTable(Address::MVPN);
    1627             :     RoutePathReplicator *mvpn_replicator =
    1628        1804 :         server_->replicator(Address::MVPN);
    1629        1804 :     BgpTable *evpn_table = GetTable(Address::EVPN);
    1630             :     RoutePathReplicator *evpn_replicator =
    1631        1803 :         server_->replicator(Address::EVPN);
    1632        1803 :     BgpTable *inet_table = GetTable(Address::INET);
    1633             :     RoutePathReplicator *inetvpn_replicator =
    1634        1803 :         server_->replicator(Address::INETVPN);
    1635        1803 :     BgpTable *inet6_table = GetTable(Address::INET6);
    1636             :     RoutePathReplicator *inet6vpn_replicator =
    1637        1803 :         server_->replicator(Address::INET6VPN);
    1638             : 
    1639        1803 :     ermvpn_replicator->Leave(ermvpn_table, *it, import);
    1640        1805 :     mvpn_replicator->Leave(mvpn_table, *it, import);
    1641        1805 :     evpn_replicator->Leave(evpn_table, *it, import);
    1642        1805 :     inetvpn_replicator->Leave(inet_table, *it, import);
    1643        1805 :     inet6vpn_replicator->Leave(inet6_table, *it, import);
    1644             : 
    1645        1805 :     change_list->push_back(it->ToString());
    1646        1805 :     if (import) {
    1647        1107 :         DeleteRTargetRoute(server_->local_autonomous_system(), *it);
    1648        1107 :         import_.erase(it);
    1649             :     } else {
    1650         698 :         export_.erase(it);
    1651             :     }
    1652        1805 : }
    1653             : 
    1654       51136 : void RoutingInstance::ClearRouteTarget() {
    1655       51136 :     CHECK_CONCURRENCY("bgp::Config");
    1656       51136 :     if (IsMasterRoutingInstance()) {
    1657        8228 :         return;
    1658             :     }
    1659             : 
    1660       42908 :     ClearFamilyRouteTarget(Address::INET, Address::INETVPN);
    1661       42908 :     ClearFamilyRouteTarget(Address::INET6, Address::INET6VPN);
    1662       42908 :     ClearFamilyRouteTarget(Address::ERMVPN, Address::ERMVPN);
    1663       42908 :     ClearFamilyRouteTarget(Address::MVPN, Address::MVPN);
    1664       42908 :     ClearFamilyRouteTarget(Address::EVPN, Address::EVPN);
    1665             : 
    1666       42908 :     import_.clear();
    1667       42908 :     export_.clear();
    1668             : }
    1669             : 
    1670        8228 : BgpTable *RoutingInstance::RTargetTableCreate() {
    1671             :     BgpTable *rtargettbl = static_cast<BgpTable *>(
    1672        8228 :         server_->database()->CreateTable("bgp.rtarget.0"));
    1673        8228 :     RTINSTANCE_LOG_TABLE(Create, this, rtargettbl, SandeshLevel::SYS_DEBUG,
    1674             :                          RTINSTANCE_LOG_FLAG_ALL);
    1675        8228 :     AddTable(rtargettbl);
    1676        8228 :     return rtargettbl;
    1677             : }
    1678             : 
    1679       41140 : BgpTable *RoutingInstance::VpnTableCreate(Address::Family vpn_family) {
    1680       41140 :     string table_name = GetTableName(name(), vpn_family);
    1681             :     BgpTable *table = static_cast<BgpTable *>(
    1682       41140 :         server_->database()->CreateTable(table_name));
    1683       41140 :     assert(table);
    1684             : 
    1685       41140 :     AddTable(table);
    1686       41140 :     RTINSTANCE_LOG_TABLE(Create, this, table, SandeshLevel::SYS_DEBUG,
    1687             :         RTINSTANCE_LOG_FLAG_ALL);
    1688       41140 :     assert(server_->rtarget_group_mgr()->empty());
    1689       41140 :     RoutePathReplicator *replicator = server_->replicator(vpn_family);
    1690       41140 :     replicator->Initialize();
    1691       41140 :     return table;
    1692       41140 : }
    1693             : 
    1694      214478 : BgpTable *RoutingInstance::VrfTableCreate(Address::Family vrf_family,
    1695             :     Address::Family vpn_family) {
    1696      214478 :     string table_name = GetTableName(name(), vrf_family);
    1697             :     BgpTable *table = static_cast<BgpTable *>(
    1698      214526 :         server_->database()->CreateTable(table_name));
    1699      214540 :     assert(table);
    1700             : 
    1701      214540 :     AddTable(table);
    1702      214509 :     RTINSTANCE_LOG_TABLE(Create, this, table, SandeshLevel::SYS_DEBUG,
    1703             :         RTINSTANCE_LOG_FLAG_ALL);
    1704      214511 :     RoutePathReplicator *replicator = server_->replicator(vpn_family);
    1705     1570561 :     BOOST_FOREACH(RouteTarget rt, import_) {
    1706      677734 :         replicator->Join(table, rt, true);
    1707             :     }
    1708      678089 :     BOOST_FOREACH(RouteTarget rt, export_) {
    1709      231752 :         replicator->Join(table, rt, false);
    1710             :     }
    1711      214532 :     return table;
    1712      214532 : }
    1713             : 
    1714      288590 : void RoutingInstance::AddTable(BgpTable *tbl) {
    1715      288590 :     vrf_tables_by_name_.insert(make_pair(tbl->name(), tbl));
    1716      288590 :     vrf_tables_by_family_.insert(make_pair(tbl->family(), tbl));
    1717      288592 :     tbl->set_routing_instance(this);
    1718      288577 :     RoutingInstanceInfo info = GetDataCollection("Add");
    1719      288564 :     info.set_family(Address::FamilyToString(tbl->family()));
    1720      288578 :     ROUTING_INSTANCE_COLLECTOR_INFO(info);
    1721      288583 : }
    1722             : 
    1723      288592 : void RoutingInstance::RemoveTable(BgpTable *tbl) {
    1724      288592 :     RoutingInstanceInfo info = GetDataCollection("Remove");
    1725      288592 :     info.set_family(Address::FamilyToString(tbl->family()));
    1726      288592 :     vrf_tables_by_name_.erase(tbl->name());
    1727      288592 :     vrf_tables_by_family_.erase(tbl->family());
    1728      288592 :     ROUTING_INSTANCE_COLLECTOR_INFO(info);
    1729      288592 : }
    1730             : 
    1731             : //
    1732             : // Concurrency: BGP Config task
    1733             : //
    1734             : // Remove the table from the map and delete the table data structure
    1735             : //
    1736      288592 : void RoutingInstance::DestroyDBTable(DBTable *dbtable) {
    1737      288592 :     CHECK_CONCURRENCY("bgp::Config");
    1738             : 
    1739      288592 :     BgpTable *table = static_cast<BgpTable *>(dbtable);
    1740             : 
    1741      288592 :     RTINSTANCE_LOG_TABLE(Destroy, this, table,
    1742             :         SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
    1743             : 
    1744             :     // Remove this table from various data structures
    1745      288592 :     server_->database()->RemoveTable(table);
    1746      288592 :     RemoveTable(table);
    1747             : 
    1748             :     // Make sure that there are no routes left in this table
    1749      288592 :     assert(table->Size() == 0);
    1750             : 
    1751      288592 :     delete table;
    1752      288592 : }
    1753             : 
    1754      256811 : string RoutingInstance::GetTableName(string instance_name,
    1755             :     Address::Family fmly) {
    1756      256811 :     string table_name;
    1757      256813 :     if (instance_name == BgpConfigManager::kMasterInstance) {
    1758       41194 :         if ((fmly == Address::INET) || (fmly == Address::INET6)) {
    1759          54 :             table_name = Address::FamilyToTableString(fmly) + ".0";
    1760       41140 :         } else if (fmly == Address::INETMPLS) {
    1761           0 :             table_name = Address::FamilyToTableString(fmly) + ".3";
    1762             :         } else {
    1763       41140 :             table_name = "bgp." + Address::FamilyToTableString(fmly) + ".0";
    1764             :         }
    1765             :     } else {
    1766             :         table_name =
    1767      215648 :             instance_name + "." + Address::FamilyToTableString(fmly) + ".0";
    1768             :     }
    1769      256851 :     return table_name;
    1770           0 : }
    1771             : 
    1772     1298272 : BgpTable *RoutingInstance::GetTable(Address::Family fmly) {
    1773     1298272 :     RouteTableFamilyList::const_iterator loc = vrf_tables_by_family_.find(fmly);
    1774     1298171 :     return (loc != vrf_tables_by_family_.end() ? loc->second : NULL);
    1775             : }
    1776             : 
    1777      141156 : const BgpTable *RoutingInstance::GetTable(Address::Family fmly) const {
    1778      141156 :     RouteTableFamilyList::const_iterator loc = vrf_tables_by_family_.find(fmly);
    1779      141156 :     return (loc != vrf_tables_by_family_.end() ? loc->second : NULL);
    1780             : }
    1781             : 
    1782         252 : string RoutingInstance::GetVrfFromTableName(const string table) {
    1783         252 :     static set<string> master_tables = list_of("inet.0")("inet.3")("inet6.0");
    1784             :     static set<string> vpn_tables =
    1785           8 :         list_of("bgp.l3vpn.0")("bgp.ermvpn.0")("bgp.evpn.0")("bgp.rtarget.0")
    1786         256 :                 ("bgp.l3vpn-inet6.0")("bgp.mvpn.0");
    1787             : 
    1788         252 :     if (master_tables.find(table) != master_tables.end())
    1789           0 :         return BgpConfigManager::kMasterInstance;
    1790         252 :     if (vpn_tables.find(table) != vpn_tables.end())
    1791          16 :         return BgpConfigManager::kMasterInstance;
    1792             : 
    1793         236 :     size_t pos1 = table.rfind('.');
    1794         236 :     if (pos1 == string::npos)
    1795           4 :         return "__unknown__";
    1796         232 :     size_t pos2 = table.rfind('.', pos1 - 1);
    1797         232 :     if (pos2 == string::npos)
    1798           4 :         return "__unknown__";
    1799             : 
    1800         228 :     return table.substr(0, pos2);
    1801             : }
    1802             : 
    1803       51136 : void RoutingInstance::set_index(int index) {
    1804       51136 :     index_ = index;
    1805       51136 :     if (is_master_)
    1806        8228 :         return;
    1807             : 
    1808       42908 :     rd_.reset(new RouteDistinguisher(server_->bgp_identifier(), index));
    1809             : }
    1810             : 
    1811      651438 : RoutingInstanceInfo RoutingInstance::GetDataCollection(const char *operation) {
    1812     1302779 :     RoutingInstanceInfo info;
    1813      651335 :     info.set_name(GetVirtualNetworkName());
    1814      651409 :     info.set_instance_name(name_);
    1815      651408 :     info.set_hostname(server_->localname());
    1816      651393 :     if (rd_.get()) info.set_route_distinguisher(rd_->ToString());
    1817      651381 :     if (operation) info.set_operation(operation);
    1818      651362 :     return info;
    1819           0 : }
    1820             : 
    1821             : //
    1822             : // Return true if one of the route targets in the ExtCommunity is in the
    1823             : // set of export RouteTargets for this RoutingInstance.
    1824             : //
    1825         468 : bool RoutingInstance::HasExportTarget(const ExtCommunity *extcomm) const {
    1826         468 :     if (!extcomm)
    1827           0 :         return false;
    1828             : 
    1829        1544 :     BOOST_FOREACH(const ExtCommunity::ExtCommunityValue &value,
    1830             :                   extcomm->communities()) {
    1831         906 :         if (!ExtCommunity::is_route_target(value))
    1832          32 :             continue;
    1833         874 :         RouteTarget rtarget(value);
    1834         874 :         if (export_.find(rtarget) != export_.end())
    1835         368 :             return true;
    1836             :     }
    1837             : 
    1838         100 :     return false;
    1839             : }
    1840             : 
    1841             : // Return true if the route is a service-chain route
    1842      386603 : bool RoutingInstance::IsServiceChainRoute(const BgpRoute *route) const {
    1843      386603 :     const BgpTable *table = route->table();
    1844      386627 :     if (!table) {
    1845           0 :         return false;
    1846             :     }
    1847      386627 :     const BgpInstanceConfig *rt_config = this->config();
    1848      386625 :     if (!rt_config) {
    1849           0 :         return false;
    1850             :     }
    1851             :     SCAddress::Family sc_family =
    1852      386625 :         SCAddress::AddressFamilyToSCFamily(table->family());
    1853             :     const ServiceChainConfig *sc_config =
    1854      386625 :            rt_config->service_chain_info(sc_family);
    1855      386621 :     if (!sc_config) {
    1856      383674 :         return false;
    1857             :     }
    1858        2947 :     return true;
    1859             : }
    1860             : 
    1861             : //
    1862             : // On given route/path apply the routing policy
    1863             : //    Called from
    1864             : //        * InsertPath [While adding the path for the first time]
    1865             : //        * While walking the routing table to apply updating routing policy
    1866             : //
    1867             : 
    1868      451011 : bool RoutingInstance::ProcessRoutingPolicy(const BgpRoute *route,
    1869             :                                            BgpPath *path) const {
    1870      451011 :     ExtCommunityPtr ext_community = path->GetOriginalAttr()->ext_community();
    1871      837777 :     if (path->IsReplicated() &&
    1872      837774 :             ext_community && ext_community->GetSubClusterId()) {
    1873             :         // If self sub-cluster id macthes with what is associated with the route
    1874             :         // then no need to apply policy.
    1875           0 :         if (route->SubClusterId() == ext_community->GetSubClusterId()) {
    1876           0 :             BGP_LOG_ROUTE(route->table(), static_cast<IPeer *>(path->GetPeer()),
    1877             :                     route, "Not applying policy since sub-cluster associated "
    1878             :                     "with path is same as that with route");
    1879           0 :             return true;
    1880             :         }
    1881             :     }
    1882             :     // Don't apply routing policy on secondary path for service chain route
    1883      450981 :     if (path->IsReplicated() && IsServiceChainRoute(route)) {
    1884        2944 :         BGP_LOG_ROUTE(route->table(), static_cast<IPeer *>(path->GetPeer()),
    1885             :                 route, "Not applying policy for service-chain secondary "
    1886             :                 "routes");
    1887        2944 :         return true;
    1888             :     }
    1889      448020 :     const RoutingPolicyMgr *policy_mgr = server()->routing_policy_mgr();
    1890             :     // Take snapshot of original attribute
    1891      448041 :     BgpAttr *out_attr = new BgpAttr(*(path->GetOriginalAttr()));
    1892      449388 :     BOOST_FOREACH(RoutingPolicyInfo info, routing_policies()) {
    1893         765 :         RoutingPolicyPtr policy = info.first;
    1894             :         // Process the routing policy on original attribute and prefix
    1895             :         // Update of the attribute based on routing policy action is done
    1896             :         // on the snapshot of original attribute passed to this function
    1897             :         RoutingPolicy::PolicyResult result =
    1898         765 :             policy_mgr->ExecuteRoutingPolicy(policy.get(), route,
    1899             :                                              path, out_attr);
    1900         765 :         if (result.first) {
    1901             :             // Hit a terminal policy
    1902         144 :             if (!result.second) {
    1903             :                 // Result of the policy is reject
    1904          14 :                 path->SetPolicyReject();
    1905         130 :             } else if (path->IsPolicyReject()) {
    1906             :                 // Result of the policy is Accept
    1907             :                 // Clear the reject flag is marked before
    1908           1 :                 path->ResetPolicyReject();
    1909             :             }
    1910         144 :             IPeer *peer = path->GetPeer();
    1911             :             // Process default tunnel encapsulation that may be configured per
    1912             :             // address family on the peer. 'peer' is not expected to be NULL
    1913             :             // except in unit tests.
    1914         144 :             if (peer) {
    1915         278 :                 peer->ProcessPathTunnelEncapsulation(path, out_attr,
    1916         139 :                     server_->extcomm_db(), route->table());
    1917             :             }
    1918         144 :             BgpAttrPtr modified_attr = server_->attr_db()->Locate(out_attr);
    1919             :             // Update the path with new set of attributes
    1920         144 :             path->SetAttr(modified_attr, path->GetOriginalAttr());
    1921         144 :             return result.second;
    1922         144 :         }
    1923        1530 :     }
    1924             :     // After processing all the routing policy,,
    1925             :     // We are here means, all the routing policies have accepted the route
    1926      447868 :     IPeer *peer = path->GetPeer();
    1927      447866 :     if (peer) {
    1928      757747 :         peer->ProcessPathTunnelEncapsulation(path, out_attr,
    1929      378893 :             server_->extcomm_db(), route->table());
    1930             :     }
    1931      447881 :     BgpAttrPtr modified_attr = server_->attr_db()->Locate(out_attr);
    1932      448000 :     path->SetAttr(modified_attr, path->GetOriginalAttr());
    1933             :     // Clear the reject if marked so in past
    1934      447999 :     if (path->IsPolicyReject()) path->ResetPolicyReject();
    1935      447992 :     return true;
    1936      451080 : }
    1937             : 
    1938         122 : IStaticRouteMgr *RoutingInstance::LocateStaticRouteMgr(
    1939             :     Address::Family family) {
    1940         122 :     IStaticRouteMgr *manager = static_route_mgr(family);
    1941         122 :     if (manager)
    1942           0 :         return manager;
    1943         122 :     if (family == Address::INET) {
    1944          79 :         inet_static_route_mgr_.reset(
    1945          79 :             BgpStaticObjectFactory::Create<IStaticRouteMgr, Address::INET>(this));
    1946          79 :         return inet_static_route_mgr_.get();
    1947          43 :     } else if (family == Address::INET6) {
    1948          43 :         inet6_static_route_mgr_.reset(
    1949          43 :             BgpStaticObjectFactory::Create<IStaticRouteMgr, Address::INET6>(this));
    1950          43 :         return inet6_static_route_mgr_.get();
    1951             :     }
    1952           0 :     return NULL;
    1953             : }
    1954             : 
    1955         160 : IRouteAggregator *RoutingInstance::LocateRouteAggregator(
    1956             :     Address::Family family) {
    1957         160 :     IRouteAggregator *aggregator = route_aggregator(family);
    1958         160 :     if (aggregator)
    1959           0 :         return aggregator;
    1960         160 :     if (family == Address::INET) {
    1961         152 :         GetTable(family)->LocatePathResolver();
    1962         152 :         inet_route_aggregator_.reset(
    1963         152 :             BgpStaticObjectFactory::Create<IRouteAggregator, Address::INET>(this));
    1964         152 :         inet_route_aggregator_->Initialize();
    1965         152 :         return inet_route_aggregator_.get();
    1966           8 :     } else if (family == Address::INET6) {
    1967           8 :         GetTable(family)->LocatePathResolver();
    1968           8 :         inet6_route_aggregator_.reset(
    1969           8 :             BgpStaticObjectFactory::Create<IRouteAggregator, Address::INET6>(this));
    1970           8 :         inet6_route_aggregator_->Initialize();
    1971           8 :         return inet6_route_aggregator_.get();
    1972             :     }
    1973           0 :     return NULL;
    1974             : }
    1975             : 
    1976         160 : void RoutingInstance::DestroyRouteAggregator(Address::Family family) {
    1977         160 :     if (family == Address::INET) {
    1978         152 :         inet_route_aggregator_.reset();
    1979           8 :     } else if (family == Address::INET6) {
    1980           8 :         inet6_route_aggregator_.reset();
    1981             :     }
    1982         160 : }
    1983             : 
    1984             : // Check whether the route is aggregating route
    1985         200 : bool RoutingInstance::IsAggregateRoute(const BgpTable *table,
    1986             :                                        const BgpRoute *route) const {
    1987         200 :     if (!route_aggregator(table->family())) return false;
    1988         200 :     return route_aggregator(table->family())->IsAggregateRoute(route);
    1989             : }
    1990             : 
    1991             : // Check whether the route is contributing route to aggregate route
    1992      920690 : bool RoutingInstance::IsContributingRoute(const BgpTable *table,
    1993             :                                           const BgpRoute *route) const {
    1994      920690 :     if (!route_aggregator(table->family())) return false;
    1995        1897 :     return route_aggregator(table->family())->IsContributingRoute(route);
    1996             : }
    1997             : 
    1998        2052 : int RoutingInstance::GetOriginVnForAggregateRoute(Address::Family fmly) const {
    1999             :     SCAddress sc_addr;
    2000             :     SCAddress::Family sc_family =
    2001        2052 :          sc_addr.AddressFamilyToSCFamily(fmly);
    2002             :     const ServiceChainConfig *sc_config =
    2003        2052 :         config_ ? config_->service_chain_info(sc_family) : NULL;
    2004        2052 :     if (sc_config && !sc_config->routing_instance.empty()) {
    2005             :         RoutingInstance *dest =
    2006          36 :             mgr_->GetRoutingInstanceLocked(sc_config->routing_instance);
    2007          36 :         if (dest) return dest->virtual_network_index();
    2008             :     }
    2009        2016 :     return virtual_network_index_;
    2010             : }
    2011             : 
    2012          25 : size_t RoutingInstance::peer_manager_size() const {
    2013          25 :     return (peer_manager_ ? peer_manager_->size() : 0);
    2014             : }
    2015             : 
    2016       19227 : PeerManager *RoutingInstance::LocatePeerManager() {
    2017       19227 :     if (!peer_manager_)
    2018        8350 :         peer_manager_.reset(BgpStaticObjectFactory::Create<PeerManager>(this));
    2019       19227 :     return peer_manager_.get();
    2020             : }
    2021             : 
    2022             : // Get primary routing instance name from service RI names which works for both
    2023             : // in-network and transparent service chains. Use name based lookup to identify
    2024             : // the primary RI of service instance.
    2025             : // Service RI Name Format: <domain>:<project>:<VN>:<ServiceRI>
    2026             : // Primaru RI Name Format: <domain>:<project>:<VN>:<VN>
    2027       16481 : string RoutingInstanceMgr::GetPrimaryRoutingInstanceName(const string &name) {
    2028       16481 :     string n = name;
    2029       16481 :     vector<string> tokens;
    2030       16481 :     boost::split(tokens, n, boost::is_any_of(":"));
    2031       16481 :     if (tokens.size() < 3)
    2032       16479 :         return "";
    2033           2 :     ostringstream os;
    2034           2 :     os << tokens[0] << ":" << tokens[1] << ":" << tokens[2] << ":" << tokens[2];
    2035           2 :     return os.str();
    2036       16481 : }

Generated by: LCOV version 1.14