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

Generated by: LCOV version 1.14