LCOV - code coverage report
Current view: top level - bgp - bgp_attr.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 911 992 91.8 %
Date: 2026-06-08 02:02:55 Functions: 173 182 95.1 %
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_attr.h"
       6             : 
       7             : #include <algorithm>
       8             : #include <string>
       9             : 
      10             : #include "bgp/bgp_server.h"
      11             : #include "bgp/extended-community/esi_label.h"
      12             : #include "bgp/extended-community/etree.h"
      13             : #include "bgp/extended-community/mac_mobility.h"
      14             : #include "bgp/extended-community/router_mac.h"
      15             : #include "net/bgp_af.h"
      16             : 
      17             : using std::sort;
      18             : using std::vector;
      19             : using std::string;
      20             : 
      21        9985 : int BgpAttrOrigin::CompareTo(const BgpAttribute &rhs_attr) const {
      22        9985 :     int ret = BgpAttribute::CompareTo(rhs_attr);
      23        9985 :     if (ret != 0) return ret;
      24        9985 :     KEY_COMPARE(origin, static_cast<const BgpAttrOrigin &>(rhs_attr).origin);
      25        9985 :     return 0;
      26             : }
      27             : 
      28      184225 : void BgpAttrOrigin::ToCanonical(BgpAttr *attr) {
      29      184225 :     attr->set_origin(static_cast<BgpAttrOrigin::OriginType>(origin));
      30      184225 : }
      31             : 
      32      111055 : string BgpAttrOrigin::ToString() const {
      33             :     char repr[80];
      34      111055 :     snprintf(repr, sizeof(repr), "ORIGIN <code: %d, flags: %02x> : %02x",
      35      111055 :              code, flags, origin);
      36      111055 :     return string(repr);
      37             : }
      38             : 
      39        9981 : int BgpAttrNextHop::CompareTo(const BgpAttribute &rhs_attr) const {
      40        9981 :     int ret = BgpAttribute::CompareTo(rhs_attr);
      41        9981 :     if (ret != 0) return ret;
      42        9981 :     KEY_COMPARE(nexthop,
      43             :             static_cast<const BgpAttrNextHop &>(rhs_attr).nexthop);
      44        9981 :     return 0;
      45             : }
      46             : 
      47      191410 : void BgpAttrNextHop::ToCanonical(BgpAttr *attr) {
      48      191410 :     if (v6_nexthop.is_unspecified()) {
      49      188878 :         attr->set_nexthop(Ip4Address(nexthop));
      50             :     } else {
      51        2532 :         attr->set_nexthop(v6_nexthop);
      52             :     }
      53      191409 : }
      54             : 
      55        3166 : string BgpAttrNextHop::ToString() const {
      56             :     char repr[80];
      57        3166 :     snprintf(repr, sizeof(repr), "NEXTHOP <code: %d, flags: %02x> : %04x",
      58        3166 :              code, flags, nexthop);
      59        3166 :     return string(repr);
      60             : }
      61             : 
      62        1988 : int BgpAttrMultiExitDisc::CompareTo(const BgpAttribute &rhs_attr) const {
      63        1988 :     int ret = BgpAttribute::CompareTo(rhs_attr);
      64        1988 :     if (ret != 0) return ret;
      65        1988 :     KEY_COMPARE(med, static_cast<const BgpAttrMultiExitDisc &>(rhs_attr).med);
      66        1986 :     return 0;
      67             : }
      68       76276 : void BgpAttrMultiExitDisc::ToCanonical(BgpAttr *attr) {
      69       76276 :     attr->set_med(med);
      70       76276 : }
      71             : 
      72       51447 : string BgpAttrMultiExitDisc::ToString() const {
      73             :     char repr[80];
      74       51447 :     snprintf(repr, sizeof(repr), "MED <code: %d, flags: %02x> : %d",
      75       51447 :              code, flags, med);
      76       51447 :     return string(repr);
      77             : }
      78             : 
      79        1994 : int BgpAttrLocalPref::CompareTo(const BgpAttribute &rhs_attr) const {
      80        1994 :     int ret = BgpAttribute::CompareTo(rhs_attr);
      81        1994 :     if (ret != 0) return ret;
      82        1994 :     KEY_COMPARE(local_pref,
      83             :             static_cast<const BgpAttrLocalPref &>(rhs_attr).local_pref);
      84        1994 :     return 0;
      85             : }
      86       91886 : void BgpAttrLocalPref::ToCanonical(BgpAttr *attr) {
      87       91886 :     attr->set_local_pref(local_pref);
      88       91887 : }
      89             : 
      90       23647 : string BgpAttrLocalPref::ToString() const {
      91             :     char repr[80];
      92       23647 :     snprintf(repr, sizeof(repr), "LOCAL_PREF <code: %d, flags: %02x> : %d",
      93       23647 :              code, flags, local_pref);
      94       23647 :     return string(repr);
      95             : }
      96             : 
      97           9 : void BgpAttrAtomicAggregate::ToCanonical(BgpAttr *attr) {
      98           9 :     attr->set_atomic_aggregate(true);
      99           9 : }
     100             : 
     101           1 : string BgpAttrAtomicAggregate::ToString() const {
     102             :     char repr[80];
     103           1 :     snprintf(repr, sizeof(repr), "ATOMIC_AGGR <code: %d, flags: %02x>",
     104           1 :              code, flags);
     105           1 :     return string(repr);
     106             : }
     107             : 
     108           3 : int BgpAttr4ByteAggregator::CompareTo(const BgpAttribute &rhs_attr) const {
     109           3 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     110           3 :     if (ret != 0) return ret;
     111           3 :     KEY_COMPARE(as_num,
     112             :             static_cast<const BgpAttr4ByteAggregator &>(rhs_attr).as_num);
     113           3 :     KEY_COMPARE(address,
     114             :             static_cast<const BgpAttr4ByteAggregator &>(rhs_attr).address);
     115           3 :     return 0;
     116             : }
     117           1 : void BgpAttr4ByteAggregator::ToCanonical(BgpAttr *attr) {
     118           1 :     attr->set_aggregator(as_num, Ip4Address(address));
     119           1 : }
     120             : 
     121           0 : string BgpAttr4ByteAggregator::ToString() const {
     122             :     char repr[80];
     123           0 :     snprintf(repr, sizeof(repr),
     124             :              "Aggregator <code: %d, flags: %02x> : %d:%08x",
     125           0 :              code, flags, as_num, address);
     126           0 :     return string(repr);
     127             : }
     128             : 
     129        1973 : int BgpAttrAggregator::CompareTo(const BgpAttribute &rhs_attr) const {
     130        1973 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     131        1973 :     if (ret != 0) return ret;
     132        1973 :     KEY_COMPARE(as_num,
     133             :             static_cast<const BgpAttrAggregator &>(rhs_attr).as_num);
     134        1971 :     KEY_COMPARE(address,
     135             :             static_cast<const BgpAttrAggregator &>(rhs_attr).address);
     136        1969 :     return 0;
     137             : }
     138           8 : void BgpAttrAggregator::ToCanonical(BgpAttr *attr) {
     139           8 :     attr->set_aggregator(as_num, Ip4Address(address));
     140           8 : }
     141             : 
     142           1 : string BgpAttrAggregator::ToString() const {
     143             :     char repr[80];
     144           1 :     snprintf(repr, sizeof(repr),
     145             :              "Aggregator <code: %d, flags: %02x> : %d:%08x",
     146           1 :              code, flags, as_num, address);
     147           1 :     return string(repr);
     148             : }
     149             : 
     150           0 : int BgpAttrAs4Aggregator::CompareTo(const BgpAttribute &rhs_attr) const {
     151           0 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     152           0 :     if (ret != 0) return ret;
     153           0 :     KEY_COMPARE(as_num,
     154             :             static_cast<const BgpAttrAs4Aggregator &>(rhs_attr).as_num);
     155           0 :     KEY_COMPARE(address,
     156             :             static_cast<const BgpAttrAs4Aggregator &>(rhs_attr).address);
     157           0 :     return 0;
     158             : }
     159           0 : void BgpAttrAs4Aggregator::ToCanonical(BgpAttr *attr) {
     160           0 :     attr->set_as4_aggregator(as_num, Ip4Address(address));
     161           0 : }
     162             : 
     163           0 : string BgpAttrAs4Aggregator::ToString() const {
     164             :     char repr[80];
     165           0 :     snprintf(repr, sizeof(repr),
     166             :              "Aggregator <code: %d, flags: %02x> : %d:%08x",
     167           0 :              code, flags, as_num, address);
     168           0 :     return string(repr);
     169             : }
     170             : 
     171           3 : int BgpAttrOriginatorId::CompareTo(const BgpAttribute &rhs_attr) const {
     172           3 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     173           3 :     if (ret != 0) return ret;
     174           3 :     KEY_COMPARE(originator_id,
     175             :         static_cast<const BgpAttrOriginatorId &>(rhs_attr).originator_id);
     176           1 :     return 0;
     177             : }
     178             : 
     179          18 : void BgpAttrOriginatorId::ToCanonical(BgpAttr *attr) {
     180          18 :     attr->set_originator_id(Ip4Address(originator_id));
     181          18 : }
     182             : 
     183           3 : string BgpAttrOriginatorId::ToString() const {
     184             :     char repr[80];
     185           3 :     snprintf(repr, sizeof(repr), "OriginatorId <code: %d, flags: 0x%02x> : %s",
     186           6 :              code, flags, Ip4Address(originator_id).to_string().c_str());
     187           3 :     return string(repr);
     188             : }
     189             : 
     190           9 : ClusterListSpec::ClusterListSpec(uint32_t cluster_id,
     191           9 :     const ClusterListSpec *rhs)
     192           9 :     : BgpAttribute(BgpAttribute::ClusterList, kFlags) {
     193           9 :     cluster_list.push_back(cluster_id);
     194           9 :     if (rhs) {
     195           1 :         cluster_list.insert(cluster_list.end(), rhs->cluster_list.begin(),
     196             :             rhs->cluster_list.end());
     197             :     }
     198           9 : }
     199             : 
     200          46 : int ClusterListSpec::CompareTo(const BgpAttribute &rhs_attr) const {
     201          46 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     202          46 :     if (ret != 0) return ret;
     203          46 :     KEY_COMPARE(cluster_list,
     204             :         static_cast<const ClusterListSpec &>(rhs_attr).cluster_list);
     205          38 :     return 0;
     206             : }
     207             : 
     208           8 : void ClusterListSpec::ToCanonical(BgpAttr *attr) {
     209           8 :     attr->set_cluster_list(this);
     210           8 : }
     211             : 
     212           3 : string ClusterListSpec::ToString() const {
     213           3 :     std::stringstream repr;
     214           3 :     repr << "CLUSTER_LIST <code: " << int(code);
     215           3 :     repr << ", flags: 0x" << std::hex << int(flags) << "> :";
     216           3 :     for (vector<uint32_t>::const_iterator iter = cluster_list.begin();
     217           9 :          iter != cluster_list.end(); ++iter) {
     218           6 :         repr << " " << Ip4Address(*iter).to_string();
     219             :     }
     220           6 :     return repr.str();
     221           3 : }
     222             : 
     223          14 : bool ClusterListSpec::ClusterListLoop(uint32_t cluster_id) const {
     224          14 :     for (vector<uint32_t>::const_iterator iter = cluster_list.begin();
     225          56 :          iter != cluster_list.end(); ++iter) {
     226          47 :         if (*iter == cluster_id)
     227           5 :             return true;
     228             :     }
     229           9 :     return false;
     230             : }
     231             : 
     232          22 : ClusterList::ClusterList(ClusterListDB *cluster_list_db,
     233          22 :     const ClusterListSpec &spec)
     234          22 :     : cluster_list_db_(cluster_list_db),
     235          22 :       spec_(spec) {
     236          22 :     refcount_ = 0;
     237          22 : }
     238             : 
     239          18 : void ClusterList::Remove() {
     240          18 :     cluster_list_db_->Delete(this);
     241          18 : }
     242             : 
     243        9742 : ClusterListDB::ClusterListDB(BgpServer *server) {
     244        9742 : }
     245             : 
     246        1990 : int BgpMpNlri::CompareTo(const BgpAttribute &rhs_attr) const {
     247        1990 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     248        1990 :     if (ret != 0) return ret;
     249        1990 :     const BgpMpNlri &rhs = static_cast<const BgpMpNlri &>(rhs_attr);
     250        1990 :     KEY_COMPARE(afi, rhs.afi);
     251        1990 :     KEY_COMPARE(safi, rhs.safi);
     252        1990 :     KEY_COMPARE(nexthop, rhs.nexthop);
     253        1990 :     KEY_COMPARE(nlri.size(), rhs.nlri.size());
     254             : 
     255      498340 :     for (size_t i = 0; i < nlri.size(); i++) {
     256      496350 :         KEY_COMPARE(nlri[i]->type, rhs.nlri[i]->type);
     257      496350 :         KEY_COMPARE(nlri[i]->prefixlen, rhs.nlri[i]->prefixlen);
     258      496350 :         KEY_COMPARE(nlri[i]->prefix, rhs.nlri[i]->prefix);
     259             :     }
     260        1990 :     return 0;
     261             : }
     262             : 
     263      157796 : void BgpMpNlri::ToCanonical(BgpAttr *attr) {
     264      157796 : }
     265             : 
     266      507734 : size_t BgpMpNlri::EncodeLength() const {
     267      507734 :     size_t sz = 2 /* safi */ + 1 /* afi */ +
     268             :                 1 /* NlriNextHopLength */ +
     269             :                 1 /* Reserved */;
     270      507734 :     sz += nexthop.size();
     271      507721 :     for (vector<BgpProtoPrefix*>::const_iterator iter = nlri.begin();
     272     2859778 :          iter != nlri.end(); ++iter) {
     273     2352080 :         size_t bytes = 0;
     274     2352080 :         if (afi == BgpAf::L2Vpn &&
     275       40122 :             (safi == BgpAf::EVpn || safi == BgpAf::ErmVpn)) {
     276       40122 :             bytes = (*iter)->prefixlen;
     277             :         } else {
     278     2311958 :             bytes = ((*iter)->prefixlen + 7) / 8;
     279             :         }
     280     2352079 :         sz += 1 + bytes;
     281             :     }
     282      507657 :     return sz;
     283             : }
     284             : 
     285       25398 : PmsiTunnelSpec::PmsiTunnelSpec()
     286             :     : BgpAttribute(PmsiTunnel, kFlags),
     287       25398 :       tunnel_flags(0), tunnel_type(0), label(0) {
     288       25398 : }
     289             : 
     290        3007 : PmsiTunnelSpec::PmsiTunnelSpec(const BgpAttribute &rhs)
     291        3007 :     : BgpAttribute(rhs), tunnel_flags(0), tunnel_type(0), label(0) {
     292        3007 : }
     293             : 
     294      314292 : int PmsiTunnelSpec::CompareTo(const BgpAttribute &rhs_attr) const {
     295      314292 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     296      314292 :     if (ret != 0) return ret;
     297      314292 :     const PmsiTunnelSpec &rhs = static_cast<const PmsiTunnelSpec &>(rhs_attr);
     298      314292 :     KEY_COMPARE(tunnel_flags, rhs.tunnel_flags);
     299      302660 :     KEY_COMPARE(tunnel_type, rhs.tunnel_type);
     300      302653 :     KEY_COMPARE(label, rhs.label);
     301      278749 :     KEY_COMPARE(identifier, rhs.identifier);
     302      276033 :     return 0;
     303             : }
     304             : 
     305        8133 : void PmsiTunnelSpec::ToCanonical(BgpAttr *attr) {
     306        8133 :     attr->set_pmsi_tunnel(this);
     307        8133 : }
     308             : 
     309         839 : string PmsiTunnelSpec::ToString() const {
     310         839 :     std::ostringstream oss;
     311         839 :     oss << "PmsiTunnel <code: " << int(code);
     312         839 :     oss << ", flags: 0x" << std::hex << int(flags) << std::dec << ">";
     313         839 :     oss << " Tunnel Flags: 0x" << std::hex << int(tunnel_flags) << std::dec;
     314         839 :     oss << " Tunnel Type: " << int(tunnel_type);
     315         839 :     oss << " Label: 0x" << std::hex << int(label) << std::dec;
     316         839 :     oss << " (" << int(label) << ")";
     317         839 :     oss << " Identifier: " << GetIdentifier().to_string();
     318             : 
     319        1678 :     return oss.str();
     320         839 : }
     321             : 
     322           2 : uint32_t PmsiTunnelSpec::GetLabel(const ExtCommunity *ext) const {
     323           2 :     assert(ext);
     324           2 :     bool is_vni = ext->ContainsTunnelEncapVxlan();
     325           2 :     return (is_vni ? label : (label >> 4));
     326             : }
     327             : 
     328        7747 : void PmsiTunnelSpec::SetLabel(uint32_t in_label, const ExtCommunity *ext) {
     329        7747 :     assert(ext);
     330        7747 :     bool is_vni = ext->ContainsTunnelEncapVxlan();
     331        7747 :     label = (is_vni ? in_label : (in_label << 4 | 0x01));
     332        7747 : }
     333             : 
     334       18766 : Ip4Address PmsiTunnelSpec::GetIdentifier() const {
     335       18766 :     if (identifier.size() < 4)
     336        9828 :         return Ip4Address();
     337        8938 :     return Ip4Address(get_value(&identifier[0], 4));
     338             : }
     339             : 
     340       11690 : void PmsiTunnelSpec::SetIdentifier(Ip4Address in_identifier) {
     341       11690 :     identifier.resize(4, 0);
     342       11690 :     const Ip4Address::bytes_type &bytes = in_identifier.to_bytes();
     343       11690 :     std::copy(bytes.begin(), bytes.begin() + 4, identifier.begin());
     344       11690 : }
     345             : 
     346           9 : string PmsiTunnelSpec::GetTunnelTypeString() const {
     347           9 :     switch (tunnel_type) {
     348           1 :     case RsvpP2mpLsp:
     349           1 :         return "RsvpP2mpLsp";
     350           1 :     case LdpP2mpLsp:
     351           1 :         return "LdpP2mpLsp";
     352           1 :     case PimSsmTree:
     353           1 :         return "PimSsmTree";
     354           1 :     case PimSmTree:
     355           1 :         return "PimSmTree";
     356           1 :     case BidirPimTree:
     357           1 :         return "BidirPimTree";
     358           1 :     case IngressReplication:
     359           1 :         return "IngressReplication";
     360           1 :     case MldpMp2mpLsp:
     361           1 :         return "MldpMp2mpLsp";
     362           1 :     case AssistedReplicationContrail:
     363           1 :         return "AssistedReplication";
     364           1 :     default:
     365           1 :         break;
     366             :     }
     367           2 :     std::ostringstream oss;
     368           1 :     oss << "Unknown(" << int(tunnel_type) << ")";
     369           1 :     return oss.str();
     370             : }
     371             : 
     372           4 : string PmsiTunnelSpec::GetTunnelArTypeString() const {
     373           4 :     switch (tunnel_flags & AssistedReplicationType) {
     374           1 :     case RegularNVE:
     375           1 :         return "RegularNVE";
     376           1 :     case ARReplicator:
     377           1 :         return "ARReplicator";
     378           1 :     case ARLeaf:
     379           1 :         return "ARLeaf";
     380           1 :     default:
     381           1 :         break;
     382             :     }
     383           1 :     return "Unknown";
     384             : }
     385             : 
     386           4 : vector<string> PmsiTunnelSpec::GetTunnelFlagsStrings() const {
     387           4 :     vector<string> flags;
     388           4 :     if (tunnel_flags & LeafInfoRequired) {
     389           2 :         flags.push_back("LeafInfoRequired");
     390             :     }
     391           4 :     if (tunnel_flags & EdgeReplicationSupported) {
     392           2 :         flags.push_back("EdgeReplicationSupported");
     393             :     }
     394           4 :     if (flags.empty()) {
     395           1 :         flags.push_back("None");
     396             :     }
     397           4 :     return flags;
     398           0 : }
     399             : 
     400       17925 : PmsiTunnel::PmsiTunnel(PmsiTunnelDB *pmsi_tunnel_db,
     401       17925 :     const PmsiTunnelSpec &pmsi_spec)
     402       17925 :     : pmsi_tunnel_db_(pmsi_tunnel_db),
     403       17925 :       pmsi_spec_(pmsi_spec) {
     404       17918 :     refcount_ = 0;
     405       17925 :     tunnel_flags_ = pmsi_spec_.tunnel_flags;
     406       17925 :     tunnel_type_ = pmsi_spec_.tunnel_type;
     407       17925 :     label_ = pmsi_spec_.label;
     408       17925 :     identifier_ = pmsi_spec_.GetIdentifier();
     409       17925 : }
     410             : 
     411        4970 : void PmsiTunnel::Remove() {
     412        4970 :     pmsi_tunnel_db_->Delete(this);
     413        4970 : }
     414             : 
     415        2597 : uint32_t PmsiTunnel::GetLabel(const ExtCommunity *ext) const {
     416        2597 :     bool is_vni = false;
     417        2597 :     if (ext)
     418        2585 :         is_vni = ext->ContainsTunnelEncapVxlan();
     419        2597 :     return (is_vni ? label_ : label_ >> 4);
     420             : }
     421             : 
     422        9742 : PmsiTunnelDB::PmsiTunnelDB(BgpServer *server) {
     423        9742 : }
     424             : 
     425        5919 : EdgeDiscoverySpec::EdgeDiscoverySpec()
     426        5919 :     : BgpAttribute(McastEdgeDiscovery, kFlags) {
     427        5919 : }
     428             : 
     429        3842 : EdgeDiscoverySpec::EdgeDiscoverySpec(const BgpAttribute &rhs)
     430        3842 :     : BgpAttribute(rhs) {
     431        3842 : }
     432             : 
     433        4228 : EdgeDiscoverySpec::EdgeDiscoverySpec(const EdgeDiscoverySpec &rhs)
     434        4228 :     : BgpAttribute(BgpAttribute::McastEdgeDiscovery, kFlags) {
     435       13822 :     for (size_t i = 0; i < rhs.edge_list.size(); i++) {
     436        9596 :         Edge *edge = new Edge;
     437        9596 :         *edge = *rhs.edge_list[i];
     438        9596 :         edge_list.push_back(edge);
     439             :     }
     440        4226 : }
     441             : 
     442       22893 : EdgeDiscoverySpec::~EdgeDiscoverySpec() {
     443       13983 :     STLDeleteValues(&edge_list);
     444       22875 : }
     445             : 
     446       10111 : Ip4Address EdgeDiscoverySpec::Edge::GetIp4Address() const {
     447       10111 :     return Ip4Address(get_value(&address[0], 4));
     448             : }
     449             : 
     450      130484 : void EdgeDiscoverySpec::Edge::SetIp4Address(Ip4Address addr) {
     451      130484 :     address.resize(4, 0);
     452      130484 :     const Ip4Address::bytes_type &addr_bytes = addr.to_bytes();
     453      130484 :     std::copy(addr_bytes.begin(), addr_bytes.begin() + 4, address.begin());
     454      130484 : }
     455             : 
     456       10112 : void EdgeDiscoverySpec::Edge::GetLabels(
     457             :     uint32_t *first_label, uint32_t *last_label) const {
     458       10112 :     *first_label = labels[0];
     459       10111 :     *last_label = labels[1];
     460       10111 : }
     461             : 
     462      130484 : void EdgeDiscoverySpec::Edge::SetLabels(
     463             :     uint32_t first_label, uint32_t last_label) {
     464      130484 :     labels.push_back(first_label);
     465      130484 :     labels.push_back(last_label);
     466      130484 : }
     467             : 
     468             : struct EdgeDiscoverySpecEdgeCompare {
     469       63710 :     int operator()(const EdgeDiscoverySpec::Edge *lhs,
     470             :                    const EdgeDiscoverySpec::Edge *rhs) const {
     471       63710 :         KEY_COMPARE(lhs->address, rhs->address);
     472       63710 :         KEY_COMPARE(lhs->labels, rhs->labels);
     473       63710 :         return 0;
     474             :     }
     475             : };
     476             : 
     477        2003 : int EdgeDiscoverySpec::CompareTo(const BgpAttribute &rhs_attr) const {
     478        2003 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     479        2003 :     if (ret != 0) return ret;
     480        2003 :     const EdgeDiscoverySpec &rhs =
     481             :             static_cast<const EdgeDiscoverySpec &>(rhs_attr);
     482        2003 :     ret = STLSortedCompare(edge_list.begin(), edge_list.end(),
     483             :                            rhs.edge_list.begin(), rhs.edge_list.end(),
     484             :                            EdgeDiscoverySpecEdgeCompare());
     485        2003 :     return ret;
     486             : }
     487             : 
     488        2120 : void EdgeDiscoverySpec::ToCanonical(BgpAttr *attr) {
     489        2120 :     attr->set_edge_discovery(this);
     490        2120 : }
     491             : 
     492        1236 : string EdgeDiscoverySpec::ToString() const {
     493        1236 :     std::ostringstream oss;
     494        1237 :     oss << "EdgeDiscovery <code: " << int(code);
     495        1237 :     oss << ", flags: 0x" << std::hex << int(flags) << std::dec << ">";
     496        1237 :     int idx = 0;
     497        1237 :     for (EdgeList::const_iterator it = edge_list.begin();
     498        4943 :          it != edge_list.end(); ++it, ++idx) {
     499        3706 :         const Edge *edge = *it;
     500             :         uint32_t first_label, last_label;
     501        3706 :         edge->GetLabels(&first_label, &last_label);
     502        3705 :         oss << " Edge[" << idx << "] = (" << edge->GetIp4Address() << ", ";
     503        3707 :         oss << first_label << "-" << last_label << ")";
     504             :     }
     505             : 
     506        2474 :     return oss.str();
     507        1237 : }
     508             : 
     509       14005 : size_t EdgeDiscoverySpec::EncodeLength() const {
     510       14005 :     size_t sz = 0;
     511       14005 :     for (EdgeList::const_iterator iter = edge_list.begin();
     512      276894 :          iter != edge_list.end(); ++iter) {
     513      262889 :         sz += 2; /* AddressLen + LabelLen */
     514      262889 :         sz += (*iter)->address.size();
     515      262889 :         sz += (*iter)->labels.size() * sizeof(uint32_t);
     516             :     }
     517       14005 :     return sz;
     518             : }
     519             : 
     520        6378 : EdgeDiscovery::Edge::Edge(const EdgeDiscoverySpec::Edge *spec_edge) {
     521        6378 :     address = spec_edge->GetIp4Address();
     522             :     uint32_t first_label, last_label;
     523        6378 :     spec_edge->GetLabels(&first_label, &last_label);
     524        6378 :     label_block = new LabelBlock(first_label, last_label);
     525        6378 : }
     526             : 
     527       55261 : bool EdgeDiscovery::Edge::operator<(const Edge &rhs) const {
     528       55261 :     BOOL_KEY_COMPARE(address, rhs.address);
     529       47954 :     BOOL_KEY_COMPARE(label_block->first(), rhs.label_block->first());
     530       42466 :     BOOL_KEY_COMPARE(label_block->last(), rhs.label_block->last());
     531       42463 :     return false;
     532             : }
     533             : 
     534        3155 : EdgeDiscovery::EdgeDiscovery(EdgeDiscoveryDB *edge_discovery_db,
     535        3155 :     const EdgeDiscoverySpec &edspec)
     536        3155 :     : edge_discovery_db_(edge_discovery_db),
     537        3155 :       edspec_(edspec) {
     538        3153 :     refcount_ = 0;
     539        3149 :     for (EdgeDiscoverySpec::EdgeList::const_iterator it =
     540        9527 :          edspec_.edge_list.begin(); it != edspec_.edge_list.end(); ++it) {
     541        6378 :         Edge *edge = new Edge(*it);
     542        6378 :         edge_list.push_back(edge);
     543             :     }
     544        3149 :     sort(edge_list.begin(), edge_list.end(), EdgeDiscovery::EdgeCompare());
     545        3150 : }
     546             : 
     547        5286 : EdgeDiscovery::~EdgeDiscovery() {
     548        3155 :     STLDeleteValues(&edge_list);
     549        5286 : }
     550             : 
     551             : struct EdgeDiscoveryEdgeCompare {
     552       21882 :     int operator()(const EdgeDiscovery::Edge *lhs,
     553             :                    const EdgeDiscovery::Edge *rhs) const {
     554       21882 :         KEY_COMPARE(*lhs, *rhs);
     555       12772 :         return 0;
     556             :     }
     557             : };
     558             : 
     559      510558 : int EdgeDiscovery::CompareTo(const EdgeDiscovery &rhs) const {
     560      510558 :     int result = STLSortedCompare(edge_list.begin(), edge_list.end(),
     561             :                                   rhs.edge_list.begin(), rhs.edge_list.end(),
     562             :                                   EdgeDiscoveryEdgeCompare());
     563      510558 :     return result;
     564             : }
     565             : 
     566        1845 : void EdgeDiscovery::Remove() {
     567        1845 :     edge_discovery_db_->Delete(this);
     568        1845 : }
     569             : 
     570        9742 : EdgeDiscoveryDB::EdgeDiscoveryDB(BgpServer *server) {
     571        9742 : }
     572             : 
     573        6389 : EdgeForwardingSpec::EdgeForwardingSpec()
     574        6389 :     : BgpAttribute(McastEdgeForwarding, kFlags) {
     575        6389 : }
     576             : 
     577        4642 : EdgeForwardingSpec::EdgeForwardingSpec(const BgpAttribute &rhs)
     578        4642 :     : BgpAttribute(rhs) {
     579        4642 : }
     580             : 
     581        6276 : EdgeForwardingSpec::EdgeForwardingSpec(const EdgeForwardingSpec &rhs)
     582        6276 :     : BgpAttribute(BgpAttribute::McastEdgeForwarding, kFlags) {
     583       11530 :     for (size_t i = 0; i < rhs.edge_list.size(); i++) {
     584        5253 :         Edge *edge = new Edge;
     585        5253 :         *edge = *rhs.edge_list[i];
     586        5253 :         edge_list.push_back(edge);
     587             :     }
     588        6277 : }
     589             : 
     590       27720 : EdgeForwardingSpec:: ~EdgeForwardingSpec() {
     591       17305 :     STLDeleteValues(&edge_list);
     592       27705 : }
     593             : 
     594        5618 : Ip4Address EdgeForwardingSpec::Edge::GetInboundIp4Address() const {
     595        5618 :     return Ip4Address(get_value(&inbound_address[0], 4));
     596             : }
     597             : 
     598        5618 : Ip4Address EdgeForwardingSpec::Edge::GetOutboundIp4Address() const {
     599        5618 :     return Ip4Address(get_value(&outbound_address[0], 4));
     600             : }
     601             : 
     602      126203 : void EdgeForwardingSpec::Edge::SetInboundIp4Address(Ip4Address addr) {
     603      126203 :     inbound_address.resize(4, 0);
     604      126203 :     const Ip4Address::bytes_type &addr_bytes = addr.to_bytes();
     605      126203 :     std::copy(addr_bytes.begin(), addr_bytes.begin() + 4,
     606             :         inbound_address.begin());
     607      126203 : }
     608             : 
     609      126203 : void EdgeForwardingSpec::Edge::SetOutboundIp4Address(Ip4Address addr) {
     610      126203 :     outbound_address.resize(4, 0);
     611      126203 :     const Ip4Address::bytes_type &addr_bytes = addr.to_bytes();
     612      126203 :     std::copy(addr_bytes.begin(), addr_bytes.begin() + 4,
     613             :         outbound_address.begin());
     614      126203 : }
     615             : 
     616             : struct EdgeForwardingSpecEdgeCompare {
     617       59919 :     int operator()(const EdgeForwardingSpec::Edge *lhs,
     618             :                    const EdgeForwardingSpec::Edge *rhs) const {
     619       59919 :         KEY_COMPARE(lhs->inbound_address, rhs->inbound_address);
     620       59919 :         KEY_COMPARE(lhs->outbound_address, rhs->outbound_address);
     621       59919 :         KEY_COMPARE(lhs->inbound_label, rhs->inbound_label);
     622       59919 :         KEY_COMPARE(lhs->outbound_label, rhs->outbound_label);
     623       59919 :         return 0;
     624             :     }
     625             : };
     626             : 
     627        1898 : int EdgeForwardingSpec::CompareTo(const BgpAttribute &rhs_attr) const {
     628        1898 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     629        1898 :     if (ret != 0) return ret;
     630        1898 :     const EdgeForwardingSpec &rhs =
     631             :             static_cast<const EdgeForwardingSpec &>(rhs_attr);
     632        1898 :     ret = STLSortedCompare(edge_list.begin(), edge_list.end(),
     633             :                            rhs.edge_list.begin(), rhs.edge_list.end(),
     634             :                            EdgeForwardingSpecEdgeCompare());
     635        1898 :     return ret;
     636             : }
     637             : 
     638        3453 : void EdgeForwardingSpec::ToCanonical(BgpAttr *attr) {
     639        3453 :     attr->set_edge_forwarding(this);
     640        3453 : }
     641             : 
     642        2091 : string EdgeForwardingSpec::ToString() const {
     643        2091 :     std::ostringstream oss;
     644        2091 :     oss << "EdgeForwarding <code: " << int(code);
     645        2091 :     oss << ", flags: 0x" << std::hex << int(flags) << std::dec << ">";
     646        2091 :     int idx = 0;
     647        2091 :     for (EdgeList::const_iterator it = edge_list.begin();
     648        4379 :          it != edge_list.end(); ++it, ++idx) {
     649        2288 :         const Edge *edge = *it;
     650        2288 :         oss << " Edge[" << idx << "] = (";
     651        2288 :         oss << "InAddress=" << edge->GetInboundIp4Address() << ", ";
     652        2288 :         oss << "InLabel=" << edge->inbound_label << ", ";
     653        2288 :         oss << "OutAddress=" << edge->GetOutboundIp4Address() << ", ";
     654        2288 :         oss << "OutLabel=" << edge->outbound_label << ")";
     655             :     }
     656             : 
     657        4182 :     return oss.str();
     658        2091 : }
     659             : 
     660       16216 : size_t EdgeForwardingSpec::EncodeLength() const {
     661       16216 :     size_t sz = 0;
     662       16216 :     for (EdgeList::const_iterator iter = edge_list.begin();
     663      271389 :          iter != edge_list.end(); ++iter) {
     664      255173 :         sz += 1 /* address len */ + 8 /* 2 labels */;
     665      255173 :         sz += (*iter)->inbound_address.size();
     666      255173 :         sz += (*iter)->outbound_address.size();
     667             :     }
     668             : 
     669       16216 :     return sz;
     670             : }
     671             : 
     672        3326 : EdgeForwarding::Edge::Edge(const EdgeForwardingSpec::Edge *spec_edge) {
     673        3326 :     inbound_address = spec_edge->GetInboundIp4Address();
     674        3326 :     outbound_address = spec_edge->GetOutboundIp4Address();
     675        3326 :     inbound_label = spec_edge->inbound_label;
     676        3326 :     outbound_label = spec_edge->outbound_label;
     677        3326 : }
     678             : 
     679       33764 : bool EdgeForwarding::Edge::operator<(const Edge &rhs) const {
     680       33764 :     BOOL_KEY_COMPARE(inbound_address, rhs.inbound_address);
     681       23640 :     BOOL_KEY_COMPARE(outbound_address, rhs.outbound_address);
     682       18904 :     BOOL_KEY_COMPARE(inbound_label, rhs.inbound_label);
     683       16603 :     BOOL_KEY_COMPARE(outbound_label, rhs.outbound_label);
     684       14178 :     return false;
     685             : }
     686             : 
     687        4488 : EdgeForwarding::EdgeForwarding(EdgeForwardingDB *edge_forwarding_db,
     688        4488 :     const EdgeForwardingSpec &efspec)
     689        4486 :     : edge_forwarding_db_(edge_forwarding_db),
     690        4488 :       efspec_(efspec) {
     691        4487 :     refcount_ = 0;
     692        4488 :     for (EdgeForwardingSpec::EdgeList::const_iterator it =
     693        7814 :          efspec_.edge_list.begin(); it != efspec_.edge_list.end(); ++it) {
     694        3326 :         Edge *edge = new Edge(*it);
     695        3326 :         edge_list.push_back(edge);
     696             :     }
     697        4488 :     sort(edge_list.begin(), edge_list.end(), EdgeForwarding::EdgeCompare());
     698        4486 : }
     699             : 
     700        7954 : EdgeForwarding::~EdgeForwarding() {
     701        4489 :     STLDeleteValues(&edge_list);
     702        7954 : }
     703             : 
     704             : struct EdgeForwardingEdgeCompare {
     705       19234 :     int operator()(const EdgeForwarding::Edge *lhs,
     706             :                    const EdgeForwarding::Edge *rhs) const {
     707       19234 :         KEY_COMPARE(*lhs, *rhs);
     708        7089 :         return 0;
     709             :     }
     710             : };
     711             : 
     712      612376 : int EdgeForwarding::CompareTo(const EdgeForwarding &rhs) const {
     713      612376 :     int result = STLSortedCompare(edge_list.begin(), edge_list.end(),
     714             :                                   rhs.edge_list.begin(), rhs.edge_list.end(),
     715             :                                   EdgeForwardingEdgeCompare());
     716      612376 :     return result;
     717             : }
     718             : 
     719        2364 : void EdgeForwarding::Remove() {
     720        2364 :     edge_forwarding_db_->Delete(this);
     721        2364 : }
     722             : 
     723        9742 : EdgeForwardingDB::EdgeForwardingDB(BgpServer *server) {
     724        9742 : }
     725             : 
     726      202962 : bool BgpOListElem::operator<(const BgpOListElem &rhs) const {
     727      202962 :     BOOL_KEY_COMPARE(address, rhs.address);
     728      133418 :     BOOL_KEY_COMPARE(label, rhs.label);
     729      129251 :     BOOL_KEY_COMPARE(encap, rhs.encap);
     730      129242 :     return false;
     731             : }
     732             : 
     733           3 : int BgpOListSpec::CompareTo(const BgpAttribute &rhs_attr) const {
     734           3 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     735           3 :     if (ret != 0) return ret;
     736           3 :     return 0;
     737             : }
     738             : 
     739        3570 : void BgpOListSpec::ToCanonical(BgpAttr *attr) {
     740        3570 :     if (subcode == BgpAttribute::OList) {
     741        3570 :         attr->set_olist(this);
     742           0 :     } else if (subcode == BgpAttribute::LeafOList) {
     743           0 :         attr->set_leaf_olist(this);
     744             :     } else {
     745           0 :         assert(false);
     746             :     }
     747        3570 : }
     748             : 
     749           1 : string BgpOListSpec::ToString() const {
     750           1 :     std::ostringstream oss;
     751           1 :     oss << "OList <subcode: " << int(subcode) << ">";
     752           1 :     int idx = 0;
     753           1 :     for (Elements::const_iterator it = elements.begin();
     754           3 :          it != elements.end(); ++it, ++idx) {
     755           2 :         BgpOListElem elem(*it);
     756           2 :         oss << "OList[" << idx << "] = (";
     757           2 :         oss << "address: " << elem.address << ", ";
     758           2 :         oss << "label: " << elem.label << ", ";
     759           2 :         oss << "encap-list:";
     760           2 :         int eid = 0;
     761           2 :         for (vector<string>::const_iterator e_it = elem.encap.begin();
     762           6 :              e_it != elem.encap.end(); ++e_it, ++eid) {
     763           4 :              oss << " " << *e_it;
     764             :         }
     765           2 :         oss << ")";
     766           2 :     }
     767           2 :     return (oss.str());
     768           1 : }
     769             : 
     770       14123 : BgpOList::BgpOList(BgpOListDB *olist_db, const BgpOListSpec &olist_spec)
     771       14123 :     : olist_db_(olist_db),
     772       14123 :       olist_spec_(olist_spec) {
     773       14123 :     refcount_ = 0;
     774       14122 :     for (BgpOListSpec::Elements::const_iterator it =
     775       37363 :          olist_spec_.elements.begin(); it != olist_spec_.elements.end(); ++it) {
     776       23240 :         BgpOListElem *elem = new BgpOListElem(*it);
     777       23240 :         sort(elem->encap.begin(), elem->encap.end());
     778       23240 :         elements_.push_back(elem);
     779             :     }
     780       14120 :     sort(elements_.begin(), elements_.end(), BgpOListElemCompare());
     781       14118 : }
     782             : 
     783       27222 : BgpOList::~BgpOList() {
     784       14123 :     STLDeleteValues(&elements_);
     785       27222 : }
     786             : 
     787             : struct BgpOListElementCompare {
     788       79529 :     int operator()(const BgpOListElem *lhs, const BgpOListElem *rhs) const {
     789       79529 :         KEY_COMPARE(*lhs, *rhs);
     790       64621 :         return 0;
     791             :     }
     792             : };
     793             : 
     794      423745 : int BgpOList::CompareTo(const BgpOList &rhs) const {
     795      423745 :     KEY_COMPARE(olist().subcode, rhs.olist().subcode);
     796      817456 :     int result = STLSortedCompare(elements().begin(), elements().end(),
     797      817456 :                                   rhs.elements().begin(), rhs.elements().end(),
     798             :                                   BgpOListElementCompare());
     799      408728 :     return result;
     800             : }
     801             : 
     802        9722 : void BgpOList::Remove() {
     803        9722 :     olist_db_->Delete(this);
     804        9722 : }
     805             : 
     806        9742 : BgpOListDB::BgpOListDB(BgpServer *server) {
     807        9742 : }
     808             : 
     809           0 : int BgpAttrLabelBlock::CompareTo(const BgpAttribute &rhs_attr) const {
     810           0 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     811           0 :     if (ret != 0) return ret;
     812           0 :     KEY_COMPARE(label_block.get(),
     813             :             static_cast<const BgpAttrLabelBlock &>(rhs_attr).label_block.get());
     814           0 :     return 0;
     815             : }
     816             : 
     817        1033 : void BgpAttrLabelBlock::ToCanonical(BgpAttr *attr) {
     818        1033 :     attr->set_label_block(label_block);
     819        1033 : }
     820             : 
     821           0 : string BgpAttrLabelBlock::ToString() const {
     822             :     char repr[80];
     823           0 :     snprintf(repr, sizeof(repr), "LabelBlock <subcode: %d> : %d-%d",
     824           0 :              subcode, label_block->first(), label_block->last());
     825           0 :     return string(repr);
     826             : }
     827             : 
     828           3 : int BgpAttrSourceRd::CompareTo(const BgpAttribute &rhs_attr) const {
     829           3 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     830           3 :     if (ret != 0) return ret;
     831           3 :     KEY_COMPARE(source_rd,
     832             :             static_cast<const BgpAttrSourceRd &>(rhs_attr).source_rd);
     833           1 :     return 0;
     834             : }
     835             : 
     836       28637 : void BgpAttrSourceRd::ToCanonical(BgpAttr *attr) {
     837       28637 :     attr->set_source_rd(source_rd);
     838       28637 : }
     839             : 
     840           1 : string BgpAttrSourceRd::ToString() const {
     841             :     char repr[80];
     842           1 :     snprintf(repr, sizeof(repr), "SourceRd <subcode: %d> : %s",
     843           2 :              subcode, source_rd.ToString().c_str());
     844           1 :     return string(repr);
     845             : }
     846             : 
     847           3 : int BgpAttrEsi::CompareTo(const BgpAttribute &rhs_attr) const {
     848           3 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     849           3 :     if (ret != 0) return ret;
     850           3 :     KEY_COMPARE(esi, static_cast<const BgpAttrEsi &>(rhs_attr).esi);
     851           1 :     return 0;
     852             : }
     853             : 
     854          59 : void BgpAttrEsi::ToCanonical(BgpAttr *attr) {
     855          59 :     attr->set_esi(esi);
     856          59 : }
     857             : 
     858           1 : string BgpAttrEsi::ToString() const {
     859             :     char repr[80];
     860           1 :     snprintf(repr, sizeof(repr), "Esi <subcode: %d> : %s",
     861           2 :              subcode, esi.ToString().c_str());
     862           1 :     return string(repr);
     863             : }
     864             : 
     865           3 : int BgpAttrParams::CompareTo(const BgpAttribute &rhs_attr) const {
     866           3 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     867           3 :     if (ret != 0) return ret;
     868           3 :     KEY_COMPARE(params, static_cast<const BgpAttrParams &>(rhs_attr).params);
     869           1 :     return 0;
     870             : }
     871             : 
     872           3 : void BgpAttrParams::ToCanonical(BgpAttr *attr) {
     873           3 :     attr->set_params(params);
     874           3 : }
     875             : 
     876           1 : string BgpAttrParams::ToString() const {
     877             :     char repr[80];
     878           1 :     snprintf(repr, sizeof(repr), "Params <subcode: %d> : 0x%016jx",
     879           1 :              subcode, params);
     880           1 :     return string(repr);
     881             : }
     882             : 
     883           3 : int BgpAttrSubProtocol::CompareTo(const BgpAttribute &rhs_attr) const {
     884           3 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     885           3 :     if (ret != 0) return ret;
     886           3 :     KEY_COMPARE(sbp, static_cast<const BgpAttrSubProtocol &>(rhs_attr).sbp);
     887           1 :     return 0;
     888             : }
     889             : 
     890       21985 : void BgpAttrSubProtocol::ToCanonical(BgpAttr *attr) {
     891       21985 :     attr->set_sub_protocol(sbp);
     892       21985 : }
     893             : 
     894           1 : string BgpAttrSubProtocol::ToString() const {
     895             :     char repr[80];
     896           1 :     snprintf(repr, sizeof(repr), "SubProtocol <subcode: %d> : %s",
     897           1 :              subcode, sbp.c_str());
     898           1 :     return string(repr);
     899             : }
     900             : 
     901          38 : BgpAttr::BgpAttr()
     902          38 :     : attr_db_(NULL), origin_(BgpAttrOrigin::INCOMPLETE), nexthop_(),
     903          38 :       med_(0), local_pref_(0), atomic_aggregate_(false),
     904          38 :       aggregator_as_num_(0), aggregator_as4_num_(0), params_(0) {
     905          38 :     refcount_ = 0;
     906          38 : }
     907             : 
     908        5953 : BgpAttr::BgpAttr(BgpAttrDB *attr_db)
     909        5953 :     : attr_db_(attr_db), origin_(BgpAttrOrigin::INCOMPLETE),
     910       11906 :       nexthop_(), med_(0), local_pref_(0), atomic_aggregate_(false),
     911        5953 :       aggregator_as_num_(0), aggregator_as4_num_(0), params_(0) {
     912        5953 :     refcount_ = 0;
     913        5953 : }
     914             : 
     915      388622 : BgpAttr::BgpAttr(BgpAttrDB *attr_db, const BgpAttrSpec &spec)
     916      388622 :     : attr_db_(attr_db), origin_(BgpAttrOrigin::INCOMPLETE),
     917      777241 :       nexthop_(), med_(0),
     918      388619 :       local_pref_(BgpAttrLocalPref::kDefault),
     919      388619 :       atomic_aggregate_(false),
     920      388619 :       aggregator_as_num_(0), aggregator_as4_num_(0), 
     921      388622 :       aggregator_address_(), params_(0) {
     922      388612 :     refcount_ = 0;
     923      388624 :     for (vector<BgpAttribute *>::const_iterator it = spec.begin();
     924     1464850 :          it < spec.end(); it++) {
     925     1076218 :         (*it)->ToCanonical(this);
     926             :     }
     927      388607 : }
     928             : 
     929     3013568 : BgpAttr::BgpAttr(const BgpAttr &rhs)
     930     3013568 :     : attr_db_(rhs.attr_db_), origin_(rhs.origin_), nexthop_(rhs.nexthop_),
     931     3013145 :       med_(rhs.med_), local_pref_(rhs.local_pref_),
     932     3013145 :       atomic_aggregate_(rhs.atomic_aggregate_),
     933     3013145 :       aggregator_as_num_(rhs.aggregator_as_num_),
     934     3013145 :       aggregator_as4_num_(rhs.aggregator_as4_num_),
     935     3013145 :       aggregator_address_(rhs.aggregator_address_),
     936     3012952 :       originator_id_(rhs.originator_id_),
     937     3012900 :       source_rd_(rhs.source_rd_), esi_(rhs.esi_), params_(rhs.params_),
     938     3012617 :       as_path_(rhs.as_path_),
     939     3013470 :       aspath_4byte_(rhs.aspath_4byte_),
     940     3013385 :       as4_path_(rhs.as4_path_),
     941     3013230 :       cluster_list_(rhs.cluster_list_),
     942     3013115 :       community_(rhs.community_),
     943     3013082 :       ext_community_(rhs.ext_community_),
     944     3014019 :       large_community_(rhs.large_community_),
     945     3013576 :       deferred_large_spec_(nullptr),
     946     3012959 :       origin_vn_path_(rhs.origin_vn_path_),
     947     3012898 :       pmsi_tunnel_(rhs.pmsi_tunnel_),
     948     3012778 :       edge_discovery_(rhs.edge_discovery_),
     949     3012647 :       edge_forwarding_(rhs.edge_forwarding_),
     950     3012558 :       label_block_(rhs.label_block_),
     951     3012488 :       olist_(rhs.olist_),
     952     3012384 :       leaf_olist_(rhs.leaf_olist_),
     953     6025837 :       sub_protocol_(rhs.sub_protocol_) {
     954     3012052 :     refcount_ = 0;
     955     3014137 : }
     956             : 
     957       19181 : void BgpAttr::set_as_path(AsPathPtr aspath) {
     958       19181 :     as_path_ = aspath;
     959       19181 : }
     960             : 
     961      360412 : void BgpAttr::set_as_path(const AsPathSpec *spec) {
     962      360412 :     if (spec) {
     963      360313 :         as_path_ = attr_db_->server()->aspath_db()->Locate(*spec);
     964             :     } else {
     965          99 :         as_path_ = NULL;
     966             :     }
     967      360513 : }
     968             : 
     969           0 : void BgpAttr::set_as4_path(As4PathPtr aspath) {
     970           0 :     as4_path_ = aspath;
     971           0 : }
     972             : 
     973         494 : void BgpAttr::set_as4_path(const As4PathSpec *spec) {
     974         494 :     if (spec) {
     975         460 :         as4_path_ = attr_db_->server()->as4path_db()->Locate(*spec);
     976             :     } else {
     977          34 :         as4_path_ = NULL;
     978             :     }
     979         494 : }
     980             : 
     981           0 : void BgpAttr::set_aspath_4byte(AsPath4BytePtr aspath) {
     982           0 :     aspath_4byte_ = aspath;
     983           0 : }
     984             : 
     985         554 : void BgpAttr::set_aspath_4byte(const AsPath4ByteSpec *spec) {
     986         554 :     if (spec) {
     987         493 :         aspath_4byte_ = attr_db_->server()->aspath_4byte_db()->Locate(*spec);
     988             :     } else {
     989          61 :         aspath_4byte_ = NULL;
     990             :     }
     991         554 : }
     992             : 
     993      202150 : void BgpAttr::set_cluster_list(const ClusterListSpec *spec) {
     994      202150 :     if (spec) {
     995          18 :         cluster_list_ = attr_db_->server()->cluster_list_db()->Locate(*spec);
     996             :     } else {
     997      202132 :         cluster_list_ = NULL;
     998             :     }
     999      202153 : }
    1000             : 
    1001       24467 : void BgpAttr::set_community(CommunityPtr comm) {
    1002       24467 :     community_ = comm;
    1003       24467 : }
    1004             : 
    1005        4315 : void BgpAttr::set_community(const CommunitySpec *comm) {
    1006        4315 :     if (comm) {
    1007        4315 :         community_ = attr_db_->server()->comm_db()->Locate(*comm);
    1008             :     } else {
    1009           0 :         community_ = NULL;
    1010             :     }
    1011        4315 : }
    1012             : 
    1013     1001784 : void BgpAttr::set_ext_community(ExtCommunityPtr extcomm) {
    1014     1001784 :     ext_community_ = extcomm;
    1015     1001821 : }
    1016             : 
    1017      183342 : void BgpAttr::set_ext_community(const ExtCommunitySpec *extcomm) {
    1018      183342 :     if (extcomm) {
    1019      183342 :         LargeCommunitySpec large_spec = LargeCommunitySpec::FromTag(*extcomm);
    1020      183340 :         set_large_community(&large_spec);
    1021             :         
    1022      183342 :         if (large_spec.communities.size()) {
    1023             :             ExtCommunitySpec new_comms =
    1024           4 :                 LargeCommunitySpec::RemoveTags(*extcomm);
    1025             :             ext_community_ =
    1026           4 :                 attr_db_->server()->extcomm_db()->Locate(new_comms);
    1027           4 :             return;
    1028           4 :         }
    1029      183338 :         ext_community_ = attr_db_->server()->extcomm_db()->Locate(*extcomm);
    1030      183342 :     } else {
    1031           0 :         ext_community_ = NULL;
    1032             :     }
    1033             : }
    1034             : 
    1035       18877 : void BgpAttr::set_large_community(LargeCommunityPtr largecomm) {
    1036       18877 :     large_community_ = largecomm;
    1037       18877 : }
    1038             : 
    1039      183384 : void BgpAttr::set_large_community(const LargeCommunitySpec *largecomm) {
    1040      183384 :     if (largecomm) {
    1041      183384 :         if (!bool(deferred_large_spec_)) {
    1042      183341 :             deferred_large_spec_.reset(new LargeCommunitySpec);
    1043      183338 :             deferred_large_spec_->communities = largecomm->communities;
    1044             :         } else {
    1045          88 :             deferred_large_spec_->communities.insert(
    1046          88 :                 deferred_large_spec_->communities.end(),
    1047             :                 largecomm->communities.begin(),
    1048             :                 largecomm->communities.end());
    1049             :         }
    1050             :         large_community_ =
    1051      183382 :             attr_db_->server()->largecomm_db()->Locate(*deferred_large_spec_);
    1052             :     } else {
    1053           0 :         large_community_ = NULL;
    1054             :     }
    1055      183386 : }
    1056             : 
    1057       18878 : void BgpAttr::set_origin_vn_path(OriginVnPathPtr ovnpath) {
    1058       18878 :     origin_vn_path_ = ovnpath;
    1059       18878 : }
    1060             : 
    1061         718 : void BgpAttr::set_origin_vn_path(const OriginVnPathSpec *spec) {
    1062         718 :     if (spec) {
    1063         718 :         origin_vn_path_ = attr_db_->server()->ovnpath_db()->Locate(*spec);
    1064             :     } else {
    1065           0 :         origin_vn_path_ = NULL;
    1066             :     }
    1067         718 : }
    1068             : 
    1069       16891 : void BgpAttr::set_pmsi_tunnel(const PmsiTunnelSpec *pmsi_spec) {
    1070       16891 :     if (pmsi_spec) {
    1071       16891 :         pmsi_tunnel_ = attr_db_->server()->pmsi_tunnel_db()->Locate(*pmsi_spec);
    1072             :     } else {
    1073           0 :         pmsi_tunnel_ = NULL;
    1074             :     }
    1075       16891 : }
    1076             : 
    1077        2121 : void BgpAttr::set_edge_discovery(const EdgeDiscoverySpec *edspec) {
    1078        2121 :     if (edspec) {
    1079             :         edge_discovery_ =
    1080        2121 :             attr_db_->server()->edge_discovery_db()->Locate(*edspec);
    1081             :     } else {
    1082           0 :         edge_discovery_ = NULL;
    1083             :     }
    1084        2121 : }
    1085             : 
    1086        3455 : void BgpAttr::set_edge_forwarding(const EdgeForwardingSpec *efspec) {
    1087        3455 :     if (efspec) {
    1088             :         edge_forwarding_ =
    1089        3455 :             attr_db_->server()->edge_forwarding_db()->Locate(*efspec);
    1090             :     } else {
    1091           0 :         edge_forwarding_ = NULL;
    1092             :     }
    1093        3455 : }
    1094             : 
    1095        1034 : void BgpAttr::set_label_block(LabelBlockPtr label_block) {
    1096        1034 :     label_block_ = label_block;
    1097        1034 : }
    1098             : 
    1099        8402 : void BgpAttr::set_olist(const BgpOListSpec *olist_spec) {
    1100        8402 :     if (olist_spec) {
    1101        8402 :         olist_ = attr_db_->server()->olist_db()->Locate(*olist_spec);
    1102             :     } else {
    1103           0 :         olist_ = NULL;
    1104             :     }
    1105        8402 : }
    1106             : 
    1107        4677 : void BgpAttr::set_leaf_olist(const BgpOListSpec *leaf_olist_spec) {
    1108        4677 :     if (leaf_olist_spec) {
    1109        4677 :         leaf_olist_ = attr_db_->server()->olist_db()->Locate(*leaf_olist_spec);
    1110             :     } else {
    1111           0 :         leaf_olist_ = NULL;
    1112             :     }
    1113        4677 : }
    1114             : 
    1115     9325270 : int BgpAttr::max_as_path_count() const {
    1116     9325270 :     int as_count = as_path_count();
    1117     9325248 :     int as4_count = aspath_4byte_count();
    1118     9325231 :     return as_count > as4_count ? as_count : as4_count;
    1119             : }
    1120             : 
    1121       98875 : bool BgpAttr::IsAsPathEmpty() const {
    1122       98875 :     if (as_path_ && !as_path_->empty())
    1123         332 :         return false;
    1124       98543 :     if (aspath_4byte_ && !aspath_4byte_->empty())
    1125          86 :         return false;
    1126       98457 :     return true;
    1127             : }
    1128             : 
    1129        5605 : string BgpAttr::OriginToString(BgpAttrOrigin::OriginType origin) {
    1130        5605 :     switch (origin) {
    1131        5251 :     case BgpAttrOrigin::IGP:
    1132        5251 :         return "igp";
    1133             :         break;
    1134           3 :     case BgpAttrOrigin::EGP:
    1135           3 :         return "egp";
    1136             :         break;
    1137         351 :     case BgpAttrOrigin::INCOMPLETE:
    1138         351 :         return "incomplete";
    1139             :         break;
    1140             :     }
    1141           0 :     return "unknown";
    1142             : }
    1143             : 
    1144       20423 : BgpAttrOrigin::OriginType BgpAttr::OriginFromString(
    1145             :         const string &bgp_origin_type) {
    1146       20423 :     if(bgp_origin_type ==  "IGP"){
    1147       20420 :         return BgpAttrOrigin::IGP;
    1148           3 :     } else if( bgp_origin_type ==  "EGP") {
    1149           2 :         return BgpAttrOrigin::EGP;
    1150             :     }
    1151           1 :     return BgpAttrOrigin::INCOMPLETE;
    1152             : }
    1153             : 
    1154        5601 : string BgpAttr::origin_string() const {
    1155        5601 :     return OriginToString(origin());
    1156             : }
    1157             : 
    1158        2887 : Address::Family BgpAttr::nexthop_family() const {
    1159        2887 :     if (nexthop_.is_v6()) {
    1160         325 :         return Address::INET6;
    1161             :     } else {
    1162        2562 :         return Address::INET;
    1163             :     }
    1164             : }
    1165             : 
    1166     2646275 : as_t BgpAttr::neighbor_as() const {
    1167     2646275 :     if (as_path_.get())
    1168      485299 :         return as_path_->neighbor_as();
    1169     2160976 :     if (aspath_4byte_.get())
    1170         225 :         return aspath_4byte_->neighbor_as();
    1171     2160759 :     return 0;
    1172             : }
    1173             : 
    1174     9417345 : uint32_t BgpAttr::sequence_number() const {
    1175     9417345 :     if (!ext_community_)
    1176     1136440 :         return 0;
    1177     8280919 :     for (ExtCommunity::ExtCommunityList::const_iterator it =
    1178     8280933 :          ext_community_->communities().begin();
    1179    28896775 :          it != ext_community_->communities().end(); ++it) {
    1180    20620036 :         if (ExtCommunity::is_mac_mobility(*it)) {
    1181        4321 :             MacMobility mm(*it);
    1182        4321 :             return mm.sequence_number();
    1183             :         }
    1184             :     }
    1185     8276506 :     return 0;
    1186             : }
    1187             : 
    1188     4708734 : bool BgpAttr::evpn_sticky_mac() const {
    1189     4708734 :     if (!ext_community_)
    1190      568220 :         return 0;
    1191     4140507 :     for (ExtCommunity::ExtCommunityList::const_iterator it =
    1192     4140532 :          ext_community_->communities().begin();
    1193    14449114 :          it != ext_community_->communities().end(); ++it) {
    1194    10310730 :         if (ExtCommunity::is_mac_mobility(*it)) {
    1195        2180 :             MacMobility mm(*it);
    1196        2180 :             return mm.sticky();
    1197             :         }
    1198             :     }
    1199     4138317 :     return 0;
    1200             : }
    1201             : 
    1202     4708812 : bool BgpAttr::etree_leaf() const {
    1203     4708812 :     if (!ext_community_)
    1204      568220 :         return 0;
    1205     4140568 :     for (ExtCommunity::ExtCommunityList::const_iterator it =
    1206     4140582 :          ext_community_->communities().begin();
    1207    14304612 :          it != ext_community_->communities().end(); ++it) {
    1208    10237186 :         if (ExtCommunity::is_etree(*it)) {
    1209       73160 :             ETree etree(*it);
    1210       73164 :             return etree.leaf();
    1211             :         }
    1212             :     }
    1213     4067350 :     return 0;
    1214             : }
    1215             : 
    1216          60 : bool BgpAttr::evpn_single_active() const {
    1217          60 :     if (!ext_community_)
    1218           0 :         return false;
    1219          60 :     for (ExtCommunity::ExtCommunityList::const_iterator it =
    1220          60 :          ext_community_->communities().begin();
    1221         120 :          it != ext_community_->communities().end(); ++it) {
    1222         120 :         if (ExtCommunity::is_esi_label(*it)) {
    1223          60 :             EsiLabel esi_label(*it);
    1224          60 :             return esi_label.single_active();
    1225             :         }
    1226             :     }
    1227           0 :     return true;
    1228             : }
    1229             : 
    1230      462906 : MacAddress BgpAttr::mac_address() const {
    1231      462906 :     if (!ext_community_)
    1232       13679 :         return MacAddress::kZeroMac;
    1233      449198 :     for (ExtCommunity::ExtCommunityList::const_iterator it =
    1234      449221 :          ext_community_->communities().begin();
    1235     3173975 :          it != ext_community_->communities().end(); ++it) {
    1236     2724800 :         if (ExtCommunity::is_router_mac(*it)) {
    1237          22 :             RouterMac router_mac(*it);
    1238          22 :             return router_mac.mac_address();
    1239             :         }
    1240             :     }
    1241      449069 :     return MacAddress::kZeroMac;
    1242             : }
    1243             : 
    1244      438894 : void BgpAttr::Remove() {
    1245      438894 :     attr_db_->Delete(this);
    1246      438899 : }
    1247             : 
    1248      448352 : int BgpAttr::IsAsPathLoop(as_t asn, uint8_t max_loop_count) const {
    1249      448352 :     if (as_path() && as_path()->path().AsPathLoop(asn, max_loop_count)) {
    1250      135151 :         return true;
    1251             :     }
    1252      313416 :     if (aspath_4byte() &&
    1253         196 :            aspath_4byte()->path().AsPathLoop(asn, max_loop_count)) {
    1254          51 :         return true;
    1255             :     }
    1256      313171 :     if (asn > AS2_MAX && as4_path() &&
    1257          20 :            as4_path()->path().AsPathLoop(asn, max_loop_count)) {
    1258           4 :         return true;
    1259             :     }
    1260      313147 :     return false;
    1261             : }
    1262             : 
    1263    25332249 : int BgpAttr::CompareTo(const BgpAttr &rhs) const {
    1264    25332249 :     KEY_COMPARE(origin_, rhs.origin_);
    1265    23582503 :     KEY_COMPARE(nexthop_, rhs.nexthop_);
    1266    15826558 :     KEY_COMPARE(med_, rhs.med_);
    1267    15052637 :     KEY_COMPARE(local_pref_, rhs.local_pref_);
    1268    14659204 :     KEY_COMPARE(atomic_aggregate_, rhs.atomic_aggregate_);
    1269    14659204 :     KEY_COMPARE(aggregator_as_num_, rhs.aggregator_as_num_);
    1270    14659012 :     KEY_COMPARE(aggregator_as4_num_, rhs.aggregator_as4_num_);
    1271    14658884 :     KEY_COMPARE(aggregator_address_, rhs.aggregator_address_);
    1272    14661826 :     KEY_COMPARE(originator_id_, rhs.originator_id_);
    1273    14660519 :     KEY_COMPARE(pmsi_tunnel_.get(), rhs.pmsi_tunnel_.get());
    1274    14304852 :     KEY_COMPARE(edge_discovery_.get(), rhs.edge_discovery_.get());
    1275    14242488 :     KEY_COMPARE(edge_forwarding_.get(), rhs.edge_forwarding_.get());
    1276    14178033 :     KEY_COMPARE(esi_, rhs.esi_);
    1277    14177910 :     KEY_COMPARE(params_, rhs.params_);
    1278    14177905 :     KEY_COMPARE(source_rd_, rhs.source_rd_);
    1279    10182362 :     KEY_COMPARE(label_block_.get(), rhs.label_block_.get());
    1280    10184273 :     KEY_COMPARE(olist_.get(), rhs.olist_.get());
    1281    10125215 :     KEY_COMPARE(leaf_olist_.get(), rhs.leaf_olist_.get());
    1282    10105170 :     KEY_COMPARE(as_path_.get(), rhs.as_path_.get());
    1283     9814655 :     KEY_COMPARE(aspath_4byte_.get(), rhs.aspath_4byte_.get());
    1284     9813525 :     KEY_COMPARE(as4_path_.get(), rhs.as4_path_.get());
    1285     9812611 :     KEY_COMPARE(cluster_list_.get(), rhs.cluster_list_.get());
    1286     9812508 :     KEY_COMPARE(community_.get(), rhs.community_.get());
    1287     9556807 :     KEY_COMPARE(ext_community_.get(), rhs.ext_community_.get());
    1288     7058494 :     KEY_COMPARE(large_community_.get(), rhs.large_community_.get());
    1289     7043829 :     KEY_COMPARE(origin_vn_path_.get(), rhs.origin_vn_path_.get());
    1290     6967893 :     KEY_COMPARE(sub_protocol_, rhs.sub_protocol_);
    1291     6951953 :     return 0;
    1292             : }
    1293             : 
    1294           0 : std::size_t hash_value(BgpAttr const &attr) {
    1295           0 :     size_t hash = 0;
    1296             : 
    1297           0 :     boost::hash_combine(hash, attr.origin_);
    1298           0 :     boost::hash_combine(hash, attr.nexthop_.to_string());
    1299           0 :     boost::hash_combine(hash, attr.med_);
    1300           0 :     boost::hash_combine(hash, attr.local_pref_);
    1301           0 :     boost::hash_combine(hash, attr.atomic_aggregate_);
    1302           0 :     boost::hash_combine(hash, attr.aggregator_as_num_);
    1303           0 :     boost::hash_combine(hash, attr.aggregator_as4_num_);
    1304           0 :     boost::hash_combine(hash, attr.aggregator_address_.to_string());
    1305           0 :     boost::hash_combine(hash, attr.originator_id_.to_string());
    1306           0 :     boost::hash_combine(hash, attr.params_);
    1307           0 :     boost::hash_combine(hash, attr.source_rd_.ToString());
    1308           0 :     boost::hash_combine(hash, attr.esi_.ToString());
    1309             : 
    1310           0 :     if (attr.label_block_) {
    1311           0 :         boost::hash_combine(hash, attr.label_block_->first());
    1312           0 :         boost::hash_combine(hash, attr.label_block_->last());
    1313             :     }
    1314             : 
    1315           0 :     if (attr.olist_) {
    1316           0 :         boost::hash_range(hash, attr.olist_->elements().begin(),
    1317           0 :                           attr.olist_->elements().end());
    1318             :     }
    1319           0 :     if (attr.leaf_olist_) {
    1320           0 :         boost::hash_range(hash, attr.leaf_olist_->elements().begin(),
    1321           0 :                           attr.leaf_olist_->elements().end());
    1322             :     }
    1323             : 
    1324           0 :     if (attr.as_path_) boost::hash_combine(hash, *attr.as_path_);
    1325           0 :     if (attr.aspath_4byte_) boost::hash_combine(hash, *attr.aspath_4byte_);
    1326           0 :     if (attr.as4_path_) boost::hash_combine(hash, *attr.as4_path_);
    1327           0 :     if (attr.community_) boost::hash_combine(hash, *attr.community_);
    1328           0 :     if (attr.ext_community_) boost::hash_combine(hash, *attr.ext_community_);
    1329           0 :     if (attr.large_community_) boost::hash_combine(hash, *attr.large_community_);
    1330           0 :     if (attr.origin_vn_path_) boost::hash_combine(hash, *attr.origin_vn_path_);
    1331           0 :     if (!attr.sub_protocol_.empty()) {
    1332           0 :         boost::hash_combine(hash, attr.sub_protocol_);
    1333             :     }
    1334             : 
    1335           0 :     return hash;
    1336             : }
    1337             : 
    1338        9742 : BgpAttrDB::BgpAttrDB(BgpServer *server) : server_(server) {
    1339        9742 : }
    1340             : 
    1341             : // Return a clone of attribute with updated aspath.
    1342       19181 : BgpAttrPtr BgpAttrDB::ReplaceAsPathAndLocate(const BgpAttr *attr,
    1343             :                                              AsPathPtr aspath) {
    1344       19181 :     BgpAttr *clone = new BgpAttr(*attr);
    1345       19181 :     clone->set_as_path(aspath);
    1346       19181 :     return Locate(clone);
    1347             : }
    1348             : 
    1349             : // Return a clone of attribute with updated community.
    1350       19211 : BgpAttrPtr BgpAttrDB::ReplaceCommunityAndLocate(const BgpAttr *attr,
    1351             :                                                 CommunityPtr community) {
    1352       19211 :     BgpAttr *clone = new BgpAttr(*attr);
    1353       19211 :     clone->set_community(community);
    1354       19211 :     return Locate(clone);
    1355             : }
    1356             : 
    1357             : //Return a clone of attribute with updated origin
    1358           4 : BgpAttrPtr BgpAttrDB::ReplaceOriginAndLocate(const BgpAttr *attr,
    1359             :                                              BgpAttrOrigin::OriginType origin) {
    1360           4 :     BgpAttr *clone = new BgpAttr(*attr);
    1361           4 :     clone->set_origin(origin);
    1362           4 :     return Locate(clone);
    1363             : }
    1364             : 
    1365             : // Return a clone of attribute with updated extended community.
    1366     1001775 : BgpAttrPtr BgpAttrDB::ReplaceExtCommunityAndLocate(const BgpAttr *attr,
    1367             :                                                    ExtCommunityPtr extcomm) {
    1368     1001775 :     BgpAttr *clone = new BgpAttr(*attr);
    1369     1001810 :     clone->set_ext_community(extcomm);
    1370     1001803 :     return Locate(clone);
    1371             : }
    1372             : 
    1373             : // Return a clone of attribute with updated large community.
    1374       18877 : BgpAttrPtr BgpAttrDB::ReplaceLargeCommunityAndLocate(
    1375             :     const BgpAttr *attr, LargeCommunityPtr largecomm) {
    1376       18877 :     BgpAttr *clone = new BgpAttr(*attr);
    1377       18877 :     clone->set_large_community(largecomm);
    1378       18877 :     return Locate(clone);
    1379             : }
    1380             : 
    1381             : // Return a clone of attribute with updated origin vn path.
    1382       18878 : BgpAttrPtr BgpAttrDB::ReplaceOriginVnPathAndLocate(const BgpAttr *attr,
    1383             :                                                    OriginVnPathPtr ovnpath) {
    1384       18878 :     BgpAttr *clone = new BgpAttr(*attr);
    1385       18878 :     clone->set_origin_vn_path(ovnpath);
    1386       18878 :     return Locate(clone);
    1387             : }
    1388             : 
    1389             : // Return a clone of attribute with updated local preference.
    1390          18 : BgpAttrPtr BgpAttrDB::ReplaceLocalPreferenceAndLocate(const BgpAttr *attr,
    1391             :                                                       uint32_t local_pref) {
    1392          18 :     BgpAttr *clone = new BgpAttr(*attr);
    1393          18 :     clone->set_local_pref(local_pref);
    1394          18 :     return Locate(clone);
    1395             : }
    1396             : 
    1397             : // Return a clone of attribute with updated originator id.
    1398           1 : BgpAttrPtr BgpAttrDB::ReplaceOriginatorIdAndLocate(const BgpAttr *attr,
    1399             :                                                    Ip4Address originator_id) {
    1400           1 :     BgpAttr *clone = new BgpAttr(*attr);
    1401           1 :     clone->set_originator_id(originator_id);
    1402           1 :     return Locate(clone);
    1403             : }
    1404             : 
    1405             : // Return a clone of attribute with updated source rd.
    1406      600437 : BgpAttrPtr BgpAttrDB::ReplaceSourceRdAndLocate(const BgpAttr *attr,
    1407             :     const RouteDistinguisher &source_rd) {
    1408      600437 :     BgpAttr *clone = new BgpAttr(*attr);
    1409      600473 :     clone->set_source_rd(source_rd);
    1410      600458 :     return Locate(clone);
    1411             : }
    1412             : 
    1413             : // Return a clone of attribute with updated esi.
    1414       17810 : BgpAttrPtr BgpAttrDB::ReplaceEsiAndLocate(const BgpAttr *attr,
    1415             :                                           const EthernetSegmentId &esi) {
    1416       17810 :     BgpAttr *clone = new BgpAttr(*attr);
    1417       17810 :     clone->set_esi(esi);
    1418       17810 :     return Locate(clone);
    1419             : }
    1420             : 
    1421             : // Return a clone of attribute with updated olist.
    1422        4832 : BgpAttrPtr BgpAttrDB::ReplaceOListAndLocate(const BgpAttr *attr,
    1423             :     const BgpOListSpec *olist_spec) {
    1424        4832 :     assert(olist_spec->subcode == BgpAttribute::OList);
    1425        4832 :     BgpAttr *clone = new BgpAttr(*attr);
    1426        4832 :     clone->set_olist(olist_spec);
    1427        4832 :     return Locate(clone);
    1428             : }
    1429             : 
    1430             : // Return a clone of attribute with updated leaf olist.
    1431        4677 : BgpAttrPtr BgpAttrDB::ReplaceLeafOListAndLocate(const BgpAttr *attr,
    1432             :     const BgpOListSpec *leaf_olist_spec) {
    1433        4677 :     assert(leaf_olist_spec->subcode == BgpAttribute::LeafOList);
    1434        4677 :     BgpAttr *clone = new BgpAttr(*attr);
    1435        4677 :     clone->set_leaf_olist(leaf_olist_spec);
    1436        4677 :     return Locate(clone);
    1437             : }
    1438             : 
    1439             : // Return a clone of attribute with updated sub-protocol.
    1440        2038 : BgpAttrPtr BgpAttrDB::ReplaceSubProtocolAndLocate(const BgpAttr *attr,
    1441             :     const string &sbp) {
    1442        2038 :     BgpAttr *clone = new BgpAttr(*attr);
    1443        2038 :     clone->set_sub_protocol(sbp);
    1444        2038 :     return Locate(clone);
    1445             : }
    1446             : 
    1447             : 
    1448             : // Return a clone of attribute with updated pmsi tunnel.
    1449        8758 : BgpAttrPtr BgpAttrDB::ReplacePmsiTunnelAndLocate(const BgpAttr *attr,
    1450             :     const PmsiTunnelSpec *pmsi_spec) {
    1451        8758 :     BgpAttr *clone = new BgpAttr(*attr);
    1452        8758 :     clone->set_pmsi_tunnel(pmsi_spec);
    1453        8758 :     return Locate(clone);
    1454             : }
    1455             : 
    1456             : // Return a clone of attribute with updated nexthop.
    1457      338866 : BgpAttrPtr BgpAttrDB::ReplaceNexthopAndLocate(const BgpAttr *attr,
    1458             :     const IpAddress &addr) {
    1459      338866 :     BgpAttr *clone = new BgpAttr(*attr);
    1460      338874 :     clone->set_nexthop(addr);
    1461      338868 :     return Locate(clone);
    1462             : }

Generated by: LCOV version 1.14