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: 199 992 20.1 %
Date: 2026-09-28 02:13:17 Functions: 37 182 20.3 %
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           0 : int BgpAttrOrigin::CompareTo(const BgpAttribute &rhs_attr) const {
      22           0 :     int ret = BgpAttribute::CompareTo(rhs_attr);
      23           0 :     if (ret != 0) return ret;
      24           0 :     KEY_COMPARE(origin, static_cast<const BgpAttrOrigin &>(rhs_attr).origin);
      25           0 :     return 0;
      26             : }
      27             : 
      28         318 : void BgpAttrOrigin::ToCanonical(BgpAttr *attr) {
      29         318 :     attr->set_origin(static_cast<BgpAttrOrigin::OriginType>(origin));
      30         318 : }
      31             : 
      32          30 : string BgpAttrOrigin::ToString() const {
      33             :     char repr[80];
      34          30 :     snprintf(repr, sizeof(repr), "ORIGIN <code: %d, flags: %02x> : %02x",
      35          30 :              code, flags, origin);
      36          30 :     return string(repr);
      37             : }
      38             : 
      39           0 : int BgpAttrNextHop::CompareTo(const BgpAttribute &rhs_attr) const {
      40           0 :     int ret = BgpAttribute::CompareTo(rhs_attr);
      41           0 :     if (ret != 0) return ret;
      42           0 :     KEY_COMPARE(nexthop,
      43             :             static_cast<const BgpAttrNextHop &>(rhs_attr).nexthop);
      44           0 :     return 0;
      45             : }
      46             : 
      47         314 : void BgpAttrNextHop::ToCanonical(BgpAttr *attr) {
      48         314 :     if (v6_nexthop.is_unspecified()) {
      49         314 :         attr->set_nexthop(Ip4Address(nexthop));
      50             :     } else {
      51           0 :         attr->set_nexthop(v6_nexthop);
      52             :     }
      53         314 : }
      54             : 
      55          24 : string BgpAttrNextHop::ToString() const {
      56             :     char repr[80];
      57          24 :     snprintf(repr, sizeof(repr), "NEXTHOP <code: %d, flags: %02x> : %04x",
      58          24 :              code, flags, nexthop);
      59          24 :     return string(repr);
      60             : }
      61             : 
      62           0 : int BgpAttrMultiExitDisc::CompareTo(const BgpAttribute &rhs_attr) const {
      63           0 :     int ret = BgpAttribute::CompareTo(rhs_attr);
      64           0 :     if (ret != 0) return ret;
      65           0 :     KEY_COMPARE(med, static_cast<const BgpAttrMultiExitDisc &>(rhs_attr).med);
      66           0 :     return 0;
      67             : }
      68           0 : void BgpAttrMultiExitDisc::ToCanonical(BgpAttr *attr) {
      69           0 :     attr->set_med(med);
      70           0 : }
      71             : 
      72           0 : string BgpAttrMultiExitDisc::ToString() const {
      73             :     char repr[80];
      74           0 :     snprintf(repr, sizeof(repr), "MED <code: %d, flags: %02x> : %d",
      75           0 :              code, flags, med);
      76           0 :     return string(repr);
      77             : }
      78             : 
      79           0 : int BgpAttrLocalPref::CompareTo(const BgpAttribute &rhs_attr) const {
      80           0 :     int ret = BgpAttribute::CompareTo(rhs_attr);
      81           0 :     if (ret != 0) return ret;
      82           0 :     KEY_COMPARE(local_pref,
      83             :             static_cast<const BgpAttrLocalPref &>(rhs_attr).local_pref);
      84           0 :     return 0;
      85             : }
      86          48 : void BgpAttrLocalPref::ToCanonical(BgpAttr *attr) {
      87          48 :     attr->set_local_pref(local_pref);
      88          48 : }
      89             : 
      90          30 : string BgpAttrLocalPref::ToString() const {
      91             :     char repr[80];
      92          30 :     snprintf(repr, sizeof(repr), "LOCAL_PREF <code: %d, flags: %02x> : %d",
      93          30 :              code, flags, local_pref);
      94          30 :     return string(repr);
      95             : }
      96             : 
      97           0 : void BgpAttrAtomicAggregate::ToCanonical(BgpAttr *attr) {
      98           0 :     attr->set_atomic_aggregate(true);
      99           0 : }
     100             : 
     101           0 : string BgpAttrAtomicAggregate::ToString() const {
     102             :     char repr[80];
     103           0 :     snprintf(repr, sizeof(repr), "ATOMIC_AGGR <code: %d, flags: %02x>",
     104           0 :              code, flags);
     105           0 :     return string(repr);
     106             : }
     107             : 
     108           0 : int BgpAttr4ByteAggregator::CompareTo(const BgpAttribute &rhs_attr) const {
     109           0 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     110           0 :     if (ret != 0) return ret;
     111           0 :     KEY_COMPARE(as_num,
     112             :             static_cast<const BgpAttr4ByteAggregator &>(rhs_attr).as_num);
     113           0 :     KEY_COMPARE(address,
     114             :             static_cast<const BgpAttr4ByteAggregator &>(rhs_attr).address);
     115           0 :     return 0;
     116             : }
     117           0 : void BgpAttr4ByteAggregator::ToCanonical(BgpAttr *attr) {
     118           0 :     attr->set_aggregator(as_num, Ip4Address(address));
     119           0 : }
     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           0 : int BgpAttrAggregator::CompareTo(const BgpAttribute &rhs_attr) const {
     130           0 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     131           0 :     if (ret != 0) return ret;
     132           0 :     KEY_COMPARE(as_num,
     133             :             static_cast<const BgpAttrAggregator &>(rhs_attr).as_num);
     134           0 :     KEY_COMPARE(address,
     135             :             static_cast<const BgpAttrAggregator &>(rhs_attr).address);
     136           0 :     return 0;
     137             : }
     138           0 : void BgpAttrAggregator::ToCanonical(BgpAttr *attr) {
     139           0 :     attr->set_aggregator(as_num, Ip4Address(address));
     140           0 : }
     141             : 
     142           0 : string BgpAttrAggregator::ToString() const {
     143             :     char repr[80];
     144           0 :     snprintf(repr, sizeof(repr),
     145             :              "Aggregator <code: %d, flags: %02x> : %d:%08x",
     146           0 :              code, flags, as_num, address);
     147           0 :     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           0 : int BgpAttrOriginatorId::CompareTo(const BgpAttribute &rhs_attr) const {
     172           0 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     173           0 :     if (ret != 0) return ret;
     174           0 :     KEY_COMPARE(originator_id,
     175             :         static_cast<const BgpAttrOriginatorId &>(rhs_attr).originator_id);
     176           0 :     return 0;
     177             : }
     178             : 
     179           2 : void BgpAttrOriginatorId::ToCanonical(BgpAttr *attr) {
     180           2 :     attr->set_originator_id(Ip4Address(originator_id));
     181           2 : }
     182             : 
     183           2 : string BgpAttrOriginatorId::ToString() const {
     184             :     char repr[80];
     185           2 :     snprintf(repr, sizeof(repr), "OriginatorId <code: %d, flags: 0x%02x> : %s",
     186           4 :              code, flags, Ip4Address(originator_id).to_string().c_str());
     187           2 :     return string(repr);
     188             : }
     189             : 
     190           2 : ClusterListSpec::ClusterListSpec(uint32_t cluster_id,
     191           2 :     const ClusterListSpec *rhs)
     192           2 :     : BgpAttribute(BgpAttribute::ClusterList, kFlags) {
     193           2 :     cluster_list.push_back(cluster_id);
     194           2 :     if (rhs) {
     195           0 :         cluster_list.insert(cluster_list.end(), rhs->cluster_list.begin(),
     196             :             rhs->cluster_list.end());
     197             :     }
     198           2 : }
     199             : 
     200           8 : int ClusterListSpec::CompareTo(const BgpAttribute &rhs_attr) const {
     201           8 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     202           8 :     if (ret != 0) return ret;
     203           8 :     KEY_COMPARE(cluster_list,
     204             :         static_cast<const ClusterListSpec &>(rhs_attr).cluster_list);
     205           8 :     return 0;
     206             : }
     207             : 
     208           2 : void ClusterListSpec::ToCanonical(BgpAttr *attr) {
     209           2 :     attr->set_cluster_list(this);
     210           2 : }
     211             : 
     212           2 : string ClusterListSpec::ToString() const {
     213           2 :     std::stringstream repr;
     214           2 :     repr << "CLUSTER_LIST <code: " << int(code);
     215           2 :     repr << ", flags: 0x" << std::hex << int(flags) << "> :";
     216           2 :     for (vector<uint32_t>::const_iterator iter = cluster_list.begin();
     217           4 :          iter != cluster_list.end(); ++iter) {
     218           2 :         repr << " " << Ip4Address(*iter).to_string();
     219             :     }
     220           4 :     return repr.str();
     221           2 : }
     222             : 
     223           0 : bool ClusterListSpec::ClusterListLoop(uint32_t cluster_id) const {
     224           0 :     for (vector<uint32_t>::const_iterator iter = cluster_list.begin();
     225           0 :          iter != cluster_list.end(); ++iter) {
     226           0 :         if (*iter == cluster_id)
     227           0 :             return true;
     228             :     }
     229           0 :     return false;
     230             : }
     231             : 
     232           4 : ClusterList::ClusterList(ClusterListDB *cluster_list_db,
     233           4 :     const ClusterListSpec &spec)
     234           4 :     : cluster_list_db_(cluster_list_db),
     235           4 :       spec_(spec) {
     236           4 :     refcount_ = 0;
     237           4 : }
     238             : 
     239           4 : void ClusterList::Remove() {
     240           4 :     cluster_list_db_->Delete(this);
     241           4 : }
     242             : 
     243         378 : ClusterListDB::ClusterListDB(BgpServer *server) {
     244         378 : }
     245             : 
     246           0 : int BgpMpNlri::CompareTo(const BgpAttribute &rhs_attr) const {
     247           0 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     248           0 :     if (ret != 0) return ret;
     249           0 :     const BgpMpNlri &rhs = static_cast<const BgpMpNlri &>(rhs_attr);
     250           0 :     KEY_COMPARE(afi, rhs.afi);
     251           0 :     KEY_COMPARE(safi, rhs.safi);
     252           0 :     KEY_COMPARE(nexthop, rhs.nexthop);
     253           0 :     KEY_COMPARE(nlri.size(), rhs.nlri.size());
     254             : 
     255           0 :     for (size_t i = 0; i < nlri.size(); i++) {
     256           0 :         KEY_COMPARE(nlri[i]->type, rhs.nlri[i]->type);
     257           0 :         KEY_COMPARE(nlri[i]->prefixlen, rhs.nlri[i]->prefixlen);
     258           0 :         KEY_COMPARE(nlri[i]->prefix, rhs.nlri[i]->prefix);
     259             :     }
     260           0 :     return 0;
     261             : }
     262             : 
     263        1091 : void BgpMpNlri::ToCanonical(BgpAttr *attr) {
     264        1091 : }
     265             : 
     266        3323 : size_t BgpMpNlri::EncodeLength() const {
     267        3323 :     size_t sz = 2 /* safi */ + 1 /* afi */ +
     268             :                 1 /* NlriNextHopLength */ +
     269             :                 1 /* Reserved */;
     270        3323 :     sz += nexthop.size();
     271        3323 :     for (vector<BgpProtoPrefix*>::const_iterator iter = nlri.begin();
     272        3401 :          iter != nlri.end(); ++iter) {
     273          78 :         size_t bytes = 0;
     274          78 :         if (afi == BgpAf::L2Vpn &&
     275           0 :             (safi == BgpAf::EVpn || safi == BgpAf::ErmVpn)) {
     276           0 :             bytes = (*iter)->prefixlen;
     277             :         } else {
     278          78 :             bytes = ((*iter)->prefixlen + 7) / 8;
     279             :         }
     280          78 :         sz += 1 + bytes;
     281             :     }
     282        3324 :     return sz;
     283             : }
     284             : 
     285           0 : PmsiTunnelSpec::PmsiTunnelSpec()
     286             :     : BgpAttribute(PmsiTunnel, kFlags),
     287           0 :       tunnel_flags(0), tunnel_type(0), label(0) {
     288           0 : }
     289             : 
     290           0 : PmsiTunnelSpec::PmsiTunnelSpec(const BgpAttribute &rhs)
     291           0 :     : BgpAttribute(rhs), tunnel_flags(0), tunnel_type(0), label(0) {
     292           0 : }
     293             : 
     294           0 : int PmsiTunnelSpec::CompareTo(const BgpAttribute &rhs_attr) const {
     295           0 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     296           0 :     if (ret != 0) return ret;
     297           0 :     const PmsiTunnelSpec &rhs = static_cast<const PmsiTunnelSpec &>(rhs_attr);
     298           0 :     KEY_COMPARE(tunnel_flags, rhs.tunnel_flags);
     299           0 :     KEY_COMPARE(tunnel_type, rhs.tunnel_type);
     300           0 :     KEY_COMPARE(label, rhs.label);
     301           0 :     KEY_COMPARE(identifier, rhs.identifier);
     302           0 :     return 0;
     303             : }
     304             : 
     305           0 : void PmsiTunnelSpec::ToCanonical(BgpAttr *attr) {
     306           0 :     attr->set_pmsi_tunnel(this);
     307           0 : }
     308             : 
     309           0 : string PmsiTunnelSpec::ToString() const {
     310           0 :     std::ostringstream oss;
     311           0 :     oss << "PmsiTunnel <code: " << int(code);
     312           0 :     oss << ", flags: 0x" << std::hex << int(flags) << std::dec << ">";
     313           0 :     oss << " Tunnel Flags: 0x" << std::hex << int(tunnel_flags) << std::dec;
     314           0 :     oss << " Tunnel Type: " << int(tunnel_type);
     315           0 :     oss << " Label: 0x" << std::hex << int(label) << std::dec;
     316           0 :     oss << " (" << int(label) << ")";
     317           0 :     oss << " Identifier: " << GetIdentifier().to_string();
     318             : 
     319           0 :     return oss.str();
     320           0 : }
     321             : 
     322           0 : uint32_t PmsiTunnelSpec::GetLabel(const ExtCommunity *ext) const {
     323           0 :     assert(ext);
     324           0 :     bool is_vni = ext->ContainsTunnelEncapVxlan();
     325           0 :     return (is_vni ? label : (label >> 4));
     326             : }
     327             : 
     328           0 : void PmsiTunnelSpec::SetLabel(uint32_t in_label, const ExtCommunity *ext) {
     329           0 :     assert(ext);
     330           0 :     bool is_vni = ext->ContainsTunnelEncapVxlan();
     331           0 :     label = (is_vni ? in_label : (in_label << 4 | 0x01));
     332           0 : }
     333             : 
     334           0 : Ip4Address PmsiTunnelSpec::GetIdentifier() const {
     335           0 :     if (identifier.size() < 4)
     336           0 :         return Ip4Address();
     337           0 :     return Ip4Address(get_value(&identifier[0], 4));
     338             : }
     339             : 
     340           0 : void PmsiTunnelSpec::SetIdentifier(Ip4Address in_identifier) {
     341           0 :     identifier.resize(4, 0);
     342           0 :     const Ip4Address::bytes_type &bytes = in_identifier.to_bytes();
     343           0 :     std::copy(bytes.begin(), bytes.begin() + 4, identifier.begin());
     344           0 : }
     345             : 
     346           0 : string PmsiTunnelSpec::GetTunnelTypeString() const {
     347           0 :     switch (tunnel_type) {
     348           0 :     case RsvpP2mpLsp:
     349           0 :         return "RsvpP2mpLsp";
     350           0 :     case LdpP2mpLsp:
     351           0 :         return "LdpP2mpLsp";
     352           0 :     case PimSsmTree:
     353           0 :         return "PimSsmTree";
     354           0 :     case PimSmTree:
     355           0 :         return "PimSmTree";
     356           0 :     case BidirPimTree:
     357           0 :         return "BidirPimTree";
     358           0 :     case IngressReplication:
     359           0 :         return "IngressReplication";
     360           0 :     case MldpMp2mpLsp:
     361           0 :         return "MldpMp2mpLsp";
     362           0 :     case AssistedReplicationContrail:
     363           0 :         return "AssistedReplication";
     364           0 :     default:
     365           0 :         break;
     366             :     }
     367           0 :     std::ostringstream oss;
     368           0 :     oss << "Unknown(" << int(tunnel_type) << ")";
     369           0 :     return oss.str();
     370             : }
     371             : 
     372           0 : string PmsiTunnelSpec::GetTunnelArTypeString() const {
     373           0 :     switch (tunnel_flags & AssistedReplicationType) {
     374           0 :     case RegularNVE:
     375           0 :         return "RegularNVE";
     376           0 :     case ARReplicator:
     377           0 :         return "ARReplicator";
     378           0 :     case ARLeaf:
     379           0 :         return "ARLeaf";
     380           0 :     default:
     381           0 :         break;
     382             :     }
     383           0 :     return "Unknown";
     384             : }
     385             : 
     386           0 : vector<string> PmsiTunnelSpec::GetTunnelFlagsStrings() const {
     387           0 :     vector<string> flags;
     388           0 :     if (tunnel_flags & LeafInfoRequired) {
     389           0 :         flags.push_back("LeafInfoRequired");
     390             :     }
     391           0 :     if (tunnel_flags & EdgeReplicationSupported) {
     392           0 :         flags.push_back("EdgeReplicationSupported");
     393             :     }
     394           0 :     if (flags.empty()) {
     395           0 :         flags.push_back("None");
     396             :     }
     397           0 :     return flags;
     398           0 : }
     399             : 
     400           0 : PmsiTunnel::PmsiTunnel(PmsiTunnelDB *pmsi_tunnel_db,
     401           0 :     const PmsiTunnelSpec &pmsi_spec)
     402           0 :     : pmsi_tunnel_db_(pmsi_tunnel_db),
     403           0 :       pmsi_spec_(pmsi_spec) {
     404           0 :     refcount_ = 0;
     405           0 :     tunnel_flags_ = pmsi_spec_.tunnel_flags;
     406           0 :     tunnel_type_ = pmsi_spec_.tunnel_type;
     407           0 :     label_ = pmsi_spec_.label;
     408           0 :     identifier_ = pmsi_spec_.GetIdentifier();
     409           0 : }
     410             : 
     411           0 : void PmsiTunnel::Remove() {
     412           0 :     pmsi_tunnel_db_->Delete(this);
     413           0 : }
     414             : 
     415           0 : uint32_t PmsiTunnel::GetLabel(const ExtCommunity *ext) const {
     416           0 :     bool is_vni = false;
     417           0 :     if (ext)
     418           0 :         is_vni = ext->ContainsTunnelEncapVxlan();
     419           0 :     return (is_vni ? label_ : label_ >> 4);
     420             : }
     421             : 
     422         378 : PmsiTunnelDB::PmsiTunnelDB(BgpServer *server) {
     423         378 : }
     424             : 
     425           0 : EdgeDiscoverySpec::EdgeDiscoverySpec()
     426           0 :     : BgpAttribute(McastEdgeDiscovery, kFlags) {
     427           0 : }
     428             : 
     429           0 : EdgeDiscoverySpec::EdgeDiscoverySpec(const BgpAttribute &rhs)
     430           0 :     : BgpAttribute(rhs) {
     431           0 : }
     432             : 
     433           0 : EdgeDiscoverySpec::EdgeDiscoverySpec(const EdgeDiscoverySpec &rhs)
     434           0 :     : BgpAttribute(BgpAttribute::McastEdgeDiscovery, kFlags) {
     435           0 :     for (size_t i = 0; i < rhs.edge_list.size(); i++) {
     436           0 :         Edge *edge = new Edge;
     437           0 :         *edge = *rhs.edge_list[i];
     438           0 :         edge_list.push_back(edge);
     439             :     }
     440           0 : }
     441             : 
     442           0 : EdgeDiscoverySpec::~EdgeDiscoverySpec() {
     443           0 :     STLDeleteValues(&edge_list);
     444           0 : }
     445             : 
     446           0 : Ip4Address EdgeDiscoverySpec::Edge::GetIp4Address() const {
     447           0 :     return Ip4Address(get_value(&address[0], 4));
     448             : }
     449             : 
     450           0 : void EdgeDiscoverySpec::Edge::SetIp4Address(Ip4Address addr) {
     451           0 :     address.resize(4, 0);
     452           0 :     const Ip4Address::bytes_type &addr_bytes = addr.to_bytes();
     453           0 :     std::copy(addr_bytes.begin(), addr_bytes.begin() + 4, address.begin());
     454           0 : }
     455             : 
     456           0 : void EdgeDiscoverySpec::Edge::GetLabels(
     457             :     uint32_t *first_label, uint32_t *last_label) const {
     458           0 :     *first_label = labels[0];
     459           0 :     *last_label = labels[1];
     460           0 : }
     461             : 
     462           0 : void EdgeDiscoverySpec::Edge::SetLabels(
     463             :     uint32_t first_label, uint32_t last_label) {
     464           0 :     labels.push_back(first_label);
     465           0 :     labels.push_back(last_label);
     466           0 : }
     467             : 
     468             : struct EdgeDiscoverySpecEdgeCompare {
     469           0 :     int operator()(const EdgeDiscoverySpec::Edge *lhs,
     470             :                    const EdgeDiscoverySpec::Edge *rhs) const {
     471           0 :         KEY_COMPARE(lhs->address, rhs->address);
     472           0 :         KEY_COMPARE(lhs->labels, rhs->labels);
     473           0 :         return 0;
     474             :     }
     475             : };
     476             : 
     477           0 : int EdgeDiscoverySpec::CompareTo(const BgpAttribute &rhs_attr) const {
     478           0 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     479           0 :     if (ret != 0) return ret;
     480           0 :     const EdgeDiscoverySpec &rhs =
     481             :             static_cast<const EdgeDiscoverySpec &>(rhs_attr);
     482           0 :     ret = STLSortedCompare(edge_list.begin(), edge_list.end(),
     483             :                            rhs.edge_list.begin(), rhs.edge_list.end(),
     484             :                            EdgeDiscoverySpecEdgeCompare());
     485           0 :     return ret;
     486             : }
     487             : 
     488           0 : void EdgeDiscoverySpec::ToCanonical(BgpAttr *attr) {
     489           0 :     attr->set_edge_discovery(this);
     490           0 : }
     491             : 
     492           0 : string EdgeDiscoverySpec::ToString() const {
     493           0 :     std::ostringstream oss;
     494           0 :     oss << "EdgeDiscovery <code: " << int(code);
     495           0 :     oss << ", flags: 0x" << std::hex << int(flags) << std::dec << ">";
     496           0 :     int idx = 0;
     497           0 :     for (EdgeList::const_iterator it = edge_list.begin();
     498           0 :          it != edge_list.end(); ++it, ++idx) {
     499           0 :         const Edge *edge = *it;
     500             :         uint32_t first_label, last_label;
     501           0 :         edge->GetLabels(&first_label, &last_label);
     502           0 :         oss << " Edge[" << idx << "] = (" << edge->GetIp4Address() << ", ";
     503           0 :         oss << first_label << "-" << last_label << ")";
     504             :     }
     505             : 
     506           0 :     return oss.str();
     507           0 : }
     508             : 
     509           0 : size_t EdgeDiscoverySpec::EncodeLength() const {
     510           0 :     size_t sz = 0;
     511           0 :     for (EdgeList::const_iterator iter = edge_list.begin();
     512           0 :          iter != edge_list.end(); ++iter) {
     513           0 :         sz += 2; /* AddressLen + LabelLen */
     514           0 :         sz += (*iter)->address.size();
     515           0 :         sz += (*iter)->labels.size() * sizeof(uint32_t);
     516             :     }
     517           0 :     return sz;
     518             : }
     519             : 
     520           0 : EdgeDiscovery::Edge::Edge(const EdgeDiscoverySpec::Edge *spec_edge) {
     521           0 :     address = spec_edge->GetIp4Address();
     522             :     uint32_t first_label, last_label;
     523           0 :     spec_edge->GetLabels(&first_label, &last_label);
     524           0 :     label_block = new LabelBlock(first_label, last_label);
     525           0 : }
     526             : 
     527           0 : bool EdgeDiscovery::Edge::operator<(const Edge &rhs) const {
     528           0 :     BOOL_KEY_COMPARE(address, rhs.address);
     529           0 :     BOOL_KEY_COMPARE(label_block->first(), rhs.label_block->first());
     530           0 :     BOOL_KEY_COMPARE(label_block->last(), rhs.label_block->last());
     531           0 :     return false;
     532             : }
     533             : 
     534           0 : EdgeDiscovery::EdgeDiscovery(EdgeDiscoveryDB *edge_discovery_db,
     535           0 :     const EdgeDiscoverySpec &edspec)
     536           0 :     : edge_discovery_db_(edge_discovery_db),
     537           0 :       edspec_(edspec) {
     538           0 :     refcount_ = 0;
     539           0 :     for (EdgeDiscoverySpec::EdgeList::const_iterator it =
     540           0 :          edspec_.edge_list.begin(); it != edspec_.edge_list.end(); ++it) {
     541           0 :         Edge *edge = new Edge(*it);
     542           0 :         edge_list.push_back(edge);
     543             :     }
     544           0 :     sort(edge_list.begin(), edge_list.end(), EdgeDiscovery::EdgeCompare());
     545           0 : }
     546             : 
     547           0 : EdgeDiscovery::~EdgeDiscovery() {
     548           0 :     STLDeleteValues(&edge_list);
     549           0 : }
     550             : 
     551             : struct EdgeDiscoveryEdgeCompare {
     552           0 :     int operator()(const EdgeDiscovery::Edge *lhs,
     553             :                    const EdgeDiscovery::Edge *rhs) const {
     554           0 :         KEY_COMPARE(*lhs, *rhs);
     555           0 :         return 0;
     556             :     }
     557             : };
     558             : 
     559           0 : int EdgeDiscovery::CompareTo(const EdgeDiscovery &rhs) const {
     560           0 :     int result = STLSortedCompare(edge_list.begin(), edge_list.end(),
     561             :                                   rhs.edge_list.begin(), rhs.edge_list.end(),
     562             :                                   EdgeDiscoveryEdgeCompare());
     563           0 :     return result;
     564             : }
     565             : 
     566           0 : void EdgeDiscovery::Remove() {
     567           0 :     edge_discovery_db_->Delete(this);
     568           0 : }
     569             : 
     570         378 : EdgeDiscoveryDB::EdgeDiscoveryDB(BgpServer *server) {
     571         378 : }
     572             : 
     573           0 : EdgeForwardingSpec::EdgeForwardingSpec()
     574           0 :     : BgpAttribute(McastEdgeForwarding, kFlags) {
     575           0 : }
     576             : 
     577           0 : EdgeForwardingSpec::EdgeForwardingSpec(const BgpAttribute &rhs)
     578           0 :     : BgpAttribute(rhs) {
     579           0 : }
     580             : 
     581           0 : EdgeForwardingSpec::EdgeForwardingSpec(const EdgeForwardingSpec &rhs)
     582           0 :     : BgpAttribute(BgpAttribute::McastEdgeForwarding, kFlags) {
     583           0 :     for (size_t i = 0; i < rhs.edge_list.size(); i++) {
     584           0 :         Edge *edge = new Edge;
     585           0 :         *edge = *rhs.edge_list[i];
     586           0 :         edge_list.push_back(edge);
     587             :     }
     588           0 : }
     589             : 
     590           0 : EdgeForwardingSpec:: ~EdgeForwardingSpec() {
     591           0 :     STLDeleteValues(&edge_list);
     592           0 : }
     593             : 
     594           0 : Ip4Address EdgeForwardingSpec::Edge::GetInboundIp4Address() const {
     595           0 :     return Ip4Address(get_value(&inbound_address[0], 4));
     596             : }
     597             : 
     598           0 : Ip4Address EdgeForwardingSpec::Edge::GetOutboundIp4Address() const {
     599           0 :     return Ip4Address(get_value(&outbound_address[0], 4));
     600             : }
     601             : 
     602           0 : void EdgeForwardingSpec::Edge::SetInboundIp4Address(Ip4Address addr) {
     603           0 :     inbound_address.resize(4, 0);
     604           0 :     const Ip4Address::bytes_type &addr_bytes = addr.to_bytes();
     605           0 :     std::copy(addr_bytes.begin(), addr_bytes.begin() + 4,
     606             :         inbound_address.begin());
     607           0 : }
     608             : 
     609           0 : void EdgeForwardingSpec::Edge::SetOutboundIp4Address(Ip4Address addr) {
     610           0 :     outbound_address.resize(4, 0);
     611           0 :     const Ip4Address::bytes_type &addr_bytes = addr.to_bytes();
     612           0 :     std::copy(addr_bytes.begin(), addr_bytes.begin() + 4,
     613             :         outbound_address.begin());
     614           0 : }
     615             : 
     616             : struct EdgeForwardingSpecEdgeCompare {
     617           0 :     int operator()(const EdgeForwardingSpec::Edge *lhs,
     618             :                    const EdgeForwardingSpec::Edge *rhs) const {
     619           0 :         KEY_COMPARE(lhs->inbound_address, rhs->inbound_address);
     620           0 :         KEY_COMPARE(lhs->outbound_address, rhs->outbound_address);
     621           0 :         KEY_COMPARE(lhs->inbound_label, rhs->inbound_label);
     622           0 :         KEY_COMPARE(lhs->outbound_label, rhs->outbound_label);
     623           0 :         return 0;
     624             :     }
     625             : };
     626             : 
     627           0 : int EdgeForwardingSpec::CompareTo(const BgpAttribute &rhs_attr) const {
     628           0 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     629           0 :     if (ret != 0) return ret;
     630           0 :     const EdgeForwardingSpec &rhs =
     631             :             static_cast<const EdgeForwardingSpec &>(rhs_attr);
     632           0 :     ret = STLSortedCompare(edge_list.begin(), edge_list.end(),
     633             :                            rhs.edge_list.begin(), rhs.edge_list.end(),
     634             :                            EdgeForwardingSpecEdgeCompare());
     635           0 :     return ret;
     636             : }
     637             : 
     638           0 : void EdgeForwardingSpec::ToCanonical(BgpAttr *attr) {
     639           0 :     attr->set_edge_forwarding(this);
     640           0 : }
     641             : 
     642           0 : string EdgeForwardingSpec::ToString() const {
     643           0 :     std::ostringstream oss;
     644           0 :     oss << "EdgeForwarding <code: " << int(code);
     645           0 :     oss << ", flags: 0x" << std::hex << int(flags) << std::dec << ">";
     646           0 :     int idx = 0;
     647           0 :     for (EdgeList::const_iterator it = edge_list.begin();
     648           0 :          it != edge_list.end(); ++it, ++idx) {
     649           0 :         const Edge *edge = *it;
     650           0 :         oss << " Edge[" << idx << "] = (";
     651           0 :         oss << "InAddress=" << edge->GetInboundIp4Address() << ", ";
     652           0 :         oss << "InLabel=" << edge->inbound_label << ", ";
     653           0 :         oss << "OutAddress=" << edge->GetOutboundIp4Address() << ", ";
     654           0 :         oss << "OutLabel=" << edge->outbound_label << ")";
     655             :     }
     656             : 
     657           0 :     return oss.str();
     658           0 : }
     659             : 
     660           0 : size_t EdgeForwardingSpec::EncodeLength() const {
     661           0 :     size_t sz = 0;
     662           0 :     for (EdgeList::const_iterator iter = edge_list.begin();
     663           0 :          iter != edge_list.end(); ++iter) {
     664           0 :         sz += 1 /* address len */ + 8 /* 2 labels */;
     665           0 :         sz += (*iter)->inbound_address.size();
     666           0 :         sz += (*iter)->outbound_address.size();
     667             :     }
     668             : 
     669           0 :     return sz;
     670             : }
     671             : 
     672           0 : EdgeForwarding::Edge::Edge(const EdgeForwardingSpec::Edge *spec_edge) {
     673           0 :     inbound_address = spec_edge->GetInboundIp4Address();
     674           0 :     outbound_address = spec_edge->GetOutboundIp4Address();
     675           0 :     inbound_label = spec_edge->inbound_label;
     676           0 :     outbound_label = spec_edge->outbound_label;
     677           0 : }
     678             : 
     679           0 : bool EdgeForwarding::Edge::operator<(const Edge &rhs) const {
     680           0 :     BOOL_KEY_COMPARE(inbound_address, rhs.inbound_address);
     681           0 :     BOOL_KEY_COMPARE(outbound_address, rhs.outbound_address);
     682           0 :     BOOL_KEY_COMPARE(inbound_label, rhs.inbound_label);
     683           0 :     BOOL_KEY_COMPARE(outbound_label, rhs.outbound_label);
     684           0 :     return false;
     685             : }
     686             : 
     687           0 : EdgeForwarding::EdgeForwarding(EdgeForwardingDB *edge_forwarding_db,
     688           0 :     const EdgeForwardingSpec &efspec)
     689           0 :     : edge_forwarding_db_(edge_forwarding_db),
     690           0 :       efspec_(efspec) {
     691           0 :     refcount_ = 0;
     692           0 :     for (EdgeForwardingSpec::EdgeList::const_iterator it =
     693           0 :          efspec_.edge_list.begin(); it != efspec_.edge_list.end(); ++it) {
     694           0 :         Edge *edge = new Edge(*it);
     695           0 :         edge_list.push_back(edge);
     696             :     }
     697           0 :     sort(edge_list.begin(), edge_list.end(), EdgeForwarding::EdgeCompare());
     698           0 : }
     699             : 
     700           0 : EdgeForwarding::~EdgeForwarding() {
     701           0 :     STLDeleteValues(&edge_list);
     702           0 : }
     703             : 
     704             : struct EdgeForwardingEdgeCompare {
     705           0 :     int operator()(const EdgeForwarding::Edge *lhs,
     706             :                    const EdgeForwarding::Edge *rhs) const {
     707           0 :         KEY_COMPARE(*lhs, *rhs);
     708           0 :         return 0;
     709             :     }
     710             : };
     711             : 
     712           0 : int EdgeForwarding::CompareTo(const EdgeForwarding &rhs) const {
     713           0 :     int result = STLSortedCompare(edge_list.begin(), edge_list.end(),
     714             :                                   rhs.edge_list.begin(), rhs.edge_list.end(),
     715             :                                   EdgeForwardingEdgeCompare());
     716           0 :     return result;
     717             : }
     718             : 
     719           0 : void EdgeForwarding::Remove() {
     720           0 :     edge_forwarding_db_->Delete(this);
     721           0 : }
     722             : 
     723         378 : EdgeForwardingDB::EdgeForwardingDB(BgpServer *server) {
     724         378 : }
     725             : 
     726           0 : bool BgpOListElem::operator<(const BgpOListElem &rhs) const {
     727           0 :     BOOL_KEY_COMPARE(address, rhs.address);
     728           0 :     BOOL_KEY_COMPARE(label, rhs.label);
     729           0 :     BOOL_KEY_COMPARE(encap, rhs.encap);
     730           0 :     return false;
     731             : }
     732             : 
     733           0 : int BgpOListSpec::CompareTo(const BgpAttribute &rhs_attr) const {
     734           0 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     735           0 :     if (ret != 0) return ret;
     736           0 :     return 0;
     737             : }
     738             : 
     739           0 : void BgpOListSpec::ToCanonical(BgpAttr *attr) {
     740           0 :     if (subcode == BgpAttribute::OList) {
     741           0 :         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           0 : }
     748             : 
     749           0 : string BgpOListSpec::ToString() const {
     750           0 :     std::ostringstream oss;
     751           0 :     oss << "OList <subcode: " << int(subcode) << ">";
     752           0 :     int idx = 0;
     753           0 :     for (Elements::const_iterator it = elements.begin();
     754           0 :          it != elements.end(); ++it, ++idx) {
     755           0 :         BgpOListElem elem(*it);
     756           0 :         oss << "OList[" << idx << "] = (";
     757           0 :         oss << "address: " << elem.address << ", ";
     758           0 :         oss << "label: " << elem.label << ", ";
     759           0 :         oss << "encap-list:";
     760           0 :         int eid = 0;
     761           0 :         for (vector<string>::const_iterator e_it = elem.encap.begin();
     762           0 :              e_it != elem.encap.end(); ++e_it, ++eid) {
     763           0 :              oss << " " << *e_it;
     764             :         }
     765           0 :         oss << ")";
     766           0 :     }
     767           0 :     return (oss.str());
     768           0 : }
     769             : 
     770           0 : BgpOList::BgpOList(BgpOListDB *olist_db, const BgpOListSpec &olist_spec)
     771           0 :     : olist_db_(olist_db),
     772           0 :       olist_spec_(olist_spec) {
     773           0 :     refcount_ = 0;
     774           0 :     for (BgpOListSpec::Elements::const_iterator it =
     775           0 :          olist_spec_.elements.begin(); it != olist_spec_.elements.end(); ++it) {
     776           0 :         BgpOListElem *elem = new BgpOListElem(*it);
     777           0 :         sort(elem->encap.begin(), elem->encap.end());
     778           0 :         elements_.push_back(elem);
     779             :     }
     780           0 :     sort(elements_.begin(), elements_.end(), BgpOListElemCompare());
     781           0 : }
     782             : 
     783           0 : BgpOList::~BgpOList() {
     784           0 :     STLDeleteValues(&elements_);
     785           0 : }
     786             : 
     787             : struct BgpOListElementCompare {
     788           0 :     int operator()(const BgpOListElem *lhs, const BgpOListElem *rhs) const {
     789           0 :         KEY_COMPARE(*lhs, *rhs);
     790           0 :         return 0;
     791             :     }
     792             : };
     793             : 
     794           0 : int BgpOList::CompareTo(const BgpOList &rhs) const {
     795           0 :     KEY_COMPARE(olist().subcode, rhs.olist().subcode);
     796           0 :     int result = STLSortedCompare(elements().begin(), elements().end(),
     797           0 :                                   rhs.elements().begin(), rhs.elements().end(),
     798             :                                   BgpOListElementCompare());
     799           0 :     return result;
     800             : }
     801             : 
     802           0 : void BgpOList::Remove() {
     803           0 :     olist_db_->Delete(this);
     804           0 : }
     805             : 
     806         378 : BgpOListDB::BgpOListDB(BgpServer *server) {
     807         378 : }
     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           0 : void BgpAttrLabelBlock::ToCanonical(BgpAttr *attr) {
     818           0 :     attr->set_label_block(label_block);
     819           0 : }
     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           0 : int BgpAttrSourceRd::CompareTo(const BgpAttribute &rhs_attr) const {
     829           0 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     830           0 :     if (ret != 0) return ret;
     831           0 :     KEY_COMPARE(source_rd,
     832             :             static_cast<const BgpAttrSourceRd &>(rhs_attr).source_rd);
     833           0 :     return 0;
     834             : }
     835             : 
     836           0 : void BgpAttrSourceRd::ToCanonical(BgpAttr *attr) {
     837           0 :     attr->set_source_rd(source_rd);
     838           0 : }
     839             : 
     840           0 : string BgpAttrSourceRd::ToString() const {
     841             :     char repr[80];
     842           0 :     snprintf(repr, sizeof(repr), "SourceRd <subcode: %d> : %s",
     843           0 :              subcode, source_rd.ToString().c_str());
     844           0 :     return string(repr);
     845             : }
     846             : 
     847           0 : int BgpAttrEsi::CompareTo(const BgpAttribute &rhs_attr) const {
     848           0 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     849           0 :     if (ret != 0) return ret;
     850           0 :     KEY_COMPARE(esi, static_cast<const BgpAttrEsi &>(rhs_attr).esi);
     851           0 :     return 0;
     852             : }
     853             : 
     854           0 : void BgpAttrEsi::ToCanonical(BgpAttr *attr) {
     855           0 :     attr->set_esi(esi);
     856           0 : }
     857             : 
     858           0 : string BgpAttrEsi::ToString() const {
     859             :     char repr[80];
     860           0 :     snprintf(repr, sizeof(repr), "Esi <subcode: %d> : %s",
     861           0 :              subcode, esi.ToString().c_str());
     862           0 :     return string(repr);
     863             : }
     864             : 
     865           0 : int BgpAttrParams::CompareTo(const BgpAttribute &rhs_attr) const {
     866           0 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     867           0 :     if (ret != 0) return ret;
     868           0 :     KEY_COMPARE(params, static_cast<const BgpAttrParams &>(rhs_attr).params);
     869           0 :     return 0;
     870             : }
     871             : 
     872           0 : void BgpAttrParams::ToCanonical(BgpAttr *attr) {
     873           0 :     attr->set_params(params);
     874           0 : }
     875             : 
     876           0 : string BgpAttrParams::ToString() const {
     877             :     char repr[80];
     878           0 :     snprintf(repr, sizeof(repr), "Params <subcode: %d> : 0x%016jx",
     879           0 :              subcode, params);
     880           0 :     return string(repr);
     881             : }
     882             : 
     883           0 : int BgpAttrSubProtocol::CompareTo(const BgpAttribute &rhs_attr) const {
     884           0 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     885           0 :     if (ret != 0) return ret;
     886           0 :     KEY_COMPARE(sbp, static_cast<const BgpAttrSubProtocol &>(rhs_attr).sbp);
     887           0 :     return 0;
     888             : }
     889             : 
     890           0 : void BgpAttrSubProtocol::ToCanonical(BgpAttr *attr) {
     891           0 :     attr->set_sub_protocol(sbp);
     892           0 : }
     893             : 
     894           0 : string BgpAttrSubProtocol::ToString() const {
     895             :     char repr[80];
     896           0 :     snprintf(repr, sizeof(repr), "SubProtocol <subcode: %d> : %s",
     897           0 :              subcode, sbp.c_str());
     898           0 :     return string(repr);
     899             : }
     900             : 
     901           0 : BgpAttr::BgpAttr()
     902           0 :     : attr_db_(NULL), origin_(BgpAttrOrigin::INCOMPLETE), nexthop_(),
     903           0 :       med_(0), local_pref_(0), atomic_aggregate_(false),
     904           0 :       aggregator_as_num_(0), aggregator_as4_num_(0), params_(0) {
     905           0 :     refcount_ = 0;
     906           0 : }
     907             : 
     908           0 : BgpAttr::BgpAttr(BgpAttrDB *attr_db)
     909           0 :     : attr_db_(attr_db), origin_(BgpAttrOrigin::INCOMPLETE),
     910           0 :       nexthop_(), med_(0), local_pref_(0), atomic_aggregate_(false),
     911           0 :       aggregator_as_num_(0), aggregator_as4_num_(0), params_(0) {
     912           0 :     refcount_ = 0;
     913           0 : }
     914             : 
     915        1386 : BgpAttr::BgpAttr(BgpAttrDB *attr_db, const BgpAttrSpec &spec)
     916        1386 :     : attr_db_(attr_db), origin_(BgpAttrOrigin::INCOMPLETE),
     917        2771 :       nexthop_(), med_(0),
     918        1385 :       local_pref_(BgpAttrLocalPref::kDefault),
     919        1385 :       atomic_aggregate_(false),
     920        1385 :       aggregator_as_num_(0), aggregator_as4_num_(0), 
     921        1386 :       aggregator_address_(), params_(0) {
     922        1382 :     refcount_ = 0;
     923        1387 :     for (vector<BgpAttribute *>::const_iterator it = spec.begin();
     924        3206 :          it < spec.end(); it++) {
     925        1822 :         (*it)->ToCanonical(this);
     926             :     }
     927        1380 : }
     928             : 
     929         136 : BgpAttr::BgpAttr(const BgpAttr &rhs)
     930         136 :     : attr_db_(rhs.attr_db_), origin_(rhs.origin_), nexthop_(rhs.nexthop_),
     931         136 :       med_(rhs.med_), local_pref_(rhs.local_pref_),
     932         136 :       atomic_aggregate_(rhs.atomic_aggregate_),
     933         136 :       aggregator_as_num_(rhs.aggregator_as_num_),
     934         136 :       aggregator_as4_num_(rhs.aggregator_as4_num_),
     935         136 :       aggregator_address_(rhs.aggregator_address_),
     936         136 :       originator_id_(rhs.originator_id_),
     937         136 :       source_rd_(rhs.source_rd_), esi_(rhs.esi_), params_(rhs.params_),
     938         136 :       as_path_(rhs.as_path_),
     939         136 :       aspath_4byte_(rhs.aspath_4byte_),
     940         136 :       as4_path_(rhs.as4_path_),
     941         136 :       cluster_list_(rhs.cluster_list_),
     942         136 :       community_(rhs.community_),
     943         136 :       ext_community_(rhs.ext_community_),
     944         136 :       large_community_(rhs.large_community_),
     945         136 :       deferred_large_spec_(nullptr),
     946         136 :       origin_vn_path_(rhs.origin_vn_path_),
     947         136 :       pmsi_tunnel_(rhs.pmsi_tunnel_),
     948         136 :       edge_discovery_(rhs.edge_discovery_),
     949         136 :       edge_forwarding_(rhs.edge_forwarding_),
     950         136 :       label_block_(rhs.label_block_),
     951         136 :       olist_(rhs.olist_),
     952         136 :       leaf_olist_(rhs.leaf_olist_),
     953         272 :       sub_protocol_(rhs.sub_protocol_) {
     954         136 :     refcount_ = 0;
     955         136 : }
     956             : 
     957           0 : void BgpAttr::set_as_path(AsPathPtr aspath) {
     958           0 :     as_path_ = aspath;
     959           0 : }
     960             : 
     961          64 : void BgpAttr::set_as_path(const AsPathSpec *spec) {
     962          64 :     if (spec) {
     963          64 :         as_path_ = attr_db_->server()->aspath_db()->Locate(*spec);
     964             :     } else {
     965           0 :         as_path_ = NULL;
     966             :     }
     967          64 : }
     968             : 
     969           0 : void BgpAttr::set_as4_path(As4PathPtr aspath) {
     970           0 :     as4_path_ = aspath;
     971           0 : }
     972             : 
     973           0 : void BgpAttr::set_as4_path(const As4PathSpec *spec) {
     974           0 :     if (spec) {
     975           0 :         as4_path_ = attr_db_->server()->as4path_db()->Locate(*spec);
     976             :     } else {
     977           0 :         as4_path_ = NULL;
     978             :     }
     979           0 : }
     980             : 
     981           0 : void BgpAttr::set_aspath_4byte(AsPath4BytePtr aspath) {
     982           0 :     aspath_4byte_ = aspath;
     983           0 : }
     984             : 
     985          10 : void BgpAttr::set_aspath_4byte(const AsPath4ByteSpec *spec) {
     986          10 :     if (spec) {
     987           2 :         aspath_4byte_ = attr_db_->server()->aspath_4byte_db()->Locate(*spec);
     988             :     } else {
     989           8 :         aspath_4byte_ = NULL;
     990             :     }
     991          10 : }
     992             : 
     993           4 : void BgpAttr::set_cluster_list(const ClusterListSpec *spec) {
     994           4 :     if (spec) {
     995           4 :         cluster_list_ = attr_db_->server()->cluster_list_db()->Locate(*spec);
     996             :     } else {
     997           0 :         cluster_list_ = NULL;
     998             :     }
     999           4 : }
    1000             : 
    1001           0 : void BgpAttr::set_community(CommunityPtr comm) {
    1002           0 :     community_ = comm;
    1003           0 : }
    1004             : 
    1005           0 : void BgpAttr::set_community(const CommunitySpec *comm) {
    1006           0 :     if (comm) {
    1007           0 :         community_ = attr_db_->server()->comm_db()->Locate(*comm);
    1008             :     } else {
    1009           0 :         community_ = NULL;
    1010             :     }
    1011           0 : }
    1012             : 
    1013           0 : void BgpAttr::set_ext_community(ExtCommunityPtr extcomm) {
    1014           0 :     ext_community_ = extcomm;
    1015           0 : }
    1016             : 
    1017           0 : void BgpAttr::set_ext_community(const ExtCommunitySpec *extcomm) {
    1018           0 :     if (extcomm) {
    1019           0 :         LargeCommunitySpec large_spec = LargeCommunitySpec::FromTag(*extcomm);
    1020           0 :         set_large_community(&large_spec);
    1021             :         
    1022           0 :         if (large_spec.communities.size()) {
    1023             :             ExtCommunitySpec new_comms =
    1024           0 :                 LargeCommunitySpec::RemoveTags(*extcomm);
    1025             :             ext_community_ =
    1026           0 :                 attr_db_->server()->extcomm_db()->Locate(new_comms);
    1027           0 :             return;
    1028           0 :         }
    1029           0 :         ext_community_ = attr_db_->server()->extcomm_db()->Locate(*extcomm);
    1030           0 :     } else {
    1031           0 :         ext_community_ = NULL;
    1032             :     }
    1033             : }
    1034             : 
    1035           0 : void BgpAttr::set_large_community(LargeCommunityPtr largecomm) {
    1036           0 :     large_community_ = largecomm;
    1037           0 : }
    1038             : 
    1039           0 : void BgpAttr::set_large_community(const LargeCommunitySpec *largecomm) {
    1040           0 :     if (largecomm) {
    1041           0 :         if (!bool(deferred_large_spec_)) {
    1042           0 :             deferred_large_spec_.reset(new LargeCommunitySpec);
    1043           0 :             deferred_large_spec_->communities = largecomm->communities;
    1044             :         } else {
    1045           0 :             deferred_large_spec_->communities.insert(
    1046           0 :                 deferred_large_spec_->communities.end(),
    1047             :                 largecomm->communities.begin(),
    1048             :                 largecomm->communities.end());
    1049             :         }
    1050             :         large_community_ =
    1051           0 :             attr_db_->server()->largecomm_db()->Locate(*deferred_large_spec_);
    1052             :     } else {
    1053           0 :         large_community_ = NULL;
    1054             :     }
    1055           0 : }
    1056             : 
    1057           0 : void BgpAttr::set_origin_vn_path(OriginVnPathPtr ovnpath) {
    1058           0 :     origin_vn_path_ = ovnpath;
    1059           0 : }
    1060             : 
    1061           0 : void BgpAttr::set_origin_vn_path(const OriginVnPathSpec *spec) {
    1062           0 :     if (spec) {
    1063           0 :         origin_vn_path_ = attr_db_->server()->ovnpath_db()->Locate(*spec);
    1064             :     } else {
    1065           0 :         origin_vn_path_ = NULL;
    1066             :     }
    1067           0 : }
    1068             : 
    1069           0 : void BgpAttr::set_pmsi_tunnel(const PmsiTunnelSpec *pmsi_spec) {
    1070           0 :     if (pmsi_spec) {
    1071           0 :         pmsi_tunnel_ = attr_db_->server()->pmsi_tunnel_db()->Locate(*pmsi_spec);
    1072             :     } else {
    1073           0 :         pmsi_tunnel_ = NULL;
    1074             :     }
    1075           0 : }
    1076             : 
    1077           0 : void BgpAttr::set_edge_discovery(const EdgeDiscoverySpec *edspec) {
    1078           0 :     if (edspec) {
    1079             :         edge_discovery_ =
    1080           0 :             attr_db_->server()->edge_discovery_db()->Locate(*edspec);
    1081             :     } else {
    1082           0 :         edge_discovery_ = NULL;
    1083             :     }
    1084           0 : }
    1085             : 
    1086           0 : void BgpAttr::set_edge_forwarding(const EdgeForwardingSpec *efspec) {
    1087           0 :     if (efspec) {
    1088             :         edge_forwarding_ =
    1089           0 :             attr_db_->server()->edge_forwarding_db()->Locate(*efspec);
    1090             :     } else {
    1091           0 :         edge_forwarding_ = NULL;
    1092             :     }
    1093           0 : }
    1094             : 
    1095           0 : void BgpAttr::set_label_block(LabelBlockPtr label_block) {
    1096           0 :     label_block_ = label_block;
    1097           0 : }
    1098             : 
    1099           0 : void BgpAttr::set_olist(const BgpOListSpec *olist_spec) {
    1100           0 :     if (olist_spec) {
    1101           0 :         olist_ = attr_db_->server()->olist_db()->Locate(*olist_spec);
    1102             :     } else {
    1103           0 :         olist_ = NULL;
    1104             :     }
    1105           0 : }
    1106             : 
    1107           0 : void BgpAttr::set_leaf_olist(const BgpOListSpec *leaf_olist_spec) {
    1108           0 :     if (leaf_olist_spec) {
    1109           0 :         leaf_olist_ = attr_db_->server()->olist_db()->Locate(*leaf_olist_spec);
    1110             :     } else {
    1111           0 :         leaf_olist_ = NULL;
    1112             :     }
    1113           0 : }
    1114             : 
    1115          64 : int BgpAttr::max_as_path_count() const {
    1116          64 :     int as_count = as_path_count();
    1117          64 :     int as4_count = aspath_4byte_count();
    1118          64 :     return as_count > as4_count ? as_count : as4_count;
    1119             : }
    1120             : 
    1121           0 : bool BgpAttr::IsAsPathEmpty() const {
    1122           0 :     if (as_path_ && !as_path_->empty())
    1123           0 :         return false;
    1124           0 :     if (aspath_4byte_ && !aspath_4byte_->empty())
    1125           0 :         return false;
    1126           0 :     return true;
    1127             : }
    1128             : 
    1129           0 : string BgpAttr::OriginToString(BgpAttrOrigin::OriginType origin) {
    1130           0 :     switch (origin) {
    1131           0 :     case BgpAttrOrigin::IGP:
    1132           0 :         return "igp";
    1133             :         break;
    1134           0 :     case BgpAttrOrigin::EGP:
    1135           0 :         return "egp";
    1136             :         break;
    1137           0 :     case BgpAttrOrigin::INCOMPLETE:
    1138           0 :         return "incomplete";
    1139             :         break;
    1140             :     }
    1141           0 :     return "unknown";
    1142             : }
    1143             : 
    1144        1618 : BgpAttrOrigin::OriginType BgpAttr::OriginFromString(
    1145             :         const string &bgp_origin_type) {
    1146        1618 :     if(bgp_origin_type ==  "IGP"){
    1147        1618 :         return BgpAttrOrigin::IGP;
    1148           0 :     } else if( bgp_origin_type ==  "EGP") {
    1149           0 :         return BgpAttrOrigin::EGP;
    1150             :     }
    1151           0 :     return BgpAttrOrigin::INCOMPLETE;
    1152             : }
    1153             : 
    1154           0 : string BgpAttr::origin_string() const {
    1155           0 :     return OriginToString(origin());
    1156             : }
    1157             : 
    1158           0 : Address::Family BgpAttr::nexthop_family() const {
    1159           0 :     if (nexthop_.is_v6()) {
    1160           0 :         return Address::INET6;
    1161             :     } else {
    1162           0 :         return Address::INET;
    1163             :     }
    1164             : }
    1165             : 
    1166          16 : as_t BgpAttr::neighbor_as() const {
    1167          16 :     if (as_path_.get())
    1168           8 :         return as_path_->neighbor_as();
    1169           8 :     if (aspath_4byte_.get())
    1170           0 :         return aspath_4byte_->neighbor_as();
    1171           8 :     return 0;
    1172             : }
    1173             : 
    1174          64 : uint32_t BgpAttr::sequence_number() const {
    1175          64 :     if (!ext_community_)
    1176          64 :         return 0;
    1177           0 :     for (ExtCommunity::ExtCommunityList::const_iterator it =
    1178           0 :          ext_community_->communities().begin();
    1179           0 :          it != ext_community_->communities().end(); ++it) {
    1180           0 :         if (ExtCommunity::is_mac_mobility(*it)) {
    1181           0 :             MacMobility mm(*it);
    1182           0 :             return mm.sequence_number();
    1183             :         }
    1184             :     }
    1185           0 :     return 0;
    1186             : }
    1187             : 
    1188          32 : bool BgpAttr::evpn_sticky_mac() const {
    1189          32 :     if (!ext_community_)
    1190          32 :         return 0;
    1191           0 :     for (ExtCommunity::ExtCommunityList::const_iterator it =
    1192           0 :          ext_community_->communities().begin();
    1193           0 :          it != ext_community_->communities().end(); ++it) {
    1194           0 :         if (ExtCommunity::is_mac_mobility(*it)) {
    1195           0 :             MacMobility mm(*it);
    1196           0 :             return mm.sticky();
    1197             :         }
    1198             :     }
    1199           0 :     return 0;
    1200             : }
    1201             : 
    1202          32 : bool BgpAttr::etree_leaf() const {
    1203          32 :     if (!ext_community_)
    1204          32 :         return 0;
    1205           0 :     for (ExtCommunity::ExtCommunityList::const_iterator it =
    1206           0 :          ext_community_->communities().begin();
    1207           0 :          it != ext_community_->communities().end(); ++it) {
    1208           0 :         if (ExtCommunity::is_etree(*it)) {
    1209           0 :             ETree etree(*it);
    1210           0 :             return etree.leaf();
    1211             :         }
    1212             :     }
    1213           0 :     return 0;
    1214             : }
    1215             : 
    1216           0 : bool BgpAttr::evpn_single_active() const {
    1217           0 :     if (!ext_community_)
    1218           0 :         return false;
    1219           0 :     for (ExtCommunity::ExtCommunityList::const_iterator it =
    1220           0 :          ext_community_->communities().begin();
    1221           0 :          it != ext_community_->communities().end(); ++it) {
    1222           0 :         if (ExtCommunity::is_esi_label(*it)) {
    1223           0 :             EsiLabel esi_label(*it);
    1224           0 :             return esi_label.single_active();
    1225             :         }
    1226             :     }
    1227           0 :     return true;
    1228             : }
    1229             : 
    1230           0 : MacAddress BgpAttr::mac_address() const {
    1231           0 :     if (!ext_community_)
    1232           0 :         return MacAddress::kZeroMac;
    1233           0 :     for (ExtCommunity::ExtCommunityList::const_iterator it =
    1234           0 :          ext_community_->communities().begin();
    1235           0 :          it != ext_community_->communities().end(); ++it) {
    1236           0 :         if (ExtCommunity::is_router_mac(*it)) {
    1237           0 :             RouterMac router_mac(*it);
    1238           0 :             return router_mac.mac_address();
    1239             :         }
    1240             :     }
    1241           0 :     return MacAddress::kZeroMac;
    1242             : }
    1243             : 
    1244        1301 : void BgpAttr::Remove() {
    1245        1301 :     attr_db_->Delete(this);
    1246        1301 : }
    1247             : 
    1248          30 : int BgpAttr::IsAsPathLoop(as_t asn, uint8_t max_loop_count) const {
    1249          30 :     if (as_path() && as_path()->path().AsPathLoop(asn, max_loop_count)) {
    1250           0 :         return true;
    1251             :     }
    1252          30 :     if (aspath_4byte() &&
    1253           0 :            aspath_4byte()->path().AsPathLoop(asn, max_loop_count)) {
    1254           0 :         return true;
    1255             :     }
    1256          30 :     if (asn > AS2_MAX && as4_path() &&
    1257           0 :            as4_path()->path().AsPathLoop(asn, max_loop_count)) {
    1258           0 :         return true;
    1259             :     }
    1260          30 :     return false;
    1261             : }
    1262             : 
    1263        9628 : int BgpAttr::CompareTo(const BgpAttr &rhs) const {
    1264        9628 :     KEY_COMPARE(origin_, rhs.origin_);
    1265        4830 :     KEY_COMPARE(nexthop_, rhs.nexthop_);
    1266        4587 :     KEY_COMPARE(med_, rhs.med_);
    1267        4587 :     KEY_COMPARE(local_pref_, rhs.local_pref_);
    1268        4587 :     KEY_COMPARE(atomic_aggregate_, rhs.atomic_aggregate_);
    1269        4587 :     KEY_COMPARE(aggregator_as_num_, rhs.aggregator_as_num_);
    1270        4587 :     KEY_COMPARE(aggregator_as4_num_, rhs.aggregator_as4_num_);
    1271        4587 :     KEY_COMPARE(aggregator_address_, rhs.aggregator_address_);
    1272        4588 :     KEY_COMPARE(originator_id_, rhs.originator_id_);
    1273        4582 :     KEY_COMPARE(pmsi_tunnel_.get(), rhs.pmsi_tunnel_.get());
    1274        4583 :     KEY_COMPARE(edge_discovery_.get(), rhs.edge_discovery_.get());
    1275        4583 :     KEY_COMPARE(edge_forwarding_.get(), rhs.edge_forwarding_.get());
    1276        4583 :     KEY_COMPARE(esi_, rhs.esi_);
    1277        4582 :     KEY_COMPARE(params_, rhs.params_);
    1278        4582 :     KEY_COMPARE(source_rd_, rhs.source_rd_);
    1279        4582 :     KEY_COMPARE(label_block_.get(), rhs.label_block_.get());
    1280        4582 :     KEY_COMPARE(olist_.get(), rhs.olist_.get());
    1281        4582 :     KEY_COMPARE(leaf_olist_.get(), rhs.leaf_olist_.get());
    1282        4582 :     KEY_COMPARE(as_path_.get(), rhs.as_path_.get());
    1283        4543 :     KEY_COMPARE(aspath_4byte_.get(), rhs.aspath_4byte_.get());
    1284        4543 :     KEY_COMPARE(as4_path_.get(), rhs.as4_path_.get());
    1285        4542 :     KEY_COMPARE(cluster_list_.get(), rhs.cluster_list_.get());
    1286        4542 :     KEY_COMPARE(community_.get(), rhs.community_.get());
    1287        4542 :     KEY_COMPARE(ext_community_.get(), rhs.ext_community_.get());
    1288        4540 :     KEY_COMPARE(large_community_.get(), rhs.large_community_.get());
    1289        4541 :     KEY_COMPARE(origin_vn_path_.get(), rhs.origin_vn_path_.get());
    1290        4542 :     KEY_COMPARE(sub_protocol_, rhs.sub_protocol_);
    1291        4542 :     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         378 : BgpAttrDB::BgpAttrDB(BgpServer *server) : server_(server) {
    1339         378 : }
    1340             : 
    1341             : // Return a clone of attribute with updated aspath.
    1342           0 : BgpAttrPtr BgpAttrDB::ReplaceAsPathAndLocate(const BgpAttr *attr,
    1343             :                                              AsPathPtr aspath) {
    1344           0 :     BgpAttr *clone = new BgpAttr(*attr);
    1345           0 :     clone->set_as_path(aspath);
    1346           0 :     return Locate(clone);
    1347             : }
    1348             : 
    1349             : // Return a clone of attribute with updated community.
    1350           0 : BgpAttrPtr BgpAttrDB::ReplaceCommunityAndLocate(const BgpAttr *attr,
    1351             :                                                 CommunityPtr community) {
    1352           0 :     BgpAttr *clone = new BgpAttr(*attr);
    1353           0 :     clone->set_community(community);
    1354           0 :     return Locate(clone);
    1355             : }
    1356             : 
    1357             : //Return a clone of attribute with updated origin
    1358           0 : BgpAttrPtr BgpAttrDB::ReplaceOriginAndLocate(const BgpAttr *attr,
    1359             :                                              BgpAttrOrigin::OriginType origin) {
    1360           0 :     BgpAttr *clone = new BgpAttr(*attr);
    1361           0 :     clone->set_origin(origin);
    1362           0 :     return Locate(clone);
    1363             : }
    1364             : 
    1365             : // Return a clone of attribute with updated extended community.
    1366           0 : BgpAttrPtr BgpAttrDB::ReplaceExtCommunityAndLocate(const BgpAttr *attr,
    1367             :                                                    ExtCommunityPtr extcomm) {
    1368           0 :     BgpAttr *clone = new BgpAttr(*attr);
    1369           0 :     clone->set_ext_community(extcomm);
    1370           0 :     return Locate(clone);
    1371             : }
    1372             : 
    1373             : // Return a clone of attribute with updated large community.
    1374           0 : BgpAttrPtr BgpAttrDB::ReplaceLargeCommunityAndLocate(
    1375             :     const BgpAttr *attr, LargeCommunityPtr largecomm) {
    1376           0 :     BgpAttr *clone = new BgpAttr(*attr);
    1377           0 :     clone->set_large_community(largecomm);
    1378           0 :     return Locate(clone);
    1379             : }
    1380             : 
    1381             : // Return a clone of attribute with updated origin vn path.
    1382           0 : BgpAttrPtr BgpAttrDB::ReplaceOriginVnPathAndLocate(const BgpAttr *attr,
    1383             :                                                    OriginVnPathPtr ovnpath) {
    1384           0 :     BgpAttr *clone = new BgpAttr(*attr);
    1385           0 :     clone->set_origin_vn_path(ovnpath);
    1386           0 :     return Locate(clone);
    1387             : }
    1388             : 
    1389             : // Return a clone of attribute with updated local preference.
    1390           0 : BgpAttrPtr BgpAttrDB::ReplaceLocalPreferenceAndLocate(const BgpAttr *attr,
    1391             :                                                       uint32_t local_pref) {
    1392           0 :     BgpAttr *clone = new BgpAttr(*attr);
    1393           0 :     clone->set_local_pref(local_pref);
    1394           0 :     return Locate(clone);
    1395             : }
    1396             : 
    1397             : // Return a clone of attribute with updated originator id.
    1398           0 : BgpAttrPtr BgpAttrDB::ReplaceOriginatorIdAndLocate(const BgpAttr *attr,
    1399             :                                                    Ip4Address originator_id) {
    1400           0 :     BgpAttr *clone = new BgpAttr(*attr);
    1401           0 :     clone->set_originator_id(originator_id);
    1402           0 :     return Locate(clone);
    1403             : }
    1404             : 
    1405             : // Return a clone of attribute with updated source rd.
    1406           0 : BgpAttrPtr BgpAttrDB::ReplaceSourceRdAndLocate(const BgpAttr *attr,
    1407             :     const RouteDistinguisher &source_rd) {
    1408           0 :     BgpAttr *clone = new BgpAttr(*attr);
    1409           0 :     clone->set_source_rd(source_rd);
    1410           0 :     return Locate(clone);
    1411             : }
    1412             : 
    1413             : // Return a clone of attribute with updated esi.
    1414           0 : BgpAttrPtr BgpAttrDB::ReplaceEsiAndLocate(const BgpAttr *attr,
    1415             :                                           const EthernetSegmentId &esi) {
    1416           0 :     BgpAttr *clone = new BgpAttr(*attr);
    1417           0 :     clone->set_esi(esi);
    1418           0 :     return Locate(clone);
    1419             : }
    1420             : 
    1421             : // Return a clone of attribute with updated olist.
    1422           0 : BgpAttrPtr BgpAttrDB::ReplaceOListAndLocate(const BgpAttr *attr,
    1423             :     const BgpOListSpec *olist_spec) {
    1424           0 :     assert(olist_spec->subcode == BgpAttribute::OList);
    1425           0 :     BgpAttr *clone = new BgpAttr(*attr);
    1426           0 :     clone->set_olist(olist_spec);
    1427           0 :     return Locate(clone);
    1428             : }
    1429             : 
    1430             : // Return a clone of attribute with updated leaf olist.
    1431           0 : BgpAttrPtr BgpAttrDB::ReplaceLeafOListAndLocate(const BgpAttr *attr,
    1432             :     const BgpOListSpec *leaf_olist_spec) {
    1433           0 :     assert(leaf_olist_spec->subcode == BgpAttribute::LeafOList);
    1434           0 :     BgpAttr *clone = new BgpAttr(*attr);
    1435           0 :     clone->set_leaf_olist(leaf_olist_spec);
    1436           0 :     return Locate(clone);
    1437             : }
    1438             : 
    1439             : // Return a clone of attribute with updated sub-protocol.
    1440           0 : BgpAttrPtr BgpAttrDB::ReplaceSubProtocolAndLocate(const BgpAttr *attr,
    1441             :     const string &sbp) {
    1442           0 :     BgpAttr *clone = new BgpAttr(*attr);
    1443           0 :     clone->set_sub_protocol(sbp);
    1444           0 :     return Locate(clone);
    1445             : }
    1446             : 
    1447             : 
    1448             : // Return a clone of attribute with updated pmsi tunnel.
    1449           0 : BgpAttrPtr BgpAttrDB::ReplacePmsiTunnelAndLocate(const BgpAttr *attr,
    1450             :     const PmsiTunnelSpec *pmsi_spec) {
    1451           0 :     BgpAttr *clone = new BgpAttr(*attr);
    1452           0 :     clone->set_pmsi_tunnel(pmsi_spec);
    1453           0 :     return Locate(clone);
    1454             : }
    1455             : 
    1456             : // Return a clone of attribute with updated nexthop.
    1457          30 : BgpAttrPtr BgpAttrDB::ReplaceNexthopAndLocate(const BgpAttr *attr,
    1458             :     const IpAddress &addr) {
    1459          30 :     BgpAttr *clone = new BgpAttr(*attr);
    1460          30 :     clone->set_nexthop(addr);
    1461          30 :     return Locate(clone);
    1462             : }

Generated by: LCOV version 1.14