LCOV - code coverage report
Current view: top level - bgp - bgp_table.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 635 678 93.7 %
Date: 2026-06-11 01:56:02 Functions: 49 52 94.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include "bgp/bgp_table.h"
       6             : 
       7             : #include <boost/foreach.hpp>
       8             : 
       9             : #include "sandesh/sandesh_trace.h"
      10             : #include "base/task_annotations.h"
      11             : #include "bgp/bgp_log.h"
      12             : #include "bgp/bgp_membership.h"
      13             : #include "bgp/bgp_peer.h"
      14             : #include "bgp/bgp_peer_types.h"
      15             : #include "bgp/bgp_ribout.h"
      16             : #include "bgp/bgp_ribout_updates.h"
      17             : #include "bgp/bgp_route.h"
      18             : #include "bgp/bgp_server.h"
      19             : #include "bgp/bgp_update.h"
      20             : #include "bgp/inet/inet_table.h"
      21             : #include "bgp/routing-instance/iroute_aggregator.h"
      22             : #include "bgp/routing-instance/path_resolver.h"
      23             : #include "bgp/routing-instance/routing_instance.h"
      24             : #include "bgp/routing-instance/rtarget_group_mgr.h"
      25             : #include "bgp/tunnel_encap/tunnel_encap.h"
      26             : #include "net/community_type.h"
      27             : 
      28             : using std::make_pair;
      29             : using std::string;
      30             : 
      31             : class BgpTable::DeleteActor : public LifetimeActor {
      32             :   public:
      33      288583 :     explicit DeleteActor(BgpTable *table)
      34      288583 :         : LifetimeActor(table->rtinstance_->server()->lifetime_manager()),
      35      288583 :           table_(table) {
      36      288585 :     }
      37      577174 :     virtual ~DeleteActor() {
      38      577174 :     }
      39      294954 :     virtual bool MayDelete() const {
      40      294954 :         return table_->MayDelete();
      41             :     }
      42             : 
      43      288587 :     virtual void Shutdown() {
      44      288587 :         table_->Shutdown();
      45      288587 :     }
      46             : 
      47             :     // Make sure that all notifications have been processed and all db
      48             :     // state have been cleared for all partitions, before we inform the
      49             :     // parent instance that this table deletion process is complete.
      50      288587 :     virtual void Destroy() {
      51      288587 :         table_->rtinstance_->DestroyDBTable(table_);
      52      288587 :     }
      53             : 
      54             :   private:
      55             :     BgpTable *table_;
      56             : };
      57             : 
      58      296903 : BgpTable::BgpTable(DB *db, const string &name)
      59             :     : RouteTable(db, name),
      60      296866 :       rtinstance_(NULL),
      61      296866 :       path_resolver_(NULL),
      62      296903 :       instance_delete_ref_(this, NULL) {
      63      296872 :     primary_path_count_ = 0;
      64      296960 :     secondary_path_count_ = 0;
      65      296965 :     infeasible_path_count_ = 0;
      66      296942 :     stale_path_count_ = 0;
      67      296961 :     llgr_stale_path_count_ = 0;
      68      296964 : }
      69             : 
      70             : //
      71             : // Remove the table from the instance dependents before attempting to
      72             : // destroy the DeleteActor which can have its Delete() method be called
      73             : // via the reference.
      74             : //
      75      296970 : BgpTable::~BgpTable() {
      76      296970 :     assert(path_resolver_ == NULL),
      77      296970 :     instance_delete_ref_.Reset(NULL);
      78      296970 : }
      79             : 
      80      288585 : void BgpTable::set_routing_instance(RoutingInstance *rtinstance) {
      81      288585 :     rtinstance_ = rtinstance;
      82      288585 :     assert(rtinstance);
      83      288585 :     deleter_.reset(new DeleteActor(this));
      84      288582 :     instance_delete_ref_.Reset(rtinstance->deleter());
      85      288582 : }
      86             : 
      87     3022117 : BgpServer *BgpTable::server() {
      88     3022117 :     return rtinstance_->server();
      89             : }
      90             : 
      91     1766052 : const BgpServer *BgpTable::server() const {
      92     1766052 :     return rtinstance_->server();
      93             : }
      94             : 
      95             : //
      96             : // Find the RibOut for the given RibExportPolicy.
      97             : //
      98          60 : RibOut *BgpTable::RibOutFind(const RibExportPolicy &policy) {
      99          60 :     RibOutMap::iterator loc = ribout_map_.find(policy);
     100          60 :     return (loc != ribout_map_.end()) ? loc->second : NULL;
     101             : }
     102             : 
     103             : //
     104             : // Find or create the RibOut associated with the given RibExportPolicy.
     105             : // If a new RibOut is created, an entry for the pair gets added to the
     106             : // RibOutMap.
     107             : //
     108       82951 : RibOut *BgpTable::RibOutLocate(BgpUpdateSender *sender,
     109             :                                const RibExportPolicy &policy) {
     110       82951 :     RibOutMap::iterator loc = ribout_map_.find(policy);
     111       82951 :     if (loc == ribout_map_.end()) {
     112       34968 :         RibOut *ribout = new RibOut(this, sender, policy);
     113       34968 :         ribout_map_.insert(make_pair(policy, ribout));
     114       34968 :         return ribout;
     115             :     }
     116       47983 :     return loc->second;
     117             : }
     118             : 
     119             : //
     120             : // Delete the entry corresponding to the given RibExportPolicy from the
     121             : // RibOutMap.  Also deletes the RibOut itself.
     122             : //
     123       34936 : void BgpTable::RibOutDelete(const RibExportPolicy &policy) {
     124       34936 :     RibOutMap::iterator loc = ribout_map_.find(policy);
     125       34936 :     assert(loc != ribout_map_.end());
     126       34936 :     delete loc->second;
     127       34936 :     ribout_map_.erase(loc);
     128       34936 : }
     129             : 
     130             : // If both as2 and as4 aggregators are present then we need to choose one
     131      245225 : void BgpTable::CheckAggregatorAttr(BgpAttr *attr) const {
     132      245225 :     if (attr->aggregator_as_num() && attr->aggregator_as4_num()) {
     133          32 :         if (attr->aggregator_as_num() != AS_TRANS) {
     134             :             // If as2 aggregator is not as_trans then we ignore as4 aggregator
     135             :             // and ignore as4_path also
     136          16 :             attr->set_as4_path(NULL);
     137          16 :             attr->set_as4_aggregator(0, attr->aggregator_adderess());
     138             :         } else {
     139             :             // If as2 aggregator is as_trans then we use as4 aggregator
     140          16 :             attr->set_aggregator(attr->aggregator_as4_num(),
     141          16 :                                  attr->aggregator_adderess());
     142          16 :             attr->set_as4_aggregator(0, attr->aggregator_adderess());
     143             :         }
     144             :     }
     145      245223 : }
     146             : 
     147      200863 : void BgpTable::PrependLocalAs(const RibOut *ribout, BgpAttr *clone,
     148             :         const IPeer* peer) const {
     149      200863 :     CheckAggregatorAttr(clone);
     150      200866 :     as_t local_as = ribout->local_as() ?:
     151         466 :                 clone->attr_db()->server()->local_autonomous_system();
     152      200864 :     if (!server()->enable_4byte_as())
     153      200538 :        return PrependAsToAsPath2Byte(clone, (as2_t)local_as);
     154         321 :     if (ribout->as4_supported()) {
     155         121 :         if (clone->aspath_4byte())
     156          48 :             PrependAsToAsPath4Byte(clone, local_as);
     157             :         else
     158          73 :             CreateAsPath4Byte(clone, local_as);
     159             :     } else {
     160         200 :         if (!clone->as_path())
     161          52 :             CreateAsPath2Byte(clone);
     162         200 :         PrependAsToAsPath2Byte(clone, local_as);
     163             :     }
     164             : }
     165             : 
     166          82 : void BgpTable::RemovePrivateAs(const RibOut *ribout, BgpAttr *attr) const {
     167          82 :     bool all = ribout->remove_private_all();
     168          82 :     bool replace = ribout->remove_private_replace();
     169          82 :     bool peer_loop_check = ribout->remove_private_peer_loop_check();
     170             : 
     171          82 :     const AsPathSpec &spec = attr->as_path()->path();
     172          82 :     as_t peer_asn = peer_loop_check ? ribout->peer_as() : 0;
     173          82 :     as_t replace_asn = 0;
     174          82 :     if (replace) {
     175          56 :         if (ribout->peer_type() == BgpProto::EBGP) {
     176          32 :             replace_asn = server()->local_autonomous_system();
     177             :         } else {
     178          24 :             replace_asn = spec.AsLeftMostPublic();
     179             :         }
     180             :     }
     181          82 :     if (replace_asn > AS2_MAX) {
     182           8 :         if (!attr->as4_path())
     183           8 :             CreateAs4Path(attr);
     184           8 :         const As4PathSpec &spec = attr->as4_path()->path();
     185           8 :         As4PathSpec *new_spec = spec.RemovePrivate(all, replace_asn, peer_asn);
     186           8 :         attr->set_as4_path(new_spec);
     187           8 :         delete new_spec;
     188           8 :         replace_asn = AS_TRANS;
     189             :     }
     190          82 :     if (peer_asn > AS2_MAX)
     191           8 :         peer_asn = AS_TRANS;
     192             : 
     193          82 :     AsPathSpec *new_spec = spec.RemovePrivate(all, replace_asn, peer_asn);
     194          82 :     attr->set_as_path(new_spec);
     195          82 :     delete new_spec;
     196          82 : }
     197             : 
     198          24 : void BgpTable::RemovePrivate4ByteAs(const RibOut *ribout, BgpAttr *attr) const {
     199          24 :     bool all = ribout->remove_private_all();
     200          24 :     bool replace = ribout->remove_private_replace();
     201          24 :     bool peer_loop_check = ribout->remove_private_peer_loop_check();
     202             : 
     203          24 :     const AsPath4ByteSpec &spec = attr->aspath_4byte()->path();
     204          24 :     as_t peer_asn = peer_loop_check ? ribout->peer_as() : 0;
     205          24 :     as_t replace_asn = 0;
     206          24 :     if (replace) {
     207          16 :         if (ribout->peer_type() == BgpProto::EBGP) {
     208          16 :             replace_asn = server()->local_autonomous_system();
     209             :         } else {
     210           0 :             replace_asn = spec.AsLeftMostPublic();
     211             :         }
     212             :     }
     213             : 
     214          24 :     AsPath4ByteSpec *new_spec = spec.RemovePrivate(all, replace_asn, peer_asn);
     215          24 :     attr->set_aspath_4byte(new_spec);
     216          24 :     delete new_spec;
     217          24 : }
     218             : 
     219           8 : void BgpTable::RemovePrivateAs4(const RibOut *ribout, BgpAttr *attr) const {
     220           8 :     bool all = ribout->remove_private_all();
     221           8 :     bool replace = ribout->remove_private_replace();
     222           8 :     bool peer_loop_check = ribout->remove_private_peer_loop_check();
     223             : 
     224           8 :     const As4PathSpec &spec = attr->as4_path()->path();
     225           8 :     as_t peer_asn = peer_loop_check ? ribout->peer_as() : 0;
     226           8 :     as_t replace_asn = 0;
     227           8 :     if (replace) {
     228           8 :         if (ribout->peer_type() == BgpProto::EBGP) {
     229           8 :             replace_asn = server()->local_autonomous_system();
     230             :         } else {
     231           0 :             replace_asn = spec.AsLeftMostPublic();
     232             :         }
     233             :     }
     234             : 
     235           8 :     As4PathSpec *new_spec = spec.RemovePrivate(all, replace_asn, peer_asn);
     236           8 :     attr->set_as4_path(new_spec);
     237           8 :     delete new_spec;
     238           8 : }
     239             : 
     240             : //
     241             : // Process Remove Private information.
     242             : //
     243      245226 : void BgpTable::ProcessRemovePrivate(const RibOut *ribout, BgpAttr *attr) const {
     244      245226 :     if (!ribout->IsEncodingBgp())
     245           0 :         return;
     246      245226 :     if (!ribout->remove_private_enabled())
     247      245113 :         return;
     248             : 
     249         111 :     if (attr->as_path())
     250          82 :         RemovePrivateAs(ribout, attr);
     251         110 :     if (attr->aspath_4byte())
     252          24 :         RemovePrivate4ByteAs(ribout, attr);
     253         110 :     if (attr->as4_path())
     254           8 :         RemovePrivateAs4(ribout, attr);
     255             : }
     256             : 
     257             : //
     258             : // Process Remove Private information.
     259             : //
     260      200870 : void BgpTable::ProcessAsOverride(const RibOut *ribout, BgpAttr *attr) const {
     261      200870 :     if (ribout->as_override() && !attr->IsAsPathEmpty()) {
     262          52 :         as_t replace_as = ribout->local_as() ?:
     263          52 :                 attr->attr_db()->server()->local_autonomous_system();
     264          52 :         if (attr->as_path()) {
     265          44 :             const AsPathSpec &as_path = attr->as_path()->path();
     266             :             // If peer_as is > 0xffff, it can't be in as_path
     267          44 :             if (ribout->peer_as() <= AS2_MAX) {
     268          44 :                 if (replace_as > AS2_MAX) {
     269             :                     // if replace_as > 0xffff, as4_path should be created if
     270             :                     // not already there by copying data from as_path
     271          12 :                     if (!attr->as4_path()) {
     272          12 :                         CreateAs4Path(attr);
     273             :                     }
     274          12 :                     replace_as = AS_TRANS;
     275             :                 }
     276          44 :                 AsPathSpec *as_path_ptr = as_path.Replace(
     277          44 :                                                  ribout->peer_as(), replace_as);
     278          44 :                 attr->set_as_path(as_path_ptr);
     279          44 :                 delete as_path_ptr;
     280             :             }
     281          44 :             if (attr->as4_path()) {
     282          12 :                 As4PathSpec *as_path_ptr = attr->as4_path()->path().Replace(
     283             :                                                  ribout->peer_as(), replace_as);
     284          12 :                 attr->set_as4_path(as_path_ptr);
     285          12 :                 delete as_path_ptr;
     286             :             }
     287             :         }
     288          52 :         if (attr->aspath_4byte()) {
     289           8 :             const AsPath4ByteSpec &as_path = attr->aspath_4byte()->path();
     290             :             AsPath4ByteSpec *as_path_ptr =
     291           8 :                           as_path.Replace(ribout->peer_as(), replace_as);
     292           8 :             attr->set_aspath_4byte(as_path_ptr);
     293           8 :             delete as_path_ptr;
     294             :         }
     295             :     }
     296      200868 : }
     297             : 
     298             : //
     299             : // Process Long Lived Graceful Restart state information.
     300             : //
     301             : // For LLGR_STALE paths, if the peer supports LLGR then attach LLGR_STALE
     302             : // community. Otherwise, strip LLGR_STALE community, reduce LOCAL_PREF and
     303             : // attach NO_EXPORT community instead.
     304             : //
     305      245241 : void BgpTable::ProcessLlgrState(const RibOut *ribout, const BgpPath *path,
     306             :                                 BgpAttr *attr, bool llgr_stale_comm) {
     307      245241 :     if (!server() || !server()->comm_db())
     308           0 :         return;
     309             : 
     310             :     // Skip LLGR specific attributes manipulation for rtarget routes.
     311      245243 :     if (family() == Address::RTARGET)
     312       54343 :         return;
     313             : 
     314             :     // If the path is not marked as llgr_stale or if it does not have the
     315             :     // LLGR_STALE community, then no action is necessary.
     316      190900 :     if (!path->IsLlgrStale() && !llgr_stale_comm)
     317      185171 :         return;
     318             : 
     319             :     // If peers support LLGR, then attach LLGR_STALE community and return.
     320        5728 :     if (ribout->llgr()) {
     321        5715 :         if (!llgr_stale_comm) {
     322             :             CommunityPtr comm = server()->comm_db()->AppendAndLocate(
     323        5707 :                     attr->community(), CommunityType::LlgrStale);
     324        5707 :             attr->set_community(comm);
     325        5707 :         }
     326        5715 :         return;
     327             :     }
     328             : 
     329             :     // Peers do not understand LLGR. Bring down local preference instead to
     330             :     // make the advertised path less preferred.
     331          12 :     attr->set_local_pref(0);
     332             : 
     333             :     // Remove LLGR_STALE community as the peers do not support LLGR.
     334          12 :     if (llgr_stale_comm) {
     335             :         CommunityPtr comm = server()->comm_db()->RemoveAndLocate(
     336           8 :                                 attr->community(), CommunityType::LlgrStale);
     337           8 :         attr->set_community(comm);
     338           8 :     }
     339             : 
     340             :     // Attach NO_EXPORT community as well to make sure that this path does not
     341             :     // exits local AS, unless it is already present.
     342          20 :     if (!attr->community() ||
     343           8 :         !attr->community()->ContainsValue(CommunityType::NoExport)) {
     344             :         CommunityPtr comm = server()->comm_db()->AppendAndLocate(
     345          12 :                                 attr->community(), CommunityType::NoExport);
     346          12 :         attr->set_community(comm);
     347          12 :     }
     348             : }
     349             : 
     350      245246 : void BgpTable::ProcessDefaultTunnelEncapsulation(const RibOut *ribout,
     351             :     ExtCommunityDB *extcomm_db, BgpAttr *attr) const {
     352      245246 :     if (!ribout->ExportPolicy().default_tunnel_encap_list.empty()) {
     353           8 :         ExtCommunity::ExtCommunityList encap_list;
     354          30 :         BOOST_FOREACH(const string &encap_string,
     355             :           ribout->ExportPolicy().default_tunnel_encap_list) {
     356          11 :             TunnelEncap tunnel_encap(encap_string);
     357          11 :             encap_list.push_back(tunnel_encap.GetExtCommunity());
     358             :         }
     359           8 :         ExtCommunityPtr ext_community = attr->ext_community();
     360             :         ext_community =
     361          16 :             extcomm_db->ReplaceTunnelEncapsulationAndLocate(
     362           8 :             ext_community.get(), encap_list);
     363           8 :         attr->set_ext_community(ext_community);
     364           8 :     }
     365      245245 : }
     366             : 
     367      200731 : void BgpTable::PrependAsToAsPath2Byte(BgpAttr *attr, as2_t asn) const {
     368      200731 :     if (attr->as_path()) {
     369       70996 :         const AsPathSpec &as_path = attr->as_path()->path();
     370       70996 :         AsPathSpec *as_path_ptr = as_path.Add(asn);
     371       70986 :         attr->set_as_path(as_path_ptr);
     372       71002 :         delete as_path_ptr;
     373             :     } else {
     374      129740 :         AsPathSpec as_path;
     375      129755 :         AsPathSpec *as_path_ptr = as_path.Add(asn);
     376      129711 :         attr->set_as_path(as_path_ptr);
     377      129768 :         delete as_path_ptr;
     378      129767 :     }
     379      200767 : }
     380             : 
     381         200 : void BgpTable::PrependAsToAsPath2Byte(BgpAttr *attr, as_t asn) const {
     382         200 :     if (asn <= AS2_MAX) {
     383         116 :         if (attr->as_path() && attr->as4_path()) {
     384          30 :             PrependAsToAs4Path(attr, asn);
     385             :         }
     386         116 :         return PrependAsToAsPath2Byte(attr, static_cast<as2_t>(asn & AS2_MAX));
     387             :     }
     388          84 :     if (attr->as_path() && !attr->as4_path()) {
     389          46 :         CreateAs4Path(attr);
     390          46 :         assert(attr->as_path()->path().path_segments.size() ==
     391             :                     attr->as4_path()->path().path_segments.size());
     392             :     }
     393          84 :     as2_t as_trans = AS_TRANS;
     394          84 :     PrependAsToAsPath2Byte(attr, as_trans);
     395          84 :     PrependAsToAs4Path(attr, asn);
     396             : }
     397             : 
     398          48 : void BgpTable::PrependAsToAsPath4Byte(BgpAttr *clone, as_t asn) const {
     399          48 :     if (clone->aspath_4byte()) {
     400          48 :         const AsPath4ByteSpec &as4_path = clone->aspath_4byte()->path();
     401          48 :         AsPath4ByteSpec *as4_path_ptr = as4_path.Add(asn);
     402          48 :         clone->set_aspath_4byte(as4_path_ptr);
     403          48 :         delete as4_path_ptr;
     404             :     } else {
     405           0 :         AsPath4ByteSpec as_path;
     406           0 :         AsPath4ByteSpec *as_path_ptr = as_path.Add(asn);
     407           0 :         clone->set_aspath_4byte(as_path_ptr);
     408           0 :         delete as_path_ptr;
     409           0 :     }
     410          48 : }
     411             : 
     412         114 : void BgpTable::PrependAsToAs4Path(BgpAttr* attr, as_t asn) const {
     413         114 :     if (attr->as4_path()) {
     414         114 :         const As4PathSpec &as4_path = attr->as4_path()->path();
     415         114 :         As4PathSpec *as4_path_ptr = as4_path.Add(asn);
     416         114 :         attr->set_as4_path(as4_path_ptr);
     417         114 :         delete as4_path_ptr;
     418             :     } else {
     419           0 :         As4PathSpec as_path;
     420           0 :         As4PathSpec *as_path_ptr = as_path.Add(asn);
     421           0 :         attr->set_as4_path(as_path_ptr);
     422           0 :         delete as_path_ptr;
     423           0 :     }
     424         114 : }
     425             : 
     426             : // Create as4_path by copying data from as_path
     427          66 : void BgpTable::CreateAs4Path(BgpAttr *attr) const {
     428          66 :     if (!attr->as_path()) {
     429           0 :         return;
     430             :     }
     431             : 
     432          66 :     std::unique_ptr<As4PathSpec> new_as_path(new As4PathSpec);
     433          66 :     const AsPathSpec &as_path = attr->as_path()->path();
     434         107 :     for (size_t i = 0; i < as_path.path_segments.size(); i++) {
     435          41 :         As4PathSpec::PathSegment *ps4 = new As4PathSpec::PathSegment;
     436          41 :         AsPathSpec::PathSegment *ps = as_path.path_segments[i];
     437          41 :         ps4->path_segment_type = ps->path_segment_type;
     438         108 :         for (size_t j = 0; j < ps->path_segment.size(); j++) {
     439          67 :             as_t as = ps->path_segment[j];
     440          67 :             ps4->path_segment.push_back(as);
     441             :         }
     442          41 :         new_as_path->path_segments.push_back(ps4);
     443             :     }
     444          66 :     attr->set_as4_path(new_as_path.get());
     445          66 : }
     446             : 
     447             : // Check if aspath_4byte has any asn > 0xFFFF
     448          68 : bool BgpTable::Has4ByteAsn(BgpAttr *attr) const {
     449          68 :     if (!attr->aspath_4byte())
     450          14 :         return false;
     451          54 :     const AsPath4ByteSpec &as_path4 = attr->aspath_4byte()->path();
     452          74 :     for (size_t i = 0; i < as_path4.path_segments.size(); ++i) {
     453          54 :         AsPath4ByteSpec::PathSegment *ps4 = as_path4.path_segments[i];
     454          74 :         for (size_t j = 0; j < ps4->path_segment.size(); ++j) {
     455          54 :             if (ps4->path_segment[j] > AS2_MAX)
     456          34 :                 return true;
     457             :         }
     458             :     }
     459          20 :     return false;
     460             : }
     461             : 
     462             : // Create as_path (and as4_path) from as_path4byte
     463          68 : void BgpTable::CreateAsPath2Byte(BgpAttr *attr) const {
     464          68 :     std::unique_ptr<AsPathSpec> new_as_path(new AsPathSpec);
     465          68 :     As4PathSpec *new_as4_path = NULL;
     466          68 :     bool has_4byte_asn = Has4ByteAsn(attr);
     467          68 :     if (has_4byte_asn)
     468          34 :         new_as4_path = new As4PathSpec;
     469          68 :     if (attr->aspath_4byte()) {
     470          54 :         const AsPath4ByteSpec &as_path4 = attr->aspath_4byte()->path();
     471         124 :         for (size_t i = 0; i < as_path4.path_segments.size(); i++) {
     472          70 :             AsPathSpec::PathSegment *ps = new AsPathSpec::PathSegment;
     473          70 :             As4PathSpec::PathSegment *as4_ps = NULL;
     474          70 :             AsPath4ByteSpec::PathSegment *ps4 = as_path4.path_segments[i];
     475          70 :             ps->path_segment_type = ps4->path_segment_type;
     476          70 :             if (has_4byte_asn) {
     477          50 :                 as4_ps = new As4PathSpec::PathSegment;
     478          50 :                 as4_ps->path_segment_type = ps4->path_segment_type;
     479             :             }
     480         192 :             for (size_t j = 0; j < ps4->path_segment.size(); ++j) {
     481         122 :                 as_t as4 = ps4->path_segment[j];
     482         122 :                 if (as4 > AS2_MAX) {
     483          78 :                     as2_t as_trans = AS_TRANS;
     484          78 :                     ps->path_segment.push_back(as_trans);
     485             :                 } else {
     486          44 :                     ps->path_segment.push_back(static_cast<as2_t>(
     487             :                                                as4 & AS2_MAX));
     488             :                 }
     489         122 :                 if (has_4byte_asn)
     490         102 :                     as4_ps->path_segment.push_back(as4);
     491             :             }
     492          70 :             new_as_path->path_segments.push_back(ps);
     493          70 :             if (has_4byte_asn)
     494          50 :                 new_as4_path->path_segments.push_back(as4_ps);
     495             :         }
     496          54 :         attr->set_aspath_4byte(NULL);
     497             :     }
     498          68 :     attr->set_as_path(new_as_path.get());
     499          68 :     if (has_4byte_asn) {
     500          34 :         attr->set_as4_path(new_as4_path);
     501          34 :         delete new_as4_path;
     502             :     }
     503          68 : }
     504             : 
     505             : // Create aspath_4byte by merging as_path and as4_path
     506          77 : void BgpTable::CreateAsPath4Byte(BgpAttr *attr, as_t local_as) const {
     507          77 :     int as2_count = attr->as_path_count();
     508          77 :     int as4_count = attr->as4_path_count();
     509          77 :     if (as2_count < as4_count) {
     510           8 :         as4_count = 0;
     511           8 :         attr->set_as4_path(NULL);
     512             :     }
     513          77 :     AsPath4ByteSpec::PathSegment *ps4 = NULL;
     514          77 :     bool part_segment = false;
     515          77 :     std::unique_ptr <AsPath4ByteSpec> aspath_4byte(new AsPath4ByteSpec);
     516          77 :     if (attr->as_path()) {
     517          32 :         const AsPathSpec &as_path = attr->as_path()->path();
     518          32 :         int new_as_count = 0;
     519          86 :         for (size_t i = 0; i < as_path.path_segments.size() &&
     520          32 :                     new_as_count < (as2_count - as4_count) ; ++i) {
     521          30 :             ps4 = new AsPath4ByteSpec::PathSegment;
     522          30 :             AsPathSpec::PathSegment *ps = as_path.path_segments[i];
     523          30 :             ps4->path_segment_type = ps->path_segment_type;
     524          30 :             if (ps->path_segment_type == AsPathSpec::PathSegment::AS_SET) {
     525           0 :                 new_as_count++;
     526           0 :                 for (size_t j = 0; j < ps->path_segment.size(); ++j) {
     527           0 :                     as2_t as = ps->path_segment[j];
     528           0 :                     ps4->path_segment.push_back(as);
     529             :                 }
     530             :             } else {
     531         130 :                 for (size_t j = 0; j < ps->path_segment.size() &&
     532          54 :                         new_as_count < (as2_count - as4_count); ++j) {
     533          46 :                     new_as_count++;
     534          46 :                     as2_t as = ps->path_segment[j];
     535          46 :                     ps4->path_segment.push_back(as);
     536             :                 }
     537          30 :                 if (new_as_count == (as2_count - as4_count)) {
     538          30 :                     if (attr->as4_path()) {
     539           8 :                         part_segment = true;
     540           8 :                         break;
     541             :                     }
     542             :                 }
     543             :             }
     544          22 :             aspath_4byte->path_segments.push_back(ps4);
     545             :         }
     546          32 :         if (attr->as4_path()) {
     547          10 :             const As4PathSpec &as4_path = attr->as4_path()->path();
     548          20 :             for (size_t i = 0; i < as4_path.path_segments.size(); ++i) {
     549          10 :                 if (!part_segment) {
     550           2 :                     ps4 = new AsPath4ByteSpec::PathSegment;
     551             :                 }
     552          10 :                 part_segment = false;
     553          10 :                 As4PathSpec::PathSegment *ps = as4_path.path_segments[i];
     554          10 :                 ps4->path_segment_type = ps->path_segment_type;
     555          10 :                 if (ps->path_segment_type == As4PathSpec::PathSegment::AS_SET) {
     556           0 :                     new_as_count++;
     557           0 :                     for (size_t j = 0; j < ps->path_segment.size(); ++j) {
     558           0 :                         as2_t as = ps->path_segment[j];
     559           0 :                         ps4->path_segment.push_back(as);
     560             :                     }
     561             :                 } else {
     562          40 :                     for (size_t j = 0; j < ps->path_segment.size(); ++j) {
     563          30 :                         as_t as = ps->path_segment[j];
     564          30 :                         ps4->path_segment.push_back(as);
     565             :                     }
     566             :                 }
     567          10 :                 aspath_4byte->path_segments.push_back(ps4);
     568             :             }
     569          10 :             attr->set_as4_path(NULL);
     570             :         }
     571          32 :         attr->set_as_path(NULL);
     572             :     }
     573          77 :     if (local_as) {
     574          73 :         std::unique_ptr<AsPath4ByteSpec> as_path_spec(aspath_4byte->Add(local_as));
     575          73 :         attr->set_aspath_4byte(as_path_spec.get());
     576          73 :     } else {
     577           4 :         attr->set_aspath_4byte(aspath_4byte.get());
     578             :     }
     579          77 : }
     580             : 
     581      891636 : UpdateInfo *BgpTable::GetUpdateInfo(RibOut *ribout, BgpRoute *route,
     582             :         const RibPeerSet &peerset) {
     583      891636 :     const BgpPath *path = route->BestPath();
     584             : 
     585             :     // Ignore if there is no best-path.
     586      891696 :     if (!path)
     587          16 :         return NULL;
     588             : 
     589             :     // Don't advertise infeasible paths.
     590      891680 :     if (!path->IsFeasible())
     591        3104 :         return NULL;
     592             : 
     593             :     // Check whether the route is contributing route
     594      888565 :     if (IsRouteAggregationSupported() && IsContributingRoute(route))
     595           6 :         return NULL;
     596             : 
     597             :     // Needs to be outside the if block so it's not destroyed prematurely.
     598      888545 :     BgpAttrPtr attr_ptr;
     599      888545 :     const BgpAttr *attr = path->GetAttr();
     600             : 
     601      888508 :     RibPeerSet new_peerset = peerset;
     602             : 
     603             :     // LocalPref, Med and AsPath manipulation is needed only if the RibOut
     604             :     // has BGP encoding. Similarly, well-known communities do not apply if
     605             :     // the encoding is not BGP.
     606      888407 :     if (ribout->IsEncodingBgp()) {
     607             :         // Handle well-known communities.
     608      443216 :         if (attr->community() != NULL &&
     609        6940 :             attr->community()->communities().size()) {
     610       20670 :             BOOST_FOREACH(uint32_t value, attr->community()->communities()) {
     611        6964 :                 if (value == CommunityType::NoAdvertise)
     612          99 :                     return NULL;
     613             : 
     614       11412 :                 if ((ribout->peer_type() == BgpProto::EBGP) &&
     615        4504 :                     ((value == CommunityType::NoExport) ||
     616             :                      (value == CommunityType::NoExportSubconfed))) {
     617          43 :                     return NULL;
     618             :                 }
     619             :             }
     620             :         }
     621             : 
     622      436178 :         const IPeer *peer = path->GetPeer();
     623      436178 :         BgpAttr *clone = NULL;
     624      443017 :         bool llgr_stale_comm = attr->community() &&
     625        6841 :             attr->community()->ContainsValue(CommunityType::LlgrStale);
     626      436177 :         if (ribout->peer_type() == BgpProto::IBGP) {
     627             :             // Split horizon check.
     628       86528 :             if (peer && peer->CheckSplitHorizon(server()->cluster_id(),
     629             :                         ribout->cluster_id()))
     630       37282 :                 return NULL;
     631             : 
     632             :             // Handle route-target filtering.
     633       49253 :             if (IsVpnTable() && attr->ext_community() != NULL) {
     634       23661 :                 server()->rtarget_group_mgr()->GetRibOutInterestedPeers(
     635             :                     ribout, attr->ext_community(), peerset, &new_peerset);
     636       23661 :                 if (new_peerset.empty())
     637        4900 :                     return NULL;
     638             :             }
     639             : 
     640       44353 :             if (server()->cluster_id()) {
     641             :                 // Check if there is a loop in cluster_list
     642           8 :                 if (attr->cluster_list() && attr->cluster_list()->cluster_list()
     643           0 :                         .ClusterListLoop(server()->cluster_id())) {
     644           0 :                     return NULL;
     645             :                 }
     646             :             }
     647             : 
     648       44353 :             if (server()->cluster_id() && (family() != Address::RTARGET)) {
     649             :                 // route reflector should not reflect the route back to the peer
     650             :                 // from which it received that route, for non rtarget routes
     651             :                 // This is done by checking peer_router_id of all the feasible
     652             :                 // paths of this route
     653           8 :                 RibPeerSet route_peerset;
     654          16 :                 for (Route::PathList::iterator it= route->GetPathList().begin();
     655          32 :                         it != route->GetPathList().end(); it++) {
     656           8 :                     BgpPath *ipath = static_cast<BgpPath *>(it.operator->());
     657           8 :                     if (ipath->IsFeasible() && ipath->GetPeer()) {
     658           8 :                         const IPeer *ipeer = ipath->GetPeer();
     659           8 :                         const BgpPeer *bgp_peer = dynamic_cast<
     660           8 :                                                   const BgpPeer *>(ipeer);
     661           8 :                         if (bgp_peer)
     662           2 :                             route_peerset.set(bgp_peer->GetIndex());
     663             :                     }
     664             :                 }
     665           8 :                 RibOut::PeerIterator iter(ribout, new_peerset);
     666          30 :                 while (iter.HasNext()) {
     667          22 :                     int current_index = iter.index();
     668          22 :                     IPeerUpdate *peer = iter.Next();
     669          22 :                     const BgpPeer *bgp_peer = dynamic_cast<
     670          22 :                                               const BgpPeer *>(peer);
     671          22 :                     if (bgp_peer && route_peerset.test(bgp_peer->GetIndex()))
     672           2 :                         new_peerset.reset(current_index);
     673             :                 }
     674           8 :                 if (new_peerset.empty())
     675           0 :                     return NULL;
     676           8 :             }
     677             : 
     678       44353 :             clone = new BgpAttr(*attr);
     679             : 
     680             :             // Retain LocalPref value if set, else set default to 100.
     681       44359 :             if (clone->local_pref() == 0)
     682           0 :                 clone->set_local_pref(100);
     683             : 
     684             :             // Check aggregator attributes to identify which ones to be used
     685       44357 :             CheckAggregatorAttr(clone);
     686             : 
     687             :             // Should not normally be needed for iBGP, but there could be
     688             :             // complex configurations where this is useful.
     689       44356 :             ProcessRemovePrivate(ribout, clone);
     690             : 
     691             :             // Add Originator_Id if acting as route reflector and cluster_id
     692             :             // is not present
     693       44355 :             if (server()->cluster_id()) {
     694           8 :                 if (clone->originator_id().is_unspecified()) {
     695           8 :                     if (peer && (peer->bgp_identifier() != 0)) {
     696           2 :                         clone->set_originator_id(Ip4Address(
     697           2 :                                 peer->bgp_identifier()));
     698             :                     } else {
     699           6 :                         clone->set_originator_id(Ip4Address(
     700             :                                 server()->bgp_identifier()));
     701             :                     }
     702             :                 }
     703           8 :                 if (attr->cluster_list()) {
     704             :                     const ClusterListSpec &cluster =
     705           0 :                         clone->cluster_list()->cluster_list();
     706             :                     ClusterListSpec *cl_ptr = new ClusterListSpec(
     707           0 :                             server()->cluster_id(), &cluster);
     708           0 :                     clone->set_cluster_list(cl_ptr);
     709           0 :                     delete cl_ptr;
     710             :                 } else {
     711             :                     ClusterListSpec *cl_ptr = new ClusterListSpec(
     712           8 :                             server()->cluster_id(), NULL);
     713           8 :                     clone->set_cluster_list(cl_ptr);
     714           8 :                     delete cl_ptr;
     715             :                 }
     716             :             }
     717             :             // If the route is locally originated i.e. there's no AsPath,
     718             :             // then generate a Nil AsPath i.e. one with 0 length. No need
     719             :             // to modify the AsPath if it already exists since this is an
     720             :             // iBGP RibOut.
     721       44354 :             if (ribout->as4_supported() && !clone->aspath_4byte()) {
     722          53 :                 if (attr->as_path()) {
     723           4 :                     CreateAsPath4Byte(clone, 0);
     724             :                 } else {
     725          49 :                     AsPath4ByteSpec as_path;
     726          49 :                     clone->set_aspath_4byte(&as_path);
     727          49 :                 }
     728             :             }
     729       44354 :             if (!ribout->as4_supported() && !clone->as_path()) {
     730       40506 :                 if (attr->aspath_4byte()) {
     731          16 :                     CreateAsPath2Byte(clone);
     732             :                 } else {
     733       40490 :                     AsPathSpec as_path;
     734       40490 :                     clone->set_as_path(&as_path);
     735       40494 :                 }
     736             :             }
     737      349644 :         } else if (ribout->peer_type() == BgpProto::EBGP) {
     738             :             // Don't advertise routes from non-master instances if there's
     739             :             // no nexthop. The ribout has to be for bgpaas-clients because
     740             :             // that's the only case with bgp peers in non-master instance.
     741      352125 :             if (!rtinstance_->IsMasterRoutingInstance() &&
     742        2479 :                 ribout->nexthop().is_unspecified()) {
     743           0 :                 return NULL;
     744             :             }
     745             : 
     746             :             // Handle route-target filtering.
     747      349637 :             if (IsVpnTable() && attr->ext_community() != NULL) {
     748      292167 :                 server()->rtarget_group_mgr()->GetRibOutInterestedPeers(
     749             :                     ribout, attr->ext_community(), peerset, &new_peerset);
     750      292383 :                 if (new_peerset.empty())
     751       12690 :                     return NULL;
     752             :             }
     753             : 
     754             :             // Sender side AS path loop check and split horizon within RibOut.
     755      337166 :             if (!ribout->as_override()) {
     756      337106 :                 if (attr->IsAsPathLoop(ribout->peer_as()))
     757      136298 :                     return NULL;
     758             :             } else {
     759          60 :                 if (peer && peer->PeerType() == BgpProto::EBGP) {
     760          40 :                     ribout->GetSubsetPeerSet(&new_peerset, peer);
     761          40 :                     if (new_peerset.empty())
     762           0 :                         return NULL;
     763             :                 }
     764             :             }
     765             : 
     766      200855 :             clone = new BgpAttr(*attr);
     767             : 
     768             :             // Remove non-transitive attributes.
     769             :             // Note that med is handled further down.
     770      200890 :             clone->set_originator_id(Ip4Address());
     771      200883 :             clone->set_cluster_list(NULL);
     772             : 
     773             :             // Update nexthop.
     774      200876 :             if (!ribout->nexthop().is_unspecified())
     775        1602 :                 clone->set_nexthop(ribout->nexthop());
     776             : 
     777             :             // Reset LocalPref.
     778      200874 :             if (clone->local_pref())
     779      200874 :                 clone->set_local_pref(0);
     780             : 
     781             :             // Reset Med if the path did not originate from an xmpp peer.
     782             :             // The AS path is NULL if the originating xmpp peer is locally
     783             :             // connected. It's non-NULL but empty if the originating xmpp
     784             :             // peer is connected to another bgp speaker in the iBGP mesh.
     785      200871 :             if (clone->med() && !clone->IsAsPathEmpty())
     786         366 :                 clone->set_med(0);
     787             : 
     788             :             // Override the peer AS with local AS in AsPath.
     789      200871 :             ProcessAsOverride(ribout, clone);
     790             : 
     791             :             // Remove private processing must happen before local AS prepend.
     792      200869 :             ProcessRemovePrivate(ribout, clone);
     793             : 
     794             :             // Prepend the local AS to AsPath.
     795      200868 :             PrependLocalAs(ribout, clone, peer);
     796             :         }
     797             : 
     798      245243 :         assert(clone);
     799             : 
     800             :         // Update with the Default tunnel Encapsulation ordered List if
     801             :         // configured on the peer.
     802             :         // Note that all peers with the same list share the same Ribout, this is
     803             :         // ensured by making the Default Encapsulation List part of the Rib
     804             :         // Export policy.Note that, if there is Default Tunnel Encapsulation
     805             :         // configuration any tunnel encapsulation present is removed.
     806      245243 :         ProcessDefaultTunnelEncapsulation(ribout, server()->extcomm_db(),
     807             :                                           clone);
     808             : 
     809      245245 :         ProcessLlgrState(ribout, path, clone, llgr_stale_comm);
     810             : 
     811             :         // Locate the new BgpAttrPtr.
     812      245242 :         attr_ptr = clone->attr_db()->Locate(clone);
     813      245247 :         attr = attr_ptr.get();
     814             :     }
     815             : 
     816      697383 :     UpdateInfo *uinfo = new UpdateInfo;
     817      697499 :     uinfo->target = new_peerset;
     818      697461 :     uinfo->roattr = RibOutAttr(route, attr, ribout->IsEncodingXmpp());
     819      697786 :     return uinfo;
     820      889055 : }
     821             : 
     822             : // Bgp Path selection..
     823             : // Based Attribute weight
     824     1808321 : bool BgpTable::PathSelection(const Path &path1, const Path &path2) {
     825     1808321 :     const BgpPath &l_path = dynamic_cast<const BgpPath &> (path1);
     826     1808322 :     const BgpPath &r_path = dynamic_cast<const BgpPath &> (path2);
     827             : 
     828             :     // Check the weight of Path
     829     1808322 :     bool res = l_path.PathCompare(r_path, false) < 0;
     830             : 
     831     1808320 :     return res;
     832             : }
     833             : 
     834          73 : bool BgpTable::DeletePath(DBTablePartBase *root, BgpRoute *rt, BgpPath *path) {
     835         146 :     return InputCommon(root, rt, path, path->GetPeer(), NULL,
     836         146 :         DBRequest::DB_ENTRY_DELETE, NULL, path->GetPathId(), 0, 0, 0);
     837             : }
     838             : 
     839      538420 : bool BgpTable::InputCommon(DBTablePartBase *root, BgpRoute *rt, BgpPath *path,
     840             :                            const IPeer *peer, DBRequest *req,
     841             :                            DBRequest::DBOperation oper, BgpAttrPtr attrs,
     842             :                            uint32_t path_id, uint32_t flags, uint32_t label,
     843             :                            uint32_t l3_label) {
     844      538420 :     bool notify_rt = false;
     845             : 
     846      538420 :     switch (oper) {
     847      287747 :     case DBRequest::DB_ENTRY_ADD_CHANGE: {
     848      287747 :         assert(rt);
     849             : 
     850             :         // The entry may currently be marked as deleted.
     851      287747 :         rt->ClearDelete();
     852      287740 :         if (peer)
     853      243697 :             peer->UpdateCloseRouteStats(family(), path, flags);
     854             : 
     855             :         // Check whether peer already has a path.
     856      287737 :         if (path != NULL) {
     857       57079 :             if ((path->GetAttr() != attrs.get()) ||
     858       22448 :                 (path->GetFlags() != flags) ||
     859       59412 :                 (path->GetLabel() != label) ||
     860        2219 :                 (path->GetL3Label() != l3_label)) {
     861             :                 // Update Attributes and notify (if needed)
     862       34748 :                 if (path->NeedsResolution())
     863        1338 :                     path_resolver_->StopPathResolution(root->index(), path);
     864       34747 :                 rt->DeletePath(path);
     865             :             } else {
     866             :                 // Ignore duplicate update.
     867        2216 :                 break;
     868             :             }
     869             :         }
     870             : 
     871             :         BgpPath *new_path;
     872      571058 :         new_path = new BgpPath(
     873      285544 :             peer, path_id, BgpPath::BGP_XMPP, attrs, flags, label, l3_label);
     874             : 
     875             :         // Start path resolution for the new path if
     876             :         // (1) Path flag has ResolveNextHop set in which case the path will
     877             :         //     be resolved in the overlay routing table (or)
     878             :         // (2) Fast convergence knob is enabled in which case the path will
     879             :         //     be marked for resolution in the underlay (default) routing table
     880             :         // (3) Path resolution in this case is needed only for routes
     881             :         //     in the VRF routing tables and for INET, INET6 and EVPN
     882             :         //     address families.
     883      285541 :         bool fc_family = false;
     884      517878 :         if (family() == Address::INET || family() == Address::INET6 ||
     885      232340 :             family() == Address::EVPN) {
     886       99725 :             fc_family = true;
     887             :         }
     888      285512 :         bool fc_enabled = (server()->IsNextHopCheckEnabled() &&
     889      285490 :                        !rtinstance_->IsMasterRoutingInstance() && fc_family);
     890      285490 :         if (new_path->NeedsResolution() || fc_enabled) {
     891        2885 :             if (peer && !(peer->IsXmppPeer()) ) {
     892        2762 :                 rt->add_peer_sources(peer->ToString());
     893             :             }
     894        2885 :             Address::Family family = new_path->GetAttr()->nexthop_family();
     895             :             BgpTable *table;
     896        2885 :             if (new_path->NeedsResolution()) {
     897        2779 :                 table = rtinstance_->GetTable(family);
     898             :             } else {
     899             :                 // Fast convergence knob is enabled.
     900             :                 // Update path flag to indicate need for resolution.
     901         106 :                 new_path->SetResolveNextHop();
     902             : 
     903             :                 // Get the default table.
     904         106 :                 RoutingInstanceMgr *mgr = server()->routing_instance_mgr();
     905         106 :                 assert(mgr);
     906         106 :                 RoutingInstance *master_ri = mgr->GetDefaultRoutingInstance();
     907         106 :                 assert(master_ri);
     908         106 :                 table = master_ri->GetTable(family);
     909             :             }
     910        2885 :             path_resolver_->StartPathResolution(rt, new_path, table);
     911             :         }
     912             : 
     913      285485 :         rt->InsertPath(new_path);
     914      285523 :         notify_rt = true;
     915      285523 :         break;
     916             :     }
     917             : 
     918      250676 :     case DBRequest::DB_ENTRY_DELETE: {
     919      250676 :         if (rt && !rt->IsDeleted()) {
     920      250672 :             if (peer && !(peer->IsXmppPeer()) ) {
     921      153885 :                 rt->del_peer_sources(peer->ToString());
     922             :             }
     923      273013 :             BGP_LOG_ROUTE(this, const_cast<IPeer *>(peer), rt,
     924             :                           "Delete BGP path");
     925             : 
     926             :             // Remove the Path from the route
     927      250693 :             if (path->NeedsResolution())
     928        1547 :                 path_resolver_->StopPathResolution(root->index(), path);
     929      250687 :             rt->DeletePath(path);
     930      250744 :             notify_rt = true;
     931             :         }
     932      250747 :         break;
     933             :     }
     934             : 
     935           0 :     default: {
     936           0 :         assert(false);
     937             :         break;
     938             :     }
     939             :     }
     940      538486 :     return notify_rt;
     941             : }
     942             : 
     943      466718 : void BgpTable::Input(DBTablePartition *root, DBClient *client,
     944             :                      DBRequest *req) {
     945      466718 :     const IPeer *peer = (static_cast<RequestKey *>(req->key.get()))->GetPeer();
     946      466649 :     RequestData *data = static_cast<RequestData *>(req->data.get());
     947             : 
     948      466610 :     if (req->oper == DBRequest::DB_ENTRY_ADD_CHANGE && peer) {
     949             :         // Skip if this peer is down.
     950      239122 :         if (!peer->IsReady())
     951       22099 :             return;
     952             : 
     953             :         // For xmpp peers, verify that agent is subscribed to the table and
     954             :         // the route add is from the same incarnation of table subscription.
     955      229107 :         if (peer->IsXmppPeer() && peer->IsRegistrationRequired()) {
     956       59221 :             BgpMembershipManager *mgr = rtinstance_->server()->membership_mgr();
     957       59221 :             int instance_id = -1;
     958       59221 :             uint64_t subscription_gen_id = 0;
     959             :             bool is_registered =
     960       59221 :                 mgr->GetRegistrationInfo(const_cast<IPeer *>(peer), this,
     961             :                                          &instance_id, &subscription_gen_id);
     962       86219 :             if ((!is_registered && (family() != Address::RTARGET)) ||
     963       26998 :                 (is_registered &&
     964       26998 :                  (subscription_gen_id != data->subscription_gen_id()))) {
     965           3 :                 return;
     966             :             }
     967             :         }
     968             :     }
     969             : 
     970             :     // Create route if it's not already present in case of add/change.
     971      456590 :     BgpRoute *rt = TableFind(root, req->key.get());
     972      456497 :     if (!rt) {
     973      223864 :         if ((req->oper == DBRequest::DB_ENTRY_DELETE) ||
     974      212860 :             (req->oper == DBRequest::DB_ENTRY_NOTIFY))
     975       11379 :             return;
     976             : 
     977      212485 :         rt = static_cast<BgpRoute *>(Add(req));
     978      212468 :         static_cast<DBTablePartition *>(root)->Add(rt);
     979      230298 :         BGP_LOG_ROUTE(this, const_cast<IPeer *>(peer), rt,
     980             :                       "Insert new BGP path");
     981             :     }
     982             : 
     983      445185 :     if (req->oper == DBRequest::DB_ENTRY_NOTIFY) {
     984         419 :         root->Notify(rt);
     985         419 :         return;
     986             :     }
     987             : 
     988      444766 :     uint32_t path_id = 0;
     989      444766 :     uint32_t flags = 0;
     990      444766 :     uint32_t label = 0;
     991      444766 :     uint32_t l3_label = 0;
     992      444766 :     BgpPath *path = rt->FindPath(peer);
     993      444829 :     BgpAttrPtr attr = data ? data->attrs() : NULL;
     994      444847 :     if (req->oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
     995      273158 :         assert(data);
     996      273158 :         const RequestData::NextHop &nexthop = data->nexthop();
     997      273155 :         if (nexthop.address_.is_v4())
     998      268612 :             path_id = nexthop.address_.to_v4().to_ulong();
     999      273143 :         flags = nexthop.flags_;
    1000      273143 :         label = nexthop.label_;
    1001      273143 :         l3_label = nexthop.l3_label_;
    1002             : 
    1003      273143 :         attr = GetAttributes(rt, attr, peer);
    1004             :     } else {
    1005      171689 :         if (!path)
    1006         275 :             return;
    1007      171414 :         path_id = path->GetPathId();
    1008             :     }
    1009             : 
    1010      444556 :     bool notify_rt = InputCommon(root, rt, path, peer, req, req->oper,
    1011             :         attr, path_id, flags, label, l3_label);
    1012      444615 :     InputCommonPostProcess(root, rt, notify_rt);
    1013      444816 : }
    1014             : 
    1015      930571 : void BgpTable::InputCommonPostProcess(DBTablePartBase *root,
    1016             :                                       BgpRoute *rt, bool notify_rt) {
    1017      930571 :     if (!notify_rt)
    1018      394716 :         return;
    1019             : 
    1020      535855 :     if (rt->front() == NULL)
    1021      212895 :         root->Delete(rt);
    1022             :     else
    1023      322877 :         root->Notify(rt);
    1024             : }
    1025             : 
    1026      294954 : bool BgpTable::MayDelete() const {
    1027      294954 :     CHECK_CONCURRENCY("bgp::Config");
    1028             : 
    1029             :     // Bail if the table has listeners.
    1030      294954 :     if (HasListeners()) {
    1031        6353 :         BGP_LOG_TABLE(this, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
    1032             :                       "Paused table deletion due to pending listeners");
    1033        6353 :         return false;
    1034             :     }
    1035             : 
    1036             :     // Bail if the table has walkers.
    1037      288601 :     if (HasWalkers()) {
    1038           0 :         BGP_LOG_TABLE(this, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
    1039             :                       "Paused table deletion due to pending walkers");
    1040           0 :         return false;
    1041             :     }
    1042             : 
    1043             :     // Bail if the table is not empty.
    1044      288601 :     size_t size = Size();
    1045      288601 :     if (size > 0) {
    1046          14 :         BGP_LOG_TABLE(this, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
    1047             :                       "Paused table deletion due to " << size <<
    1048             :                       " pending routes");
    1049          14 :         return false;
    1050             :     }
    1051             : 
    1052             :     // Check the base class at the end so that we add custom checks
    1053             :     // before this if needed and to get more informative log message.
    1054      288587 :     if (!DBTableBase::MayDelete())
    1055           0 :         return false;
    1056             : 
    1057      288587 :     return true;
    1058             : }
    1059             : 
    1060      288587 : void BgpTable::Shutdown() {
    1061      288587 :     CHECK_CONCURRENCY("bgp::PeerMembership", "bgp::Config");
    1062      288587 : }
    1063             : 
    1064      288587 : void BgpTable::ManagedDelete() {
    1065      288587 :     BGP_LOG_TABLE(this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
    1066             :                   "Received request for table deletion");
    1067      288587 :     deleter_->Delete();
    1068      288587 : }
    1069             : 
    1070             : //
    1071             : // Retry deletion of the table if it is pending.
    1072             : //
    1073      575267 : void BgpTable::RetryDelete() {
    1074      575267 :     if (!deleter()->IsDeleted())
    1075      256378 :         return;
    1076      318885 :     deleter()->RetryDelete();
    1077             : }
    1078             : 
    1079           0 : PathResolver *BgpTable::CreatePathResolver() {
    1080           0 :     return NULL;
    1081             : }
    1082             : 
    1083      172727 : void BgpTable::LocatePathResolver() {
    1084      172727 :     if (path_resolver_)
    1085        1106 :         return;
    1086      171621 :     assert(!deleter()->IsDeleted());
    1087      171615 :     path_resolver_ = CreatePathResolver();
    1088             : }
    1089             : 
    1090      171628 : void BgpTable::DestroyPathResolver() {
    1091      171628 :     if (!path_resolver_)
    1092           0 :         return;
    1093      171628 :     delete path_resolver_;
    1094      171628 :     path_resolver_ = NULL;
    1095             : }
    1096             : 
    1097       14393 : size_t BgpTable::GetPendingRiboutsCount(size_t *markers) const {
    1098       14393 :     CHECK_CONCURRENCY("bgp::ShowCommand", "bgp::Config");
    1099       14393 :     size_t count = 0;
    1100       14393 :     *markers = 0;
    1101             : 
    1102       19685 :     BOOST_FOREACH(const RibOutMap::value_type &value, ribout_map_) {
    1103        2646 :         const RibOut *ribout = value.second;
    1104       11709 :         for (int idx = 0; idx < DB::PartitionCount(); ++idx) {
    1105        9063 :             const RibOutUpdates *updates = ribout->updates(idx);
    1106       27189 :             for (int qid = RibOutUpdates::QFIRST; qid < RibOutUpdates::QCOUNT;
    1107             :                  ++qid) {
    1108       18126 :                 count += updates->queue_size(qid);
    1109       18126 :                 *markers += updates->queue_marker_count(qid);
    1110             :             }
    1111             :         }
    1112             :     }
    1113             : 
    1114       14393 :     return count;
    1115             : }
    1116             : 
    1117     2075414 : LifetimeActor *BgpTable::deleter() {
    1118     2075414 :     return deleter_.get();
    1119             : }
    1120             : 
    1121      292230 : const LifetimeActor *BgpTable::deleter() const {
    1122      292230 :     return deleter_.get();
    1123             : }
    1124             : 
    1125     1929419 : void BgpTable::UpdatePathCount(const BgpPath *path, int count) {
    1126     1929419 :     if (dynamic_cast<const BgpSecondaryPath *>(path)) {
    1127     1157109 :         secondary_path_count_ += count;
    1128             :     } else {
    1129      772310 :         primary_path_count_ += count;
    1130             :     }
    1131             : 
    1132     1930478 :     if (!path->IsFeasible()) {
    1133        8618 :         infeasible_path_count_ += count;
    1134             :     }
    1135             : 
    1136     1930303 :     if (path->IsStale()) {
    1137       90356 :         stale_path_count_ += count;
    1138             :     }
    1139             : 
    1140     1930205 :     if (path->IsLlgrStale()) {
    1141       20297 :         llgr_stale_path_count_ += count;
    1142             :     }
    1143     1930078 : }
    1144             : 
    1145             : // Check whether the route is aggregate route
    1146           0 : bool BgpTable::IsAggregateRoute(const BgpRoute *route) const {
    1147           0 :     return routing_instance()->IsAggregateRoute(this, route);
    1148             : }
    1149             : 
    1150             : // Check whether the route is contributing route to aggregate route
    1151      919629 : bool BgpTable::IsContributingRoute(const BgpRoute *route) const {
    1152      919629 :     return routing_instance()->IsContributingRoute(this, route);
    1153             : }
    1154             : 
    1155          18 : void BgpTable::FillRibOutStatisticsInfo(
    1156             :     vector<ShowRibOutStatistics> *sros_list) const {
    1157          22 :     BOOST_FOREACH(const RibOutMap::value_type &value, ribout_map_) {
    1158           2 :         const RibOut *ribout = value.second;
    1159           2 :         ribout->FillStatisticsInfo(sros_list);
    1160             :     }
    1161          18 : }

Generated by: LCOV version 1.14