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

Generated by: LCOV version 1.14