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: 744 1224 60.8 %
Date: 2026-09-21 02:11:39 Functions: 89 129 69.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14