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: 912 992 91.9 %
Date: 2026-11-09 02:10:49 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             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #include "bgp/bgp_attr.h"
       7             : 
       8             : #include <algorithm>
       9             : #include <string>
      10             : 
      11             : #include "bgp/bgp_server.h"
      12             : #include "bgp/extended-community/esi_label.h"
      13             : #include "bgp/extended-community/etree.h"
      14             : #include "bgp/extended-community/mac_mobility.h"
      15             : #include "bgp/extended-community/router_mac.h"
      16             : #include "net/bgp_af.h"
      17             : 
      18             : using std::sort;
      19             : using std::vector;
      20             : using std::string;
      21             : 
      22        9985 : int BgpAttrOrigin::CompareTo(const BgpAttribute &rhs_attr) const {
      23        9985 :     int ret = BgpAttribute::CompareTo(rhs_attr);
      24        9985 :     if (ret != 0) return ret;
      25        9985 :     KEY_COMPARE(origin, static_cast<const BgpAttrOrigin &>(rhs_attr).origin);
      26        9985 :     return 0;
      27             : }
      28             : 
      29      184580 : void BgpAttrOrigin::ToCanonical(BgpAttr *attr) {
      30      184580 :     attr->set_origin(static_cast<BgpAttrOrigin::OriginType>(origin));
      31      184580 : }
      32             : 
      33      111443 : string BgpAttrOrigin::ToString() const {
      34             :     char repr[80];
      35      111443 :     snprintf(repr, sizeof(repr), "ORIGIN <code: %d, flags: %02x> : %02x",
      36      111443 :              code, flags, origin);
      37      111443 :     return string(repr);
      38             : }
      39             : 
      40        9981 : int BgpAttrNextHop::CompareTo(const BgpAttribute &rhs_attr) const {
      41        9981 :     int ret = BgpAttribute::CompareTo(rhs_attr);
      42        9981 :     if (ret != 0) return ret;
      43        9981 :     KEY_COMPARE(nexthop,
      44             :             static_cast<const BgpAttrNextHop &>(rhs_attr).nexthop);
      45        9981 :     return 0;
      46             : }
      47             : 
      48      191097 : void BgpAttrNextHop::ToCanonical(BgpAttr *attr) {
      49      191097 :     if (v6_nexthop.is_unspecified()) {
      50      188566 :         attr->set_nexthop(Ip4Address(nexthop));
      51             :     } else {
      52        2532 :         attr->set_nexthop(v6_nexthop);
      53             :     }
      54      191099 : }
      55             : 
      56        3045 : string BgpAttrNextHop::ToString() const {
      57             :     char repr[80];
      58        3045 :     snprintf(repr, sizeof(repr), "NEXTHOP <code: %d, flags: %02x> : %04x",
      59        3045 :              code, flags, nexthop);
      60        3045 :     return string(repr);
      61             : }
      62             : 
      63        1988 : int BgpAttrMultiExitDisc::CompareTo(const BgpAttribute &rhs_attr) const {
      64        1988 :     int ret = BgpAttribute::CompareTo(rhs_attr);
      65        1988 :     if (ret != 0) return ret;
      66        1988 :     KEY_COMPARE(med, static_cast<const BgpAttrMultiExitDisc &>(rhs_attr).med);
      67        1986 :     return 0;
      68             : }
      69       76743 : void BgpAttrMultiExitDisc::ToCanonical(BgpAttr *attr) {
      70       76743 :     attr->set_med(med);
      71       76743 : }
      72             : 
      73       51917 : string BgpAttrMultiExitDisc::ToString() const {
      74             :     char repr[80];
      75       51917 :     snprintf(repr, sizeof(repr), "MED <code: %d, flags: %02x> : %d",
      76       51917 :              code, flags, med);
      77       51917 :     return string(repr);
      78             : }
      79             : 
      80        1994 : int BgpAttrLocalPref::CompareTo(const BgpAttribute &rhs_attr) const {
      81        1994 :     int ret = BgpAttribute::CompareTo(rhs_attr);
      82        1994 :     if (ret != 0) return ret;
      83        1994 :     KEY_COMPARE(local_pref,
      84             :             static_cast<const BgpAttrLocalPref &>(rhs_attr).local_pref);
      85        1994 :     return 0;
      86             : }
      87       92086 : void BgpAttrLocalPref::ToCanonical(BgpAttr *attr) {
      88       92086 :     attr->set_local_pref(local_pref);
      89       92085 : }
      90             : 
      91       23853 : string BgpAttrLocalPref::ToString() const {
      92             :     char repr[80];
      93       23853 :     snprintf(repr, sizeof(repr), "LOCAL_PREF <code: %d, flags: %02x> : %d",
      94       23853 :              code, flags, local_pref);
      95       23853 :     return string(repr);
      96             : }
      97             : 
      98           9 : void BgpAttrAtomicAggregate::ToCanonical(BgpAttr *attr) {
      99           9 :     attr->set_atomic_aggregate(true);
     100           9 : }
     101             : 
     102           1 : string BgpAttrAtomicAggregate::ToString() const {
     103             :     char repr[80];
     104           1 :     snprintf(repr, sizeof(repr), "ATOMIC_AGGR <code: %d, flags: %02x>",
     105           1 :              code, flags);
     106           1 :     return string(repr);
     107             : }
     108             : 
     109           3 : int BgpAttr4ByteAggregator::CompareTo(const BgpAttribute &rhs_attr) const {
     110           3 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     111           3 :     if (ret != 0) return ret;
     112           3 :     KEY_COMPARE(as_num,
     113             :             static_cast<const BgpAttr4ByteAggregator &>(rhs_attr).as_num);
     114           3 :     KEY_COMPARE(address,
     115             :             static_cast<const BgpAttr4ByteAggregator &>(rhs_attr).address);
     116           3 :     return 0;
     117             : }
     118           1 : void BgpAttr4ByteAggregator::ToCanonical(BgpAttr *attr) {
     119           1 :     attr->set_aggregator(as_num, Ip4Address(address));
     120           1 : }
     121             : 
     122           0 : string BgpAttr4ByteAggregator::ToString() const {
     123             :     char repr[80];
     124           0 :     snprintf(repr, sizeof(repr),
     125             :              "Aggregator <code: %d, flags: %02x> : %d:%08x",
     126           0 :              code, flags, as_num, address);
     127           0 :     return string(repr);
     128             : }
     129             : 
     130        1973 : int BgpAttrAggregator::CompareTo(const BgpAttribute &rhs_attr) const {
     131        1973 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     132        1973 :     if (ret != 0) return ret;
     133        1973 :     KEY_COMPARE(as_num,
     134             :             static_cast<const BgpAttrAggregator &>(rhs_attr).as_num);
     135        1971 :     KEY_COMPARE(address,
     136             :             static_cast<const BgpAttrAggregator &>(rhs_attr).address);
     137        1969 :     return 0;
     138             : }
     139           8 : void BgpAttrAggregator::ToCanonical(BgpAttr *attr) {
     140           8 :     attr->set_aggregator(as_num, Ip4Address(address));
     141           8 : }
     142             : 
     143           1 : string BgpAttrAggregator::ToString() const {
     144             :     char repr[80];
     145           1 :     snprintf(repr, sizeof(repr),
     146             :              "Aggregator <code: %d, flags: %02x> : %d:%08x",
     147           1 :              code, flags, as_num, address);
     148           1 :     return string(repr);
     149             : }
     150             : 
     151           0 : int BgpAttrAs4Aggregator::CompareTo(const BgpAttribute &rhs_attr) const {
     152           0 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     153           0 :     if (ret != 0) return ret;
     154           0 :     KEY_COMPARE(as_num,
     155             :             static_cast<const BgpAttrAs4Aggregator &>(rhs_attr).as_num);
     156           0 :     KEY_COMPARE(address,
     157             :             static_cast<const BgpAttrAs4Aggregator &>(rhs_attr).address);
     158           0 :     return 0;
     159             : }
     160           0 : void BgpAttrAs4Aggregator::ToCanonical(BgpAttr *attr) {
     161           0 :     attr->set_as4_aggregator(as_num, Ip4Address(address));
     162           0 : }
     163             : 
     164           0 : string BgpAttrAs4Aggregator::ToString() const {
     165             :     char repr[80];
     166           0 :     snprintf(repr, sizeof(repr),
     167             :              "Aggregator <code: %d, flags: %02x> : %d:%08x",
     168           0 :              code, flags, as_num, address);
     169           0 :     return string(repr);
     170             : }
     171             : 
     172           3 : int BgpAttrOriginatorId::CompareTo(const BgpAttribute &rhs_attr) const {
     173           3 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     174           3 :     if (ret != 0) return ret;
     175           3 :     KEY_COMPARE(originator_id,
     176             :         static_cast<const BgpAttrOriginatorId &>(rhs_attr).originator_id);
     177           1 :     return 0;
     178             : }
     179             : 
     180          18 : void BgpAttrOriginatorId::ToCanonical(BgpAttr *attr) {
     181          18 :     attr->set_originator_id(Ip4Address(originator_id));
     182          18 : }
     183             : 
     184           3 : string BgpAttrOriginatorId::ToString() const {
     185             :     char repr[80];
     186           3 :     snprintf(repr, sizeof(repr), "OriginatorId <code: %d, flags: 0x%02x> : %s",
     187           6 :              code, flags, Ip4Address(originator_id).to_string().c_str());
     188           3 :     return string(repr);
     189             : }
     190             : 
     191           9 : ClusterListSpec::ClusterListSpec(uint32_t cluster_id,
     192           9 :     const ClusterListSpec *rhs)
     193           9 :     : BgpAttribute(BgpAttribute::ClusterList, kFlags) {
     194           9 :     cluster_list.push_back(cluster_id);
     195           9 :     if (rhs) {
     196           1 :         cluster_list.insert(cluster_list.end(), rhs->cluster_list.begin(),
     197             :             rhs->cluster_list.end());
     198             :     }
     199           9 : }
     200             : 
     201          46 : int ClusterListSpec::CompareTo(const BgpAttribute &rhs_attr) const {
     202          46 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     203          46 :     if (ret != 0) return ret;
     204          46 :     KEY_COMPARE(cluster_list,
     205             :         static_cast<const ClusterListSpec &>(rhs_attr).cluster_list);
     206          38 :     return 0;
     207             : }
     208             : 
     209           8 : void ClusterListSpec::ToCanonical(BgpAttr *attr) {
     210           8 :     attr->set_cluster_list(this);
     211           8 : }
     212             : 
     213           3 : string ClusterListSpec::ToString() const {
     214           3 :     std::stringstream repr;
     215           3 :     repr << "CLUSTER_LIST <code: " << int(code);
     216           3 :     repr << ", flags: 0x" << std::hex << int(flags) << "> :";
     217           3 :     for (vector<uint32_t>::const_iterator iter = cluster_list.begin();
     218           9 :          iter != cluster_list.end(); ++iter) {
     219           6 :         repr << " " << Ip4Address(*iter).to_string();
     220             :     }
     221           6 :     return repr.str();
     222           3 : }
     223             : 
     224          14 : bool ClusterListSpec::ClusterListLoop(uint32_t cluster_id) const {
     225          14 :     for (vector<uint32_t>::const_iterator iter = cluster_list.begin();
     226          56 :          iter != cluster_list.end(); ++iter) {
     227          47 :         if (*iter == cluster_id)
     228           5 :             return true;
     229             :     }
     230           9 :     return false;
     231             : }
     232             : 
     233          22 : ClusterList::ClusterList(ClusterListDB *cluster_list_db,
     234          22 :     const ClusterListSpec &spec)
     235          22 :     : cluster_list_db_(cluster_list_db),
     236          22 :       spec_(spec) {
     237          22 :     refcount_ = 0;
     238          22 : }
     239             : 
     240          18 : void ClusterList::Remove() {
     241          18 :     cluster_list_db_->Delete(this);
     242          18 : }
     243             : 
     244        9743 : ClusterListDB::ClusterListDB(BgpServer *server) {
     245        9743 : }
     246             : 
     247        1990 : int BgpMpNlri::CompareTo(const BgpAttribute &rhs_attr) const {
     248        1990 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     249        1990 :     if (ret != 0) return ret;
     250        1990 :     const BgpMpNlri &rhs = static_cast<const BgpMpNlri &>(rhs_attr);
     251        1990 :     KEY_COMPARE(afi, rhs.afi);
     252        1990 :     KEY_COMPARE(safi, rhs.safi);
     253        1990 :     KEY_COMPARE(nexthop, rhs.nexthop);
     254        1990 :     KEY_COMPARE(nlri.size(), rhs.nlri.size());
     255             : 
     256      498340 :     for (size_t i = 0; i < nlri.size(); i++) {
     257      496350 :         KEY_COMPARE(nlri[i]->type, rhs.nlri[i]->type);
     258      496350 :         KEY_COMPARE(nlri[i]->prefixlen, rhs.nlri[i]->prefixlen);
     259      496350 :         KEY_COMPARE(nlri[i]->prefix, rhs.nlri[i]->prefix);
     260             :     }
     261        1990 :     return 0;
     262             : }
     263             : 
     264      158286 : void BgpMpNlri::ToCanonical(BgpAttr *attr) {
     265      158286 : }
     266             : 
     267      505519 : size_t BgpMpNlri::EncodeLength() const {
     268      505519 :     size_t sz = 2 /* safi */ + 1 /* afi */ +
     269             :                 1 /* NlriNextHopLength */ +
     270             :                 1 /* Reserved */;
     271      505519 :     sz += nexthop.size();
     272      505540 :     for (vector<BgpProtoPrefix*>::const_iterator iter = nlri.begin();
     273     2854682 :          iter != nlri.end(); ++iter) {
     274     2349152 :         size_t bytes = 0;
     275     2349152 :         if (afi == BgpAf::L2Vpn &&
     276       39764 :             (safi == BgpAf::EVpn || safi == BgpAf::ErmVpn)) {
     277       39764 :             bytes = (*iter)->prefixlen;
     278             :         } else {
     279     2309388 :             bytes = ((*iter)->prefixlen + 7) / 8;
     280             :         }
     281     2349157 :         sz += 1 + bytes;
     282             :     }
     283      505513 :     return sz;
     284             : }
     285             : 
     286       25397 : PmsiTunnelSpec::PmsiTunnelSpec()
     287             :     : BgpAttribute(PmsiTunnel, kFlags),
     288       25397 :       tunnel_flags(0), tunnel_type(0), label(0) {
     289       25396 : }
     290             : 
     291        3006 : PmsiTunnelSpec::PmsiTunnelSpec(const BgpAttribute &rhs)
     292        3006 :     : BgpAttribute(rhs), tunnel_flags(0), tunnel_type(0), label(0) {
     293        3006 : }
     294             : 
     295      659713 : int PmsiTunnelSpec::CompareTo(const BgpAttribute &rhs_attr) const {
     296      659713 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     297      659713 :     if (ret != 0) return ret;
     298      659713 :     const PmsiTunnelSpec &rhs = static_cast<const PmsiTunnelSpec &>(rhs_attr);
     299      659713 :     KEY_COMPARE(tunnel_flags, rhs.tunnel_flags);
     300      648059 :     KEY_COMPARE(tunnel_type, rhs.tunnel_type);
     301      648052 :     KEY_COMPARE(label, rhs.label);
     302      624122 :     KEY_COMPARE(identifier, rhs.identifier);
     303      621449 :     return 0;
     304             : }
     305             : 
     306        8132 : void PmsiTunnelSpec::ToCanonical(BgpAttr *attr) {
     307        8132 :     attr->set_pmsi_tunnel(this);
     308        8132 : }
     309             : 
     310         840 : string PmsiTunnelSpec::ToString() const {
     311         840 :     std::ostringstream oss;
     312         840 :     oss << "PmsiTunnel <code: " << int(code);
     313         840 :     oss << ", flags: 0x" << std::hex << int(flags) << std::dec << ">";
     314         840 :     oss << " Tunnel Flags: 0x" << std::hex << int(tunnel_flags) << std::dec;
     315         840 :     oss << " Tunnel Type: " << int(tunnel_type);
     316         840 :     oss << " Label: 0x" << std::hex << int(label) << std::dec;
     317         840 :     oss << " (" << int(label) << ")";
     318         840 :     oss << " Identifier: " << GetIdentifier().to_string();
     319             : 
     320        1680 :     return oss.str();
     321         840 : }
     322             : 
     323           2 : uint32_t PmsiTunnelSpec::GetLabel(const ExtCommunity *ext) const {
     324           2 :     assert(ext);
     325           2 :     bool is_vni = ext->ContainsTunnelEncapVxlan();
     326           2 :     return (is_vni ? label : (label >> 4));
     327             : }
     328             : 
     329        7747 : void PmsiTunnelSpec::SetLabel(uint32_t in_label, const ExtCommunity *ext) {
     330        7747 :     assert(ext);
     331        7747 :     bool is_vni = ext->ContainsTunnelEncapVxlan();
     332        7747 :     label = (is_vni ? in_label : (in_label << 4 | 0x01));
     333        7747 : }
     334             : 
     335       18762 : Ip4Address PmsiTunnelSpec::GetIdentifier() const {
     336       18762 :     if (identifier.size() < 4)
     337        9824 :         return Ip4Address();
     338        8938 :     return Ip4Address(get_value(&identifier[0], 4));
     339             : }
     340             : 
     341       11690 : void PmsiTunnelSpec::SetIdentifier(Ip4Address in_identifier) {
     342       11690 :     identifier.resize(4, 0);
     343       11689 :     const Ip4Address::bytes_type &bytes = in_identifier.to_bytes();
     344       11689 :     std::copy(bytes.begin(), bytes.begin() + 4, identifier.begin());
     345       11689 : }
     346             : 
     347           9 : string PmsiTunnelSpec::GetTunnelTypeString() const {
     348           9 :     switch (tunnel_type) {
     349           1 :     case RsvpP2mpLsp:
     350           1 :         return "RsvpP2mpLsp";
     351           1 :     case LdpP2mpLsp:
     352           1 :         return "LdpP2mpLsp";
     353           1 :     case PimSsmTree:
     354           1 :         return "PimSsmTree";
     355           1 :     case PimSmTree:
     356           1 :         return "PimSmTree";
     357           1 :     case BidirPimTree:
     358           1 :         return "BidirPimTree";
     359           1 :     case IngressReplication:
     360           1 :         return "IngressReplication";
     361           1 :     case MldpMp2mpLsp:
     362           1 :         return "MldpMp2mpLsp";
     363           1 :     case AssistedReplicationContrail:
     364           1 :         return "AssistedReplication";
     365           1 :     default:
     366           1 :         break;
     367             :     }
     368           2 :     std::ostringstream oss;
     369           1 :     oss << "Unknown(" << int(tunnel_type) << ")";
     370           1 :     return oss.str();
     371             : }
     372             : 
     373           4 : string PmsiTunnelSpec::GetTunnelArTypeString() const {
     374           4 :     switch (tunnel_flags & AssistedReplicationType) {
     375           1 :     case RegularNVE:
     376           1 :         return "RegularNVE";
     377           1 :     case ARReplicator:
     378           1 :         return "ARReplicator";
     379           1 :     case ARLeaf:
     380           1 :         return "ARLeaf";
     381           1 :     default:
     382           1 :         break;
     383             :     }
     384           1 :     return "Unknown";
     385             : }
     386             : 
     387           4 : vector<string> PmsiTunnelSpec::GetTunnelFlagsStrings() const {
     388           4 :     vector<string> flags;
     389           4 :     if (tunnel_flags & LeafInfoRequired) {
     390           2 :         flags.push_back("LeafInfoRequired");
     391             :     }
     392           4 :     if (tunnel_flags & EdgeReplicationSupported) {
     393           2 :         flags.push_back("EdgeReplicationSupported");
     394             :     }
     395           4 :     if (flags.empty()) {
     396           1 :         flags.push_back("None");
     397             :     }
     398           4 :     return flags;
     399           0 : }
     400             : 
     401       17923 : PmsiTunnel::PmsiTunnel(PmsiTunnelDB *pmsi_tunnel_db,
     402       17923 :     const PmsiTunnelSpec &pmsi_spec)
     403       17923 :     : pmsi_tunnel_db_(pmsi_tunnel_db),
     404       17923 :       pmsi_spec_(pmsi_spec) {
     405       17917 :     refcount_ = 0;
     406       17922 :     tunnel_flags_ = pmsi_spec_.tunnel_flags;
     407       17922 :     tunnel_type_ = pmsi_spec_.tunnel_type;
     408       17922 :     label_ = pmsi_spec_.label;
     409       17922 :     identifier_ = pmsi_spec_.GetIdentifier();
     410       17920 : }
     411             : 
     412        4973 : void PmsiTunnel::Remove() {
     413        4973 :     pmsi_tunnel_db_->Delete(this);
     414        4973 : }
     415             : 
     416        2598 : uint32_t PmsiTunnel::GetLabel(const ExtCommunity *ext) const {
     417        2598 :     bool is_vni = false;
     418        2598 :     if (ext)
     419        2586 :         is_vni = ext->ContainsTunnelEncapVxlan();
     420        2598 :     return (is_vni ? label_ : label_ >> 4);
     421             : }
     422             : 
     423        9743 : PmsiTunnelDB::PmsiTunnelDB(BgpServer *server) {
     424        9743 : }
     425             : 
     426        5859 : EdgeDiscoverySpec::EdgeDiscoverySpec()
     427        5859 :     : BgpAttribute(McastEdgeDiscovery, kFlags) {
     428        5858 : }
     429             : 
     430        3814 : EdgeDiscoverySpec::EdgeDiscoverySpec(const BgpAttribute &rhs)
     431        3814 :     : BgpAttribute(rhs) {
     432        3814 : }
     433             : 
     434        4118 : EdgeDiscoverySpec::EdgeDiscoverySpec(const EdgeDiscoverySpec &rhs)
     435        4118 :     : BgpAttribute(BgpAttribute::McastEdgeDiscovery, kFlags) {
     436       13385 :     for (size_t i = 0; i < rhs.edge_list.size(); i++) {
     437        9268 :         Edge *edge = new Edge;
     438        9269 :         *edge = *rhs.edge_list[i];
     439        9268 :         edge_list.push_back(edge);
     440             :     }
     441        4117 : }
     442             : 
     443       22640 : EdgeDiscoverySpec::~EdgeDiscoverySpec() {
     444       13780 :     STLDeleteValues(&edge_list);
     445       22615 : }
     446             : 
     447        9754 : Ip4Address EdgeDiscoverySpec::Edge::GetIp4Address() const {
     448        9754 :     return Ip4Address(get_value(&address[0], 4));
     449             : }
     450             : 
     451      130307 : void EdgeDiscoverySpec::Edge::SetIp4Address(Ip4Address addr) {
     452      130307 :     address.resize(4, 0);
     453      130307 :     const Ip4Address::bytes_type &addr_bytes = addr.to_bytes();
     454      130307 :     std::copy(addr_bytes.begin(), addr_bytes.begin() + 4, address.begin());
     455      130307 : }
     456             : 
     457        9753 : void EdgeDiscoverySpec::Edge::GetLabels(
     458             :     uint32_t *first_label, uint32_t *last_label) const {
     459        9753 :     *first_label = labels[0];
     460        9753 :     *last_label = labels[1];
     461        9753 : }
     462             : 
     463      130307 : void EdgeDiscoverySpec::Edge::SetLabels(
     464             :     uint32_t first_label, uint32_t last_label) {
     465      130307 :     labels.push_back(first_label);
     466      130307 :     labels.push_back(last_label);
     467      130307 : }
     468             : 
     469             : struct EdgeDiscoverySpecEdgeCompare {
     470       63710 :     int operator()(const EdgeDiscoverySpec::Edge *lhs,
     471             :                    const EdgeDiscoverySpec::Edge *rhs) const {
     472       63710 :         KEY_COMPARE(lhs->address, rhs->address);
     473       63710 :         KEY_COMPARE(lhs->labels, rhs->labels);
     474       63710 :         return 0;
     475             :     }
     476             : };
     477             : 
     478        2003 : int EdgeDiscoverySpec::CompareTo(const BgpAttribute &rhs_attr) const {
     479        2003 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     480        2003 :     if (ret != 0) return ret;
     481        2003 :     const EdgeDiscoverySpec &rhs =
     482             :             static_cast<const EdgeDiscoverySpec &>(rhs_attr);
     483        2003 :     ret = STLSortedCompare(edge_list.begin(), edge_list.end(),
     484             :                            rhs.edge_list.begin(), rhs.edge_list.end(),
     485             :                            EdgeDiscoverySpecEdgeCompare());
     486        2003 :     return ret;
     487             : }
     488             : 
     489        2031 : void EdgeDiscoverySpec::ToCanonical(BgpAttr *attr) {
     490        2031 :     attr->set_edge_discovery(this);
     491        2031 : }
     492             : 
     493        1207 : string EdgeDiscoverySpec::ToString() const {
     494        1207 :     std::ostringstream oss;
     495        1207 :     oss << "EdgeDiscovery <code: " << int(code);
     496        1207 :     oss << ", flags: 0x" << std::hex << int(flags) << std::dec << ">";
     497        1207 :     int idx = 0;
     498        1207 :     for (EdgeList::const_iterator it = edge_list.begin();
     499        4822 :          it != edge_list.end(); ++it, ++idx) {
     500        3616 :         const Edge *edge = *it;
     501             :         uint32_t first_label, last_label;
     502        3616 :         edge->GetLabels(&first_label, &last_label);
     503        3616 :         oss << " Edge[" << idx << "] = (" << edge->GetIp4Address() << ", ";
     504        3616 :         oss << first_label << "-" << last_label << ")";
     505             :     }
     506             : 
     507        2414 :     return oss.str();
     508        1207 : }
     509             : 
     510       13936 : size_t EdgeDiscoverySpec::EncodeLength() const {
     511       13936 :     size_t sz = 0;
     512       13936 :     for (EdgeList::const_iterator iter = edge_list.begin();
     513      276705 :          iter != edge_list.end(); ++iter) {
     514      262769 :         sz += 2; /* AddressLen + LabelLen */
     515      262769 :         sz += (*iter)->address.size();
     516      262769 :         sz += (*iter)->labels.size() * sizeof(uint32_t);
     517             :     }
     518       13936 :     return sz;
     519             : }
     520             : 
     521        6110 : EdgeDiscovery::Edge::Edge(const EdgeDiscoverySpec::Edge *spec_edge) {
     522        6110 :     address = spec_edge->GetIp4Address();
     523             :     uint32_t first_label, last_label;
     524        6110 :     spec_edge->GetLabels(&first_label, &last_label);
     525        6110 :     label_block = new LabelBlock(first_label, last_label);
     526        6111 : }
     527             : 
     528       53095 : bool EdgeDiscovery::Edge::operator<(const Edge &rhs) const {
     529       53095 :     BOOL_KEY_COMPARE(address, rhs.address);
     530       46049 :     BOOL_KEY_COMPARE(label_block->first(), rhs.label_block->first());
     531       40688 :     BOOL_KEY_COMPARE(label_block->last(), rhs.label_block->last());
     532       40688 :     return false;
     533             : }
     534             : 
     535        3066 : EdgeDiscovery::EdgeDiscovery(EdgeDiscoveryDB *edge_discovery_db,
     536        3066 :     const EdgeDiscoverySpec &edspec)
     537        3065 :     : edge_discovery_db_(edge_discovery_db),
     538        3066 :       edspec_(edspec) {
     539        3064 :     refcount_ = 0;
     540        3061 :     for (EdgeDiscoverySpec::EdgeList::const_iterator it =
     541        9176 :          edspec_.edge_list.begin(); it != edspec_.edge_list.end(); ++it) {
     542        6110 :         Edge *edge = new Edge(*it);
     543        6111 :         edge_list.push_back(edge);
     544             :     }
     545        3061 :     sort(edge_list.begin(), edge_list.end(), EdgeDiscovery::EdgeCompare());
     546        3062 : }
     547             : 
     548        5108 : EdgeDiscovery::~EdgeDiscovery() {
     549        3066 :     STLDeleteValues(&edge_list);
     550        5108 : }
     551             : 
     552             : struct EdgeDiscoveryEdgeCompare {
     553       21044 :     int operator()(const EdgeDiscovery::Edge *lhs,
     554             :                    const EdgeDiscovery::Edge *rhs) const {
     555       21044 :         KEY_COMPARE(*lhs, *rhs);
     556       12236 :         return 0;
     557             :     }
     558             : };
     559             : 
     560      638655 : int EdgeDiscovery::CompareTo(const EdgeDiscovery &rhs) const {
     561      638655 :     int result = STLSortedCompare(edge_list.begin(), edge_list.end(),
     562             :                                   rhs.edge_list.begin(), rhs.edge_list.end(),
     563             :                                   EdgeDiscoveryEdgeCompare());
     564      638655 :     return result;
     565             : }
     566             : 
     567        1763 : void EdgeDiscovery::Remove() {
     568        1763 :     edge_discovery_db_->Delete(this);
     569        1763 : }
     570             : 
     571        9743 : EdgeDiscoveryDB::EdgeDiscoveryDB(BgpServer *server) {
     572        9743 : }
     573             : 
     574        6287 : EdgeForwardingSpec::EdgeForwardingSpec()
     575        6287 :     : BgpAttribute(McastEdgeForwarding, kFlags) {
     576        6286 : }
     577             : 
     578        4537 : EdgeForwardingSpec::EdgeForwardingSpec(const BgpAttribute &rhs)
     579        4537 :     : BgpAttribute(rhs) {
     580        4537 : }
     581             : 
     582        5983 : EdgeForwardingSpec::EdgeForwardingSpec(const EdgeForwardingSpec &rhs)
     583        5983 :     : BgpAttribute(BgpAttribute::McastEdgeForwarding, kFlags) {
     584       11013 :     for (size_t i = 0; i < rhs.edge_list.size(); i++) {
     585        5031 :         Edge *edge = new Edge;
     586        5031 :         *edge = *rhs.edge_list[i];
     587        5031 :         edge_list.push_back(edge);
     588             :     }
     589        5982 : }
     590             : 
     591       27020 : EdgeForwardingSpec:: ~EdgeForwardingSpec() {
     592       16795 :     STLDeleteValues(&edge_list);
     593       26994 : }
     594             : 
     595        5375 : Ip4Address EdgeForwardingSpec::Edge::GetInboundIp4Address() const {
     596        5375 :     return Ip4Address(get_value(&inbound_address[0], 4));
     597             : }
     598             : 
     599        5376 : Ip4Address EdgeForwardingSpec::Edge::GetOutboundIp4Address() const {
     600        5376 :     return Ip4Address(get_value(&outbound_address[0], 4));
     601             : }
     602             : 
     603      126137 : void EdgeForwardingSpec::Edge::SetInboundIp4Address(Ip4Address addr) {
     604      126137 :     inbound_address.resize(4, 0);
     605      126137 :     const Ip4Address::bytes_type &addr_bytes = addr.to_bytes();
     606      126137 :     std::copy(addr_bytes.begin(), addr_bytes.begin() + 4,
     607             :         inbound_address.begin());
     608      126137 : }
     609             : 
     610      126137 : void EdgeForwardingSpec::Edge::SetOutboundIp4Address(Ip4Address addr) {
     611      126137 :     outbound_address.resize(4, 0);
     612      126137 :     const Ip4Address::bytes_type &addr_bytes = addr.to_bytes();
     613      126137 :     std::copy(addr_bytes.begin(), addr_bytes.begin() + 4,
     614             :         outbound_address.begin());
     615      126137 : }
     616             : 
     617             : struct EdgeForwardingSpecEdgeCompare {
     618       59919 :     int operator()(const EdgeForwardingSpec::Edge *lhs,
     619             :                    const EdgeForwardingSpec::Edge *rhs) const {
     620       59919 :         KEY_COMPARE(lhs->inbound_address, rhs->inbound_address);
     621       59919 :         KEY_COMPARE(lhs->outbound_address, rhs->outbound_address);
     622       59919 :         KEY_COMPARE(lhs->inbound_label, rhs->inbound_label);
     623       59919 :         KEY_COMPARE(lhs->outbound_label, rhs->outbound_label);
     624       59919 :         return 0;
     625             :     }
     626             : };
     627             : 
     628        1898 : int EdgeForwardingSpec::CompareTo(const BgpAttribute &rhs_attr) const {
     629        1898 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     630        1898 :     if (ret != 0) return ret;
     631        1898 :     const EdgeForwardingSpec &rhs =
     632             :             static_cast<const EdgeForwardingSpec &>(rhs_attr);
     633        1898 :     ret = STLSortedCompare(edge_list.begin(), edge_list.end(),
     634             :                            rhs.edge_list.begin(), rhs.edge_list.end(),
     635             :                            EdgeForwardingSpecEdgeCompare());
     636        1898 :     return ret;
     637             : }
     638             : 
     639        3245 : void EdgeForwardingSpec::ToCanonical(BgpAttr *attr) {
     640        3245 :     attr->set_edge_forwarding(this);
     641        3245 : }
     642             : 
     643        1986 : string EdgeForwardingSpec::ToString() const {
     644        1986 :     std::ostringstream oss;
     645        1986 :     oss << "EdgeForwarding <code: " << int(code);
     646        1986 :     oss << ", flags: 0x" << std::hex << int(flags) << std::dec << ">";
     647        1986 :     int idx = 0;
     648        1986 :     for (EdgeList::const_iterator it = edge_list.begin();
     649        4185 :          it != edge_list.end(); ++it, ++idx) {
     650        2200 :         const Edge *edge = *it;
     651        2200 :         oss << " Edge[" << idx << "] = (";
     652        2200 :         oss << "InAddress=" << edge->GetInboundIp4Address() << ", ";
     653        2200 :         oss << "InLabel=" << edge->inbound_label << ", ";
     654        2200 :         oss << "OutAddress=" << edge->GetOutboundIp4Address() << ", ";
     655        2200 :         oss << "OutLabel=" << edge->outbound_label << ")";
     656             :     }
     657             : 
     658        3972 :     return oss.str();
     659        1986 : }
     660             : 
     661       15940 : size_t EdgeForwardingSpec::EncodeLength() const {
     662       15940 :     size_t sz = 0;
     663       15940 :     for (EdgeList::const_iterator iter = edge_list.begin();
     664      270978 :          iter != edge_list.end(); ++iter) {
     665      255037 :         sz += 1 /* address len */ + 8 /* 2 labels */;
     666      255037 :         sz += (*iter)->inbound_address.size();
     667      255037 :         sz += (*iter)->outbound_address.size();
     668             :     }
     669             : 
     670       15941 :     return sz;
     671             : }
     672             : 
     673        3172 : EdgeForwarding::Edge::Edge(const EdgeForwardingSpec::Edge *spec_edge) {
     674        3172 :     inbound_address = spec_edge->GetInboundIp4Address();
     675        3172 :     outbound_address = spec_edge->GetOutboundIp4Address();
     676        3172 :     inbound_label = spec_edge->inbound_label;
     677        3172 :     outbound_label = spec_edge->outbound_label;
     678        3172 : }
     679             : 
     680       31731 : bool EdgeForwarding::Edge::operator<(const Edge &rhs) const {
     681       31731 :     BOOL_KEY_COMPARE(inbound_address, rhs.inbound_address);
     682       22123 :     BOOL_KEY_COMPARE(outbound_address, rhs.outbound_address);
     683       17564 :     BOOL_KEY_COMPARE(inbound_label, rhs.inbound_label);
     684       15672 :     BOOL_KEY_COMPARE(outbound_label, rhs.outbound_label);
     685       13431 :     return false;
     686             : }
     687             : 
     688        4279 : EdgeForwarding::EdgeForwarding(EdgeForwardingDB *edge_forwarding_db,
     689        4279 :     const EdgeForwardingSpec &efspec)
     690        4278 :     : edge_forwarding_db_(edge_forwarding_db),
     691        4279 :       efspec_(efspec) {
     692        4277 :     refcount_ = 0;
     693        4275 :     for (EdgeForwardingSpec::EdgeList::const_iterator it =
     694        7453 :          efspec_.edge_list.begin(); it != efspec_.edge_list.end(); ++it) {
     695        3172 :         Edge *edge = new Edge(*it);
     696        3172 :         edge_list.push_back(edge);
     697             :     }
     698        4269 :     sort(edge_list.begin(), edge_list.end(), EdgeForwarding::EdgeCompare());
     699        4268 : }
     700             : 
     701        7538 : EdgeForwarding::~EdgeForwarding() {
     702        4281 :     STLDeleteValues(&edge_list);
     703        7538 : }
     704             : 
     705             : struct EdgeForwardingEdgeCompare {
     706       17998 :     int operator()(const EdgeForwarding::Edge *lhs,
     707             :                    const EdgeForwarding::Edge *rhs) const {
     708       17998 :         KEY_COMPARE(*lhs, *rhs);
     709        6718 :         return 0;
     710             :     }
     711             : };
     712             : 
     713      871202 : int EdgeForwarding::CompareTo(const EdgeForwarding &rhs) const {
     714      871202 :     int result = STLSortedCompare(edge_list.begin(), edge_list.end(),
     715             :                                   rhs.edge_list.begin(), rhs.edge_list.end(),
     716             :                                   EdgeForwardingEdgeCompare());
     717      871201 :     return result;
     718             : }
     719             : 
     720        2219 : void EdgeForwarding::Remove() {
     721        2219 :     edge_forwarding_db_->Delete(this);
     722        2219 : }
     723             : 
     724        9743 : EdgeForwardingDB::EdgeForwardingDB(BgpServer *server) {
     725        9743 : }
     726             : 
     727      199371 : bool BgpOListElem::operator<(const BgpOListElem &rhs) const {
     728      199371 :     BOOL_KEY_COMPARE(address, rhs.address);
     729      131099 :     BOOL_KEY_COMPARE(label, rhs.label);
     730      127025 :     BOOL_KEY_COMPARE(encap, rhs.encap);
     731      127014 :     return false;
     732             : }
     733             : 
     734           3 : int BgpOListSpec::CompareTo(const BgpAttribute &rhs_attr) const {
     735           3 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     736           3 :     if (ret != 0) return ret;
     737           3 :     return 0;
     738             : }
     739             : 
     740        3475 : void BgpOListSpec::ToCanonical(BgpAttr *attr) {
     741        3475 :     if (subcode == BgpAttribute::OList) {
     742        3475 :         attr->set_olist(this);
     743           0 :     } else if (subcode == BgpAttribute::LeafOList) {
     744           0 :         attr->set_leaf_olist(this);
     745             :     } else {
     746           0 :         assert(false);
     747             :     }
     748        3475 : }
     749             : 
     750           1 : string BgpOListSpec::ToString() const {
     751           1 :     std::ostringstream oss;
     752           1 :     oss << "OList <subcode: " << int(subcode) << ">";
     753           1 :     int idx = 0;
     754           1 :     for (Elements::const_iterator it = elements.begin();
     755           3 :          it != elements.end(); ++it, ++idx) {
     756           2 :         BgpOListElem elem(*it);
     757           2 :         oss << "OList[" << idx << "] = (";
     758           2 :         oss << "address: " << elem.address << ", ";
     759           2 :         oss << "label: " << elem.label << ", ";
     760           2 :         oss << "encap-list:";
     761           2 :         int eid = 0;
     762           2 :         for (vector<string>::const_iterator e_it = elem.encap.begin();
     763           6 :              e_it != elem.encap.end(); ++e_it, ++eid) {
     764           4 :              oss << " " << *e_it;
     765             :         }
     766           2 :         oss << ")";
     767           2 :     }
     768           2 :     return (oss.str());
     769           1 : }
     770             : 
     771       13874 : BgpOList::BgpOList(BgpOListDB *olist_db, const BgpOListSpec &olist_spec)
     772       13874 :     : olist_db_(olist_db),
     773       13874 :       olist_spec_(olist_spec) {
     774       13870 :     refcount_ = 0;
     775       13874 :     for (BgpOListSpec::Elements::const_iterator it =
     776       36816 :          olist_spec_.elements.begin(); it != olist_spec_.elements.end(); ++it) {
     777       22941 :         BgpOListElem *elem = new BgpOListElem(*it);
     778       22941 :         sort(elem->encap.begin(), elem->encap.end());
     779       22941 :         elements_.push_back(elem);
     780             :     }
     781       13873 :     sort(elements_.begin(), elements_.end(), BgpOListElemCompare());
     782       13872 : }
     783             : 
     784       26724 : BgpOList::~BgpOList() {
     785       13873 :     STLDeleteValues(&elements_);
     786       26723 : }
     787             : 
     788             : struct BgpOListElementCompare {
     789       77729 :     int operator()(const BgpOListElem *lhs, const BgpOListElem *rhs) const {
     790       77729 :         KEY_COMPARE(*lhs, *rhs);
     791       63507 :         return 0;
     792             :     }
     793             : };
     794             : 
     795      425926 : int BgpOList::CompareTo(const BgpOList &rhs) const {
     796      425926 :     KEY_COMPARE(olist().subcode, rhs.olist().subcode);
     797      822166 :     int result = STLSortedCompare(elements().begin(), elements().end(),
     798      822166 :                                   rhs.elements().begin(), rhs.elements().end(),
     799             :                                   BgpOListElementCompare());
     800      411083 :     return result;
     801             : }
     802             : 
     803        9638 : void BgpOList::Remove() {
     804        9638 :     olist_db_->Delete(this);
     805        9638 : }
     806             : 
     807        9743 : BgpOListDB::BgpOListDB(BgpServer *server) {
     808        9743 : }
     809             : 
     810           0 : int BgpAttrLabelBlock::CompareTo(const BgpAttribute &rhs_attr) const {
     811           0 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     812           0 :     if (ret != 0) return ret;
     813           0 :     KEY_COMPARE(label_block.get(),
     814             :             static_cast<const BgpAttrLabelBlock &>(rhs_attr).label_block.get());
     815           0 :     return 0;
     816             : }
     817             : 
     818        1033 : void BgpAttrLabelBlock::ToCanonical(BgpAttr *attr) {
     819        1033 :     attr->set_label_block(label_block);
     820        1033 : }
     821             : 
     822           0 : string BgpAttrLabelBlock::ToString() const {
     823             :     char repr[80];
     824           0 :     snprintf(repr, sizeof(repr), "LabelBlock <subcode: %d> : %d-%d",
     825           0 :              subcode, label_block->first(), label_block->last());
     826           0 :     return string(repr);
     827             : }
     828             : 
     829           3 : int BgpAttrSourceRd::CompareTo(const BgpAttribute &rhs_attr) const {
     830           3 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     831           3 :     if (ret != 0) return ret;
     832           3 :     KEY_COMPARE(source_rd,
     833             :             static_cast<const BgpAttrSourceRd &>(rhs_attr).source_rd);
     834           1 :     return 0;
     835             : }
     836             : 
     837       28475 : void BgpAttrSourceRd::ToCanonical(BgpAttr *attr) {
     838       28475 :     attr->set_source_rd(source_rd);
     839       28475 : }
     840             : 
     841           1 : string BgpAttrSourceRd::ToString() const {
     842             :     char repr[80];
     843           1 :     snprintf(repr, sizeof(repr), "SourceRd <subcode: %d> : %s",
     844           2 :              subcode, source_rd.ToString().c_str());
     845           1 :     return string(repr);
     846             : }
     847             : 
     848           3 : int BgpAttrEsi::CompareTo(const BgpAttribute &rhs_attr) const {
     849           3 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     850           3 :     if (ret != 0) return ret;
     851           3 :     KEY_COMPARE(esi, static_cast<const BgpAttrEsi &>(rhs_attr).esi);
     852           1 :     return 0;
     853             : }
     854             : 
     855          59 : void BgpAttrEsi::ToCanonical(BgpAttr *attr) {
     856          59 :     attr->set_esi(esi);
     857          59 : }
     858             : 
     859           1 : string BgpAttrEsi::ToString() const {
     860             :     char repr[80];
     861           1 :     snprintf(repr, sizeof(repr), "Esi <subcode: %d> : %s",
     862           2 :              subcode, esi.ToString().c_str());
     863           1 :     return string(repr);
     864             : }
     865             : 
     866           3 : int BgpAttrParams::CompareTo(const BgpAttribute &rhs_attr) const {
     867           3 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     868           3 :     if (ret != 0) return ret;
     869           3 :     KEY_COMPARE(params, static_cast<const BgpAttrParams &>(rhs_attr).params);
     870           1 :     return 0;
     871             : }
     872             : 
     873           3 : void BgpAttrParams::ToCanonical(BgpAttr *attr) {
     874           3 :     attr->set_params(params);
     875           3 : }
     876             : 
     877           1 : string BgpAttrParams::ToString() const {
     878             :     char repr[80];
     879           1 :     snprintf(repr, sizeof(repr), "Params <subcode: %d> : 0x%016jx",
     880           1 :              subcode, params);
     881           1 :     return string(repr);
     882             : }
     883             : 
     884           3 : int BgpAttrSubProtocol::CompareTo(const BgpAttribute &rhs_attr) const {
     885           3 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     886           3 :     if (ret != 0) return ret;
     887           3 :     KEY_COMPARE(sbp, static_cast<const BgpAttrSubProtocol &>(rhs_attr).sbp);
     888           1 :     return 0;
     889             : }
     890             : 
     891       21985 : void BgpAttrSubProtocol::ToCanonical(BgpAttr *attr) {
     892       21985 :     attr->set_sub_protocol(sbp);
     893       21985 : }
     894             : 
     895           1 : string BgpAttrSubProtocol::ToString() const {
     896             :     char repr[80];
     897           1 :     snprintf(repr, sizeof(repr), "SubProtocol <subcode: %d> : %s",
     898           1 :              subcode, sbp.c_str());
     899           1 :     return string(repr);
     900             : }
     901             : 
     902          38 : BgpAttr::BgpAttr()
     903          38 :     : attr_db_(NULL), origin_(BgpAttrOrigin::INCOMPLETE), nexthop_(),
     904          38 :       med_(0), local_pref_(0), atomic_aggregate_(false),
     905          38 :       aggregator_as_num_(0), aggregator_as4_num_(0), params_(0) {
     906          38 :     refcount_ = 0;
     907          38 : }
     908             : 
     909        5953 : BgpAttr::BgpAttr(BgpAttrDB *attr_db)
     910        5953 :     : attr_db_(attr_db), origin_(BgpAttrOrigin::INCOMPLETE),
     911       11906 :       nexthop_(), med_(0), local_pref_(0), atomic_aggregate_(false),
     912        5953 :       aggregator_as_num_(0), aggregator_as4_num_(0), params_(0) {
     913        5953 :     refcount_ = 0;
     914        5953 : }
     915             : 
     916      388825 : BgpAttr::BgpAttr(BgpAttrDB *attr_db, const BgpAttrSpec &spec)
     917      388825 :     : attr_db_(attr_db), origin_(BgpAttrOrigin::INCOMPLETE),
     918      777649 :       nexthop_(), med_(0),
     919      388824 :       local_pref_(BgpAttrLocalPref::kDefault),
     920      388824 :       atomic_aggregate_(false),
     921      388824 :       aggregator_as_num_(0), aggregator_as4_num_(0), 
     922      388825 :       aggregator_address_(), params_(0) {
     923      388807 :     refcount_ = 0;
     924      388831 :     for (vector<BgpAttribute *>::const_iterator it = spec.begin();
     925     1466648 :          it < spec.end(); it++) {
     926     1077794 :         (*it)->ToCanonical(this);
     927             :     }
     928      388814 : }
     929             : 
     930     3040989 : BgpAttr::BgpAttr(const BgpAttr &rhs)
     931     3040989 :     : attr_db_(rhs.attr_db_), origin_(rhs.origin_), nexthop_(rhs.nexthop_),
     932     3040549 :       med_(rhs.med_), local_pref_(rhs.local_pref_),
     933     3040549 :       atomic_aggregate_(rhs.atomic_aggregate_),
     934     3040549 :       aggregator_as_num_(rhs.aggregator_as_num_),
     935     3040549 :       aggregator_as4_num_(rhs.aggregator_as4_num_),
     936     3040549 :       aggregator_address_(rhs.aggregator_address_),
     937     3040345 :       originator_id_(rhs.originator_id_),
     938     3040223 :       source_rd_(rhs.source_rd_), esi_(rhs.esi_), params_(rhs.params_),
     939     3040147 :       as_path_(rhs.as_path_),
     940     3040945 :       aspath_4byte_(rhs.aspath_4byte_),
     941     3040814 :       as4_path_(rhs.as4_path_),
     942     3040644 :       cluster_list_(rhs.cluster_list_),
     943     3040509 :       community_(rhs.community_),
     944     3040412 :       ext_community_(rhs.ext_community_),
     945     3041555 :       large_community_(rhs.large_community_),
     946     3041124 :       deferred_large_spec_(nullptr),
     947     3040296 :       origin_vn_path_(rhs.origin_vn_path_),
     948     3040200 :       pmsi_tunnel_(rhs.pmsi_tunnel_),
     949     3040073 :       edge_discovery_(rhs.edge_discovery_),
     950     3039940 :       edge_forwarding_(rhs.edge_forwarding_),
     951     3039868 :       label_block_(rhs.label_block_),
     952     3039794 :       olist_(rhs.olist_),
     953     3039707 :       leaf_olist_(rhs.leaf_olist_),
     954     6080589 :       sub_protocol_(rhs.sub_protocol_) {
     955     3039366 :     refcount_ = 0;
     956     3041692 : }
     957             : 
     958       19267 : void BgpAttr::set_as_path(AsPathPtr aspath) {
     959       19267 :     as_path_ = aspath;
     960       19267 : }
     961             : 
     962      363132 : void BgpAttr::set_as_path(const AsPathSpec *spec) {
     963      363132 :     if (spec) {
     964      363000 :         as_path_ = attr_db_->server()->aspath_db()->Locate(*spec);
     965             :     } else {
     966         132 :         as_path_ = NULL;
     967             :     }
     968      363221 : }
     969             : 
     970           0 : void BgpAttr::set_as4_path(As4PathPtr aspath) {
     971           0 :     as4_path_ = aspath;
     972           0 : }
     973             : 
     974         495 : void BgpAttr::set_as4_path(const As4PathSpec *spec) {
     975         495 :     if (spec) {
     976         461 :         as4_path_ = attr_db_->server()->as4path_db()->Locate(*spec);
     977             :     } else {
     978          34 :         as4_path_ = NULL;
     979             :     }
     980         495 : }
     981             : 
     982           0 : void BgpAttr::set_aspath_4byte(AsPath4BytePtr aspath) {
     983           0 :     aspath_4byte_ = aspath;
     984           0 : }
     985             : 
     986         556 : void BgpAttr::set_aspath_4byte(const AsPath4ByteSpec *spec) {
     987         556 :     if (spec) {
     988         495 :         aspath_4byte_ = attr_db_->server()->aspath_4byte_db()->Locate(*spec);
     989             :     } else {
     990          61 :         aspath_4byte_ = NULL;
     991             :     }
     992         556 : }
     993             : 
     994      204576 : void BgpAttr::set_cluster_list(const ClusterListSpec *spec) {
     995      204576 :     if (spec) {
     996          18 :         cluster_list_ = attr_db_->server()->cluster_list_db()->Locate(*spec);
     997             :     } else {
     998      204558 :         cluster_list_ = NULL;
     999             :     }
    1000      204575 : }
    1001             : 
    1002       25014 : void BgpAttr::set_community(CommunityPtr comm) {
    1003       25014 :     community_ = comm;
    1004       25014 : }
    1005             : 
    1006        4371 : void BgpAttr::set_community(const CommunitySpec *comm) {
    1007        4371 :     if (comm) {
    1008        4371 :         community_ = attr_db_->server()->comm_db()->Locate(*comm);
    1009             :     } else {
    1010           0 :         community_ = NULL;
    1011             :     }
    1012        4371 : }
    1013             : 
    1014     1013638 : void BgpAttr::set_ext_community(ExtCommunityPtr extcomm) {
    1015     1013638 :     ext_community_ = extcomm;
    1016     1013708 : }
    1017             : 
    1018      183845 : void BgpAttr::set_ext_community(const ExtCommunitySpec *extcomm) {
    1019      183845 :     if (extcomm) {
    1020      183845 :         LargeCommunitySpec large_spec = LargeCommunitySpec::FromTag(*extcomm);
    1021      183842 :         set_large_community(&large_spec);
    1022             :         
    1023      183843 :         if (large_spec.communities.size()) {
    1024             :             ExtCommunitySpec new_comms =
    1025           4 :                 LargeCommunitySpec::RemoveTags(*extcomm);
    1026             :             ext_community_ =
    1027           4 :                 attr_db_->server()->extcomm_db()->Locate(new_comms);
    1028           4 :             return;
    1029           4 :         }
    1030      183839 :         ext_community_ = attr_db_->server()->extcomm_db()->Locate(*extcomm);
    1031      183847 :     } else {
    1032           0 :         ext_community_ = NULL;
    1033             :     }
    1034             : }
    1035             : 
    1036       18971 : void BgpAttr::set_large_community(LargeCommunityPtr largecomm) {
    1037       18971 :     large_community_ = largecomm;
    1038       18971 : }
    1039             : 
    1040      183886 : void BgpAttr::set_large_community(const LargeCommunitySpec *largecomm) {
    1041      183886 :     if (largecomm) {
    1042      183886 :         if (!bool(deferred_large_spec_)) {
    1043      183843 :             deferred_large_spec_.reset(new LargeCommunitySpec);
    1044      183840 :             deferred_large_spec_->communities = largecomm->communities;
    1045             :         } else {
    1046          88 :             deferred_large_spec_->communities.insert(
    1047          88 :                 deferred_large_spec_->communities.end(),
    1048             :                 largecomm->communities.begin(),
    1049             :                 largecomm->communities.end());
    1050             :         }
    1051             :         large_community_ =
    1052      183883 :             attr_db_->server()->largecomm_db()->Locate(*deferred_large_spec_);
    1053             :     } else {
    1054           0 :         large_community_ = NULL;
    1055             :     }
    1056      183887 : }
    1057             : 
    1058       18972 : void BgpAttr::set_origin_vn_path(OriginVnPathPtr ovnpath) {
    1059       18972 :     origin_vn_path_ = ovnpath;
    1060       18972 : }
    1061             : 
    1062         721 : void BgpAttr::set_origin_vn_path(const OriginVnPathSpec *spec) {
    1063         721 :     if (spec) {
    1064         721 :         origin_vn_path_ = attr_db_->server()->ovnpath_db()->Locate(*spec);
    1065             :     } else {
    1066           0 :         origin_vn_path_ = NULL;
    1067             :     }
    1068         721 : }
    1069             : 
    1070       16889 : void BgpAttr::set_pmsi_tunnel(const PmsiTunnelSpec *pmsi_spec) {
    1071       16889 :     if (pmsi_spec) {
    1072       16889 :         pmsi_tunnel_ = attr_db_->server()->pmsi_tunnel_db()->Locate(*pmsi_spec);
    1073             :     } else {
    1074           0 :         pmsi_tunnel_ = NULL;
    1075             :     }
    1076       16889 : }
    1077             : 
    1078        2032 : void BgpAttr::set_edge_discovery(const EdgeDiscoverySpec *edspec) {
    1079        2032 :     if (edspec) {
    1080             :         edge_discovery_ =
    1081        2032 :             attr_db_->server()->edge_discovery_db()->Locate(*edspec);
    1082             :     } else {
    1083           0 :         edge_discovery_ = NULL;
    1084             :     }
    1085        2032 : }
    1086             : 
    1087        3247 : void BgpAttr::set_edge_forwarding(const EdgeForwardingSpec *efspec) {
    1088        3247 :     if (efspec) {
    1089             :         edge_forwarding_ =
    1090        3247 :             attr_db_->server()->edge_forwarding_db()->Locate(*efspec);
    1091             :     } else {
    1092           0 :         edge_forwarding_ = NULL;
    1093             :     }
    1094        3247 : }
    1095             : 
    1096        1034 : void BgpAttr::set_label_block(LabelBlockPtr label_block) {
    1097        1034 :     label_block_ = label_block;
    1098        1034 : }
    1099             : 
    1100        8231 : void BgpAttr::set_olist(const BgpOListSpec *olist_spec) {
    1101        8231 :     if (olist_spec) {
    1102        8231 :         olist_ = attr_db_->server()->olist_db()->Locate(*olist_spec);
    1103             :     } else {
    1104           0 :         olist_ = NULL;
    1105             :     }
    1106        8231 : }
    1107             : 
    1108        4600 : void BgpAttr::set_leaf_olist(const BgpOListSpec *leaf_olist_spec) {
    1109        4600 :     if (leaf_olist_spec) {
    1110        4600 :         leaf_olist_ = attr_db_->server()->olist_db()->Locate(*leaf_olist_spec);
    1111             :     } else {
    1112           0 :         leaf_olist_ = NULL;
    1113             :     }
    1114        4600 : }
    1115             : 
    1116     9337321 : int BgpAttr::max_as_path_count() const {
    1117     9337321 :     int as_count = as_path_count();
    1118     9337296 :     int as4_count = aspath_4byte_count();
    1119     9337292 :     return as_count > as4_count ? as_count : as4_count;
    1120             : }
    1121             : 
    1122      100681 : bool BgpAttr::IsAsPathEmpty() const {
    1123      100681 :     if (as_path_ && !as_path_->empty())
    1124         332 :         return false;
    1125      100350 :     if (aspath_4byte_ && !aspath_4byte_->empty())
    1126          86 :         return false;
    1127      100196 :     return true;
    1128             : }
    1129             : 
    1130        5608 : string BgpAttr::OriginToString(BgpAttrOrigin::OriginType origin) {
    1131        5608 :     switch (origin) {
    1132        5246 :     case BgpAttrOrigin::IGP:
    1133        5246 :         return "igp";
    1134             :         break;
    1135           3 :     case BgpAttrOrigin::EGP:
    1136           3 :         return "egp";
    1137             :         break;
    1138         358 :     case BgpAttrOrigin::INCOMPLETE:
    1139         358 :         return "incomplete";
    1140             :         break;
    1141             :     }
    1142           1 :     return "unknown";
    1143             : }
    1144             : 
    1145       20418 : BgpAttrOrigin::OriginType BgpAttr::OriginFromString(
    1146             :         const string &bgp_origin_type) {
    1147       20418 :     if(bgp_origin_type ==  "IGP"){
    1148       20415 :         return BgpAttrOrigin::IGP;
    1149           3 :     } else if( bgp_origin_type ==  "EGP") {
    1150           2 :         return BgpAttrOrigin::EGP;
    1151             :     }
    1152           1 :     return BgpAttrOrigin::INCOMPLETE;
    1153             : }
    1154             : 
    1155        5605 : string BgpAttr::origin_string() const {
    1156        5605 :     return OriginToString(origin());
    1157             : }
    1158             : 
    1159        2860 : Address::Family BgpAttr::nexthop_family() const {
    1160        2860 :     if (nexthop_.is_v6()) {
    1161         325 :         return Address::INET6;
    1162             :     } else {
    1163        2535 :         return Address::INET;
    1164             :     }
    1165             : }
    1166             : 
    1167     2652109 : as_t BgpAttr::neighbor_as() const {
    1168     2652109 :     if (as_path_.get())
    1169      489680 :         return as_path_->neighbor_as();
    1170     2162419 :     if (aspath_4byte_.get())
    1171         233 :         return aspath_4byte_->neighbor_as();
    1172     2162198 :     return 0;
    1173             : }
    1174             : 
    1175     9429457 : uint32_t BgpAttr::sequence_number() const {
    1176     9429457 :     if (!ext_community_)
    1177     1135713 :         return 0;
    1178     8293785 :     for (ExtCommunity::ExtCommunityList::const_iterator it =
    1179     8293770 :          ext_community_->communities().begin();
    1180    29166178 :          it != ext_community_->communities().end(); ++it) {
    1181    20876614 :         if (ExtCommunity::is_mac_mobility(*it)) {
    1182        4321 :             MacMobility mm(*it);
    1183        4321 :             return mm.sequence_number();
    1184             :         }
    1185             :     }
    1186     8289398 :     return 0;
    1187             : }
    1188             : 
    1189     4714807 : bool BgpAttr::evpn_sticky_mac() const {
    1190     4714807 :     if (!ext_community_)
    1191      567864 :         return 0;
    1192     4146945 :     for (ExtCommunity::ExtCommunityList::const_iterator it =
    1193     4146960 :          ext_community_->communities().begin();
    1194    14583829 :          it != ext_community_->communities().end(); ++it) {
    1195    10439125 :         if (ExtCommunity::is_mac_mobility(*it)) {
    1196        2180 :             MacMobility mm(*it);
    1197        2180 :             return mm.sticky();
    1198             :         }
    1199             :     }
    1200     4144754 :     return 0;
    1201             : }
    1202             : 
    1203     4714880 : bool BgpAttr::etree_leaf() const {
    1204     4714880 :     if (!ext_community_)
    1205      567866 :         return 0;
    1206     4146995 :     for (ExtCommunity::ExtCommunityList::const_iterator it =
    1207     4147000 :          ext_community_->communities().begin();
    1208    14438522 :          it != ext_community_->communities().end(); ++it) {
    1209    10365284 :         if (ExtCommunity::is_etree(*it)) {
    1210       73791 :             ETree etree(*it);
    1211       73797 :             return etree.leaf();
    1212             :         }
    1213             :     }
    1214     4073147 :     return 0;
    1215             : }
    1216             : 
    1217          52 : bool BgpAttr::evpn_single_active() const {
    1218          52 :     if (!ext_community_)
    1219           0 :         return false;
    1220          52 :     for (ExtCommunity::ExtCommunityList::const_iterator it =
    1221          52 :          ext_community_->communities().begin();
    1222         104 :          it != ext_community_->communities().end(); ++it) {
    1223         104 :         if (ExtCommunity::is_esi_label(*it)) {
    1224          52 :             EsiLabel esi_label(*it);
    1225          52 :             return esi_label.single_active();
    1226             :         }
    1227             :     }
    1228           0 :     return true;
    1229             : }
    1230             : 
    1231      463036 : MacAddress BgpAttr::mac_address() const {
    1232      463036 :     if (!ext_community_)
    1233       13548 :         return MacAddress::kZeroMac;
    1234      449464 :     for (ExtCommunity::ExtCommunityList::const_iterator it =
    1235      449482 :          ext_community_->communities().begin();
    1236     3183031 :          it != ext_community_->communities().end(); ++it) {
    1237     2733597 :         if (ExtCommunity::is_router_mac(*it)) {
    1238          22 :             RouterMac router_mac(*it);
    1239          22 :             return router_mac.mac_address();
    1240             :         }
    1241             :     }
    1242      449365 :     return MacAddress::kZeroMac;
    1243             : }
    1244             : 
    1245      439464 : void BgpAttr::Remove() {
    1246      439464 :     attr_db_->Delete(this);
    1247      439465 : }
    1248             : 
    1249      452375 : int BgpAttr::IsAsPathLoop(as_t asn, uint8_t max_loop_count) const {
    1250      452375 :     if (as_path() && as_path()->path().AsPathLoop(asn, max_loop_count)) {
    1251      136352 :         return true;
    1252             :     }
    1253      316234 :     if (aspath_4byte() &&
    1254         199 :            aspath_4byte()->path().AsPathLoop(asn, max_loop_count)) {
    1255          54 :         return true;
    1256             :     }
    1257      315999 :     if (asn > AS2_MAX && as4_path() &&
    1258          20 :            as4_path()->path().AsPathLoop(asn, max_loop_count)) {
    1259           4 :         return true;
    1260             :     }
    1261      315975 :     return false;
    1262             : }
    1263             : 
    1264    25753360 : int BgpAttr::CompareTo(const BgpAttr &rhs) const {
    1265    25753360 :     KEY_COMPARE(origin_, rhs.origin_);
    1266    24029562 :     KEY_COMPARE(nexthop_, rhs.nexthop_);
    1267    16149515 :     KEY_COMPARE(med_, rhs.med_);
    1268    15368418 :     KEY_COMPARE(local_pref_, rhs.local_pref_);
    1269    14971238 :     KEY_COMPARE(atomic_aggregate_, rhs.atomic_aggregate_);
    1270    14971238 :     KEY_COMPARE(aggregator_as_num_, rhs.aggregator_as_num_);
    1271    14971046 :     KEY_COMPARE(aggregator_as4_num_, rhs.aggregator_as4_num_);
    1272    14970918 :     KEY_COMPARE(aggregator_address_, rhs.aggregator_address_);
    1273    14973951 :     KEY_COMPARE(originator_id_, rhs.originator_id_);
    1274    14973607 :     KEY_COMPARE(pmsi_tunnel_.get(), rhs.pmsi_tunnel_.get());
    1275    14619790 :     KEY_COMPARE(edge_discovery_.get(), rhs.edge_discovery_.get());
    1276    14559572 :     KEY_COMPARE(edge_forwarding_.get(), rhs.edge_forwarding_.get());
    1277    14498303 :     KEY_COMPARE(esi_, rhs.esi_);
    1278    14497980 :     KEY_COMPARE(params_, rhs.params_);
    1279    14497975 :     KEY_COMPARE(source_rd_, rhs.source_rd_);
    1280    10439883 :     KEY_COMPARE(label_block_.get(), rhs.label_block_.get());
    1281    10441659 :     KEY_COMPARE(olist_.get(), rhs.olist_.get());
    1282    10383452 :     KEY_COMPARE(leaf_olist_.get(), rhs.leaf_olist_.get());
    1283    10363721 :     KEY_COMPARE(as_path_.get(), rhs.as_path_.get());
    1284    10073277 :     KEY_COMPARE(aspath_4byte_.get(), rhs.aspath_4byte_.get());
    1285    10072154 :     KEY_COMPARE(as4_path_.get(), rhs.as4_path_.get());
    1286    10071186 :     KEY_COMPARE(cluster_list_.get(), rhs.cluster_list_.get());
    1287    10071136 :     KEY_COMPARE(community_.get(), rhs.community_.get());
    1288     9817148 :     KEY_COMPARE(ext_community_.get(), rhs.ext_community_.get());
    1289     7315243 :     KEY_COMPARE(large_community_.get(), rhs.large_community_.get());
    1290     7300464 :     KEY_COMPARE(origin_vn_path_.get(), rhs.origin_vn_path_.get());
    1291     7223613 :     KEY_COMPARE(sub_protocol_, rhs.sub_protocol_);
    1292     7207702 :     return 0;
    1293             : }
    1294             : 
    1295           0 : std::size_t hash_value(BgpAttr const &attr) {
    1296           0 :     size_t hash = 0;
    1297             : 
    1298           0 :     boost::hash_combine(hash, attr.origin_);
    1299           0 :     boost::hash_combine(hash, attr.nexthop_.to_string());
    1300           0 :     boost::hash_combine(hash, attr.med_);
    1301           0 :     boost::hash_combine(hash, attr.local_pref_);
    1302           0 :     boost::hash_combine(hash, attr.atomic_aggregate_);
    1303           0 :     boost::hash_combine(hash, attr.aggregator_as_num_);
    1304           0 :     boost::hash_combine(hash, attr.aggregator_as4_num_);
    1305           0 :     boost::hash_combine(hash, attr.aggregator_address_.to_string());
    1306           0 :     boost::hash_combine(hash, attr.originator_id_.to_string());
    1307           0 :     boost::hash_combine(hash, attr.params_);
    1308           0 :     boost::hash_combine(hash, attr.source_rd_.ToString());
    1309           0 :     boost::hash_combine(hash, attr.esi_.ToString());
    1310             : 
    1311           0 :     if (attr.label_block_) {
    1312           0 :         boost::hash_combine(hash, attr.label_block_->first());
    1313           0 :         boost::hash_combine(hash, attr.label_block_->last());
    1314             :     }
    1315             : 
    1316           0 :     if (attr.olist_) {
    1317           0 :         boost::hash_range(hash, attr.olist_->elements().begin(),
    1318           0 :                           attr.olist_->elements().end());
    1319             :     }
    1320           0 :     if (attr.leaf_olist_) {
    1321           0 :         boost::hash_range(hash, attr.leaf_olist_->elements().begin(),
    1322           0 :                           attr.leaf_olist_->elements().end());
    1323             :     }
    1324             : 
    1325           0 :     if (attr.as_path_) boost::hash_combine(hash, *attr.as_path_);
    1326           0 :     if (attr.aspath_4byte_) boost::hash_combine(hash, *attr.aspath_4byte_);
    1327           0 :     if (attr.as4_path_) boost::hash_combine(hash, *attr.as4_path_);
    1328           0 :     if (attr.community_) boost::hash_combine(hash, *attr.community_);
    1329           0 :     if (attr.ext_community_) boost::hash_combine(hash, *attr.ext_community_);
    1330           0 :     if (attr.large_community_) boost::hash_combine(hash, *attr.large_community_);
    1331           0 :     if (attr.origin_vn_path_) boost::hash_combine(hash, *attr.origin_vn_path_);
    1332           0 :     if (!attr.sub_protocol_.empty()) {
    1333           0 :         boost::hash_combine(hash, attr.sub_protocol_);
    1334             :     }
    1335             : 
    1336           0 :     return hash;
    1337             : }
    1338             : 
    1339        9743 : BgpAttrDB::BgpAttrDB(BgpServer *server) : server_(server) {
    1340        9743 : }
    1341             : 
    1342             : // Return a clone of attribute with updated aspath.
    1343       19267 : BgpAttrPtr BgpAttrDB::ReplaceAsPathAndLocate(const BgpAttr *attr,
    1344             :                                              AsPathPtr aspath) {
    1345       19267 :     BgpAttr *clone = new BgpAttr(*attr);
    1346       19267 :     clone->set_as_path(aspath);
    1347       19267 :     return Locate(clone);
    1348             : }
    1349             : 
    1350             : // Return a clone of attribute with updated community.
    1351       19297 : BgpAttrPtr BgpAttrDB::ReplaceCommunityAndLocate(const BgpAttr *attr,
    1352             :                                                 CommunityPtr community) {
    1353       19297 :     BgpAttr *clone = new BgpAttr(*attr);
    1354       19297 :     clone->set_community(community);
    1355       19297 :     return Locate(clone);
    1356             : }
    1357             : 
    1358             : //Return a clone of attribute with updated origin
    1359           4 : BgpAttrPtr BgpAttrDB::ReplaceOriginAndLocate(const BgpAttr *attr,
    1360             :                                              BgpAttrOrigin::OriginType origin) {
    1361           4 :     BgpAttr *clone = new BgpAttr(*attr);
    1362           4 :     clone->set_origin(origin);
    1363           4 :     return Locate(clone);
    1364             : }
    1365             : 
    1366             : // Return a clone of attribute with updated extended community.
    1367     1013641 : BgpAttrPtr BgpAttrDB::ReplaceExtCommunityAndLocate(const BgpAttr *attr,
    1368             :                                                    ExtCommunityPtr extcomm) {
    1369     1013641 :     BgpAttr *clone = new BgpAttr(*attr);
    1370     1013696 :     clone->set_ext_community(extcomm);
    1371     1013693 :     return Locate(clone);
    1372             : }
    1373             : 
    1374             : // Return a clone of attribute with updated large community.
    1375       18971 : BgpAttrPtr BgpAttrDB::ReplaceLargeCommunityAndLocate(
    1376             :     const BgpAttr *attr, LargeCommunityPtr largecomm) {
    1377       18971 :     BgpAttr *clone = new BgpAttr(*attr);
    1378       18971 :     clone->set_large_community(largecomm);
    1379       18971 :     return Locate(clone);
    1380             : }
    1381             : 
    1382             : // Return a clone of attribute with updated origin vn path.
    1383       18972 : BgpAttrPtr BgpAttrDB::ReplaceOriginVnPathAndLocate(const BgpAttr *attr,
    1384             :                                                    OriginVnPathPtr ovnpath) {
    1385       18972 :     BgpAttr *clone = new BgpAttr(*attr);
    1386       18972 :     clone->set_origin_vn_path(ovnpath);
    1387       18972 :     return Locate(clone);
    1388             : }
    1389             : 
    1390             : // Return a clone of attribute with updated local preference.
    1391          18 : BgpAttrPtr BgpAttrDB::ReplaceLocalPreferenceAndLocate(const BgpAttr *attr,
    1392             :                                                       uint32_t local_pref) {
    1393          18 :     BgpAttr *clone = new BgpAttr(*attr);
    1394          18 :     clone->set_local_pref(local_pref);
    1395          18 :     return Locate(clone);
    1396             : }
    1397             : 
    1398             : // Return a clone of attribute with updated originator id.
    1399           1 : BgpAttrPtr BgpAttrDB::ReplaceOriginatorIdAndLocate(const BgpAttr *attr,
    1400             :                                                    Ip4Address originator_id) {
    1401           1 :     BgpAttr *clone = new BgpAttr(*attr);
    1402           1 :     clone->set_originator_id(originator_id);
    1403           1 :     return Locate(clone);
    1404             : }
    1405             : 
    1406             : // Return a clone of attribute with updated source rd.
    1407      612744 : BgpAttrPtr BgpAttrDB::ReplaceSourceRdAndLocate(const BgpAttr *attr,
    1408             :     const RouteDistinguisher &source_rd) {
    1409      612744 :     BgpAttr *clone = new BgpAttr(*attr);
    1410      612775 :     clone->set_source_rd(source_rd);
    1411      612761 :     return Locate(clone);
    1412             : }
    1413             : 
    1414             : // Return a clone of attribute with updated esi.
    1415       17817 : BgpAttrPtr BgpAttrDB::ReplaceEsiAndLocate(const BgpAttr *attr,
    1416             :                                           const EthernetSegmentId &esi) {
    1417       17817 :     BgpAttr *clone = new BgpAttr(*attr);
    1418       17817 :     clone->set_esi(esi);
    1419       17817 :     return Locate(clone);
    1420             : }
    1421             : 
    1422             : // Return a clone of attribute with updated olist.
    1423        4756 : BgpAttrPtr BgpAttrDB::ReplaceOListAndLocate(const BgpAttr *attr,
    1424             :     const BgpOListSpec *olist_spec) {
    1425        4756 :     assert(olist_spec->subcode == BgpAttribute::OList);
    1426        4756 :     BgpAttr *clone = new BgpAttr(*attr);
    1427        4756 :     clone->set_olist(olist_spec);
    1428        4756 :     return Locate(clone);
    1429             : }
    1430             : 
    1431             : // Return a clone of attribute with updated leaf olist.
    1432        4600 : BgpAttrPtr BgpAttrDB::ReplaceLeafOListAndLocate(const BgpAttr *attr,
    1433             :     const BgpOListSpec *leaf_olist_spec) {
    1434        4600 :     assert(leaf_olist_spec->subcode == BgpAttribute::LeafOList);
    1435        4600 :     BgpAttr *clone = new BgpAttr(*attr);
    1436        4600 :     clone->set_leaf_olist(leaf_olist_spec);
    1437        4600 :     return Locate(clone);
    1438             : }
    1439             : 
    1440             : // Return a clone of attribute with updated sub-protocol.
    1441        2054 : BgpAttrPtr BgpAttrDB::ReplaceSubProtocolAndLocate(const BgpAttr *attr,
    1442             :     const string &sbp) {
    1443        2054 :     BgpAttr *clone = new BgpAttr(*attr);
    1444        2054 :     clone->set_sub_protocol(sbp);
    1445        2054 :     return Locate(clone);
    1446             : }
    1447             : 
    1448             : 
    1449             : // Return a clone of attribute with updated pmsi tunnel.
    1450        8757 : BgpAttrPtr BgpAttrDB::ReplacePmsiTunnelAndLocate(const BgpAttr *attr,
    1451             :     const PmsiTunnelSpec *pmsi_spec) {
    1452        8757 :     BgpAttr *clone = new BgpAttr(*attr);
    1453        8757 :     clone->set_pmsi_tunnel(pmsi_spec);
    1454        8757 :     return Locate(clone);
    1455             : }
    1456             : 
    1457             : // Return a clone of attribute with updated nexthop.
    1458      339467 : BgpAttrPtr BgpAttrDB::ReplaceNexthopAndLocate(const BgpAttr *attr,
    1459             :     const IpAddress &addr) {
    1460      339467 :     BgpAttr *clone = new BgpAttr(*attr);
    1461      339476 :     clone->set_nexthop(addr);
    1462      339470 :     return Locate(clone);
    1463             : }

Generated by: LCOV version 1.14