LCOV - code coverage report
Current view: top level - bgp - bgp_attr.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 273 296 92.2 %
Date: 2026-06-18 01:51:13 Functions: 133 139 95.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #ifndef SRC_BGP_BGP_ATTR_H_
       6             : #define SRC_BGP_BGP_ATTR_H_
       7             : 
       8             : #include <boost/intrusive_ptr.hpp>
       9             : 
      10             : #include <set>
      11             : #include <string>
      12             : #include <vector>
      13             : #include <atomic>
      14             : 
      15             : #include "base/label_block.h"
      16             : #include "base/parse_object.h"
      17             : #include "base/util.h"
      18             : #include "base/address.h"
      19             : #include "bgp/bgp_aspath.h"
      20             : #include "bgp/bgp_attr_base.h"
      21             : #include "bgp/bgp_origin_vn_path.h"
      22             : #include "bgp/community.h"
      23             : #include "net/esi.h"
      24             : #include "net/mac_address.h"
      25             : #include "net/rd.h"
      26             : 
      27             : class BgpAttr;
      28             : class BgpAttrDB;
      29             : class BgpOListDB;
      30             : class BgpServer;
      31             : class ClusterListDB;
      32             : class EdgeDiscoveryDB;
      33             : class EdgeForwardingDB;
      34             : class PmsiTunnelDB;
      35             : 
      36             : // BGP UPDATE attributes: as-path, community, ext-community, next-hop,
      37             : // cluster-list, ...
      38             : // all information in the UPDATE except: NLRI (prefix) and label.
      39             : 
      40             : struct BgpAttrOrigin : public BgpAttribute {
      41             :     static const int kSize = 1;
      42             :     static const uint8_t kFlags = Transitive;
      43             :     BgpAttrOrigin() : BgpAttribute(Origin, kFlags), origin(IGP) { }
      44      124278 :     explicit BgpAttrOrigin(const BgpAttribute &rhs)
      45      124278 :         : BgpAttribute(rhs), origin(IGP) {
      46      124277 :     }
      47      204068 :     explicit BgpAttrOrigin(int origin) :
      48      204068 :             BgpAttribute(Origin, kFlags), origin(origin) { }
      49             :     enum OriginType {
      50             :         IGP = 0,
      51             :         EGP = 1,
      52             :         INCOMPLETE = 2
      53             :     };
      54             : 
      55             :     int origin;
      56             :     virtual int CompareTo(const BgpAttribute &rhs_attr) const;
      57             :     virtual void ToCanonical(BgpAttr *attr);
      58             :     virtual std::string ToString() const;
      59             : };
      60             : 
      61             : struct BgpAttrNextHop : public BgpAttribute {
      62             :     static const int kSize = 4;
      63             :     static const uint8_t kFlags = Transitive;
      64             :     BgpAttrNextHop() : BgpAttribute(NextHop, kFlags), nexthop(0) {}
      65       16159 :     explicit BgpAttrNextHop(const BgpAttribute &rhs)
      66       16159 :         : BgpAttribute(rhs), nexthop(0) {
      67       16159 :     }
      68      203364 :     explicit BgpAttrNextHop(uint32_t nexthop)
      69      203364 :         : BgpAttribute(NextHop, kFlags), nexthop(nexthop) {}
      70        1236 :     explicit BgpAttrNextHop(Ip4Address v4_nexthop)
      71        1236 :         : BgpAttribute(NextHop, kFlags), nexthop(v4_nexthop.to_ulong()) {}
      72         325 :     explicit BgpAttrNextHop(Ip6Address v6_nexthop)
      73         325 :         : BgpAttribute(NextHop, kFlags), nexthop(0), v6_nexthop(v6_nexthop) {}
      74        7954 :     explicit BgpAttrNextHop(IpAddress ip_nexthop)
      75        7954 :         : BgpAttribute(NextHop, kFlags), nexthop(0) {
      76        7954 :         if (ip_nexthop.is_v4()) {
      77        5747 :             nexthop = ip_nexthop.to_v4().to_ulong();
      78        2207 :         } else if (ip_nexthop.is_v6()) {
      79        2207 :             v6_nexthop = ip_nexthop.to_v6();
      80             :         }
      81        7954 :     }
      82             :     uint32_t nexthop;
      83             :     Ip6Address v6_nexthop;
      84             :     virtual int CompareTo(const BgpAttribute &rhs_attr) const;
      85             :     virtual void ToCanonical(BgpAttr *attr);
      86             :     virtual std::string ToString() const;
      87             : };
      88             : 
      89             : struct BgpAttrMultiExitDisc : public BgpAttribute {
      90             :     static const int kSize = 4;
      91             :     static const uint8_t kFlags = Optional;
      92             :     BgpAttrMultiExitDisc() : BgpAttribute(MultiExitDisc, kFlags), med(0) {}
      93       54159 :     explicit BgpAttrMultiExitDisc(const BgpAttribute &rhs)
      94       54159 :         : BgpAttribute(rhs), med(0) {
      95       54159 :     }
      96       84823 :     explicit BgpAttrMultiExitDisc(uint32_t med) :
      97       84823 :             BgpAttribute(MultiExitDisc, kFlags), med(med) {}
      98             :     uint32_t med;
      99             :     virtual int CompareTo(const BgpAttribute &rhs_attr) const;
     100             :     virtual void ToCanonical(BgpAttr *attr);
     101             :     virtual std::string ToString() const;
     102             : };
     103             : 
     104             : struct BgpAttrLocalPref : public BgpAttribute {
     105             :     static const int kDefault = 100;
     106             :     static const int kSize = 4;
     107             :     static const uint8_t kFlags = Transitive;
     108             :     BgpAttrLocalPref() : BgpAttribute(LocalPref, kFlags), local_pref(0) {}
     109       26882 :     explicit BgpAttrLocalPref(const BgpAttribute &rhs)
     110       26882 :         : BgpAttribute(rhs), local_pref(0) {
     111       26882 :     }
     112       98411 :     explicit BgpAttrLocalPref(uint32_t local_pref)
     113       98411 :         : BgpAttribute(LocalPref, kFlags), local_pref(local_pref) {
     114       98411 :     }
     115             :     uint32_t local_pref;
     116             :     virtual int CompareTo(const BgpAttribute &rhs_attr) const;
     117             :     virtual void ToCanonical(BgpAttr *attr);
     118             :     virtual std::string ToString() const;
     119             : };
     120             : 
     121             : struct BgpAttrAtomicAggregate : public BgpAttribute {
     122             :     static const int kSize = 0;
     123             :     static const uint8_t kFlags = Transitive;
     124        4015 :     BgpAttrAtomicAggregate() : BgpAttribute(AtomicAggregate, kFlags) {}
     125        2674 :     explicit BgpAttrAtomicAggregate(const BgpAttribute &rhs)
     126        2674 :         : BgpAttribute(rhs) {
     127        2674 :     }
     128             :     virtual void ToCanonical(BgpAttr *attr);
     129             :     virtual std::string ToString() const;
     130             : };
     131             : 
     132             : struct BgpAttrAs4Aggregator : public BgpAttribute {
     133             :     static const int kSize = 8;
     134             :     static const uint8_t kFlags = Optional|Transitive;
     135             :     BgpAttrAs4Aggregator()
     136             :         : BgpAttribute(As4Aggregator, kFlags), as_num(0), address(0) {
     137             :     }
     138           2 :     explicit BgpAttrAs4Aggregator(const BgpAttribute &rhs)
     139           2 :         : BgpAttribute(rhs), as_num(0), address(0) {
     140           2 :     }
     141           0 :     explicit BgpAttrAs4Aggregator(uint32_t as_num, uint32_t address) :
     142           0 :         BgpAttribute(As4Aggregator, kFlags), as_num(as_num), address(address) {}
     143             :     as_t as_num;
     144             :     uint32_t address;
     145             :     virtual int CompareTo(const BgpAttribute &rhs_attr) const;
     146             :     virtual void ToCanonical(BgpAttr *attr);
     147             :     virtual std::string ToString() const;
     148             : };
     149             : 
     150             : struct BgpAttrAggregator : public BgpAttribute {
     151             :     static const int kSize = 6;
     152             :     static const uint8_t kFlags = Optional|Transitive;
     153             :     BgpAttrAggregator()
     154             :         : BgpAttribute(Aggregator, kFlags), as_num(0), address(0) {
     155             :     }
     156        2621 :     explicit BgpAttrAggregator(const BgpAttribute &rhs)
     157        2621 :         : BgpAttribute(rhs), as_num(0), address(0) {
     158        2621 :     }
     159        4047 :     explicit BgpAttrAggregator(uint32_t as_num, uint32_t address) :
     160        4047 :         BgpAttribute(Aggregator, kFlags), as_num(as_num), address(address) {}
     161             :     as2_t as_num;
     162             :     uint32_t address;
     163             :     virtual int CompareTo(const BgpAttribute &rhs_attr) const;
     164             :     virtual void ToCanonical(BgpAttr *attr);
     165             :     virtual std::string ToString() const;
     166             : };
     167             : 
     168             : struct BgpAttr4ByteAggregator : public BgpAttribute {
     169             :     static const int kSize = 8;
     170             :     static const uint8_t kFlags = Optional|Transitive;
     171             :     BgpAttr4ByteAggregator()
     172             :         : BgpAttribute(Aggregator, kFlags), as_num(0), address(0) {
     173             :     }
     174           3 :     explicit BgpAttr4ByteAggregator(const BgpAttribute &rhs)
     175           3 :         : BgpAttribute(rhs), as_num(0), address(0) {
     176           3 :     }
     177           3 :     explicit BgpAttr4ByteAggregator(uint32_t as_num, uint32_t address) :
     178           3 :         BgpAttribute(Aggregator, kFlags), as_num(as_num), address(address) {}
     179             :     as_t as_num;
     180             :     uint32_t address;
     181             :     virtual int CompareTo(const BgpAttribute &rhs_attr) const;
     182             :     virtual void ToCanonical(BgpAttr *attr);
     183             :     virtual std::string ToString() const;
     184             : };
     185             : 
     186             : struct BgpAttrOriginatorId : public BgpAttribute {
     187             :     static const int kSize = 4;
     188             :     static const uint8_t kFlags = Optional;
     189             :     BgpAttrOriginatorId()
     190             :         : BgpAttribute(OriginatorId, kFlags), originator_id(0) {
     191             :     }
     192           3 :     explicit BgpAttrOriginatorId(const BgpAttribute &rhs)
     193           3 :         : BgpAttribute(rhs), originator_id(0) {
     194           3 :     }
     195          21 :     explicit BgpAttrOriginatorId(uint32_t originator_id)
     196          21 :         : BgpAttribute(OriginatorId, kFlags), originator_id(originator_id) {}
     197             :     uint32_t originator_id;
     198             :     virtual int CompareTo(const BgpAttribute &rhs_attr) const;
     199             :     virtual void ToCanonical(BgpAttr *attr);
     200             :     virtual std::string ToString() const;
     201             : };
     202             : 
     203             : struct ClusterListSpec : public BgpAttribute {
     204             :     static const int kSize = -1;
     205             :     static const uint8_t kFlags = Optional;
     206          16 :     ClusterListSpec() : BgpAttribute(ClusterList, kFlags) { }
     207           3 :     explicit ClusterListSpec(const BgpAttribute &rhs) : BgpAttribute(rhs) { }
     208          24 :     explicit ClusterListSpec(const ClusterListSpec &rhs)
     209          24 :         : BgpAttribute(BgpAttribute::ClusterList, kFlags) {
     210          24 :         cluster_list = rhs.cluster_list;
     211          24 :     }
     212             :     ClusterListSpec(uint32_t cluster_id, const ClusterListSpec *rhs);
     213             :     virtual int CompareTo(const BgpAttribute &rhs) const;
     214             :     virtual void ToCanonical(BgpAttr *attr);
     215             :     virtual std::string ToString() const;
     216             :     bool ClusterListLoop(uint32_t cluster_id) const;
     217             :     std::vector<uint32_t> cluster_list;
     218             : };
     219             : 
     220             : class ClusterList {
     221             : public:
     222             :     ClusterList(ClusterListDB *cluster_list_db, const ClusterListSpec &spec);
     223          22 :     ~ClusterList() { }
     224             :     void Remove();
     225          44 :     int CompareTo(const ClusterList &rhs) const {
     226          44 :         return spec_.CompareTo(rhs.cluster_list());
     227             :     }
     228             : 
     229          48 :     const ClusterListSpec &cluster_list() const { return spec_; }
     230          16 :     size_t size() const { return spec_.cluster_list.size(); }
     231             : 
     232           0 :     friend std::size_t hash_value(const ClusterList &cluster_list) {
     233           0 :         size_t hash = 0;
     234           0 :         return hash;
     235             :     }
     236             : 
     237             : private:
     238             :     friend int intrusive_ptr_add_ref(const ClusterList *ccluster_list);
     239             :     friend int intrusive_ptr_del_ref(const ClusterList *ccluster_list);
     240             :     friend void intrusive_ptr_release(const ClusterList *ccluster_list);
     241             :     friend class ClusterListDB;
     242             : 
     243             :     mutable std::atomic<int> refcount_;
     244             :     ClusterListDB *cluster_list_db_;
     245             :     ClusterListSpec spec_;
     246             : };
     247             : 
     248          47 : inline int intrusive_ptr_add_ref(const ClusterList *ccluster_list) {
     249          94 :     return ccluster_list->refcount_.fetch_add(1);
     250             : }
     251             : 
     252          18 : inline int intrusive_ptr_del_ref(const ClusterList *ccluster_list) {
     253          36 :     return ccluster_list->refcount_.fetch_sub(1);
     254             : }
     255             : 
     256          29 : inline void intrusive_ptr_release(const ClusterList *ccluster_list) {
     257          29 :     int prev = ccluster_list->refcount_.fetch_sub(1);
     258          29 :     if (prev == 1) {
     259          18 :         ClusterList *cluster_list = const_cast<ClusterList *>(ccluster_list);
     260          18 :         cluster_list->Remove();
     261          18 :         assert(cluster_list->refcount_ == 0);
     262          18 :         delete cluster_list;
     263             :     }
     264          29 : }
     265             : 
     266             : typedef boost::intrusive_ptr<ClusterList> ClusterListPtr;
     267             : 
     268             : struct ClusterListCompare {
     269          40 :     bool operator()(const ClusterList *lhs, const ClusterList *rhs) const {
     270          40 :         return lhs->CompareTo(*rhs) < 0;
     271             :     }
     272             : };
     273             : 
     274             : class ClusterListDB : public BgpPathAttributeDB<ClusterList, ClusterListPtr,
     275             :                                                 ClusterListSpec,
     276             :                                                 ClusterListCompare,
     277             :                                                 ClusterListDB> {
     278             : public:
     279             :     explicit ClusterListDB(BgpServer *server);
     280             : };
     281             : 
     282             : struct BgpMpNlri : public BgpAttribute {
     283             :     static const int kSize = -1;
     284             :     static const uint8_t kFlags = Optional;
     285             :     // Always using extended length for MP NLRI
     286       65062 :     BgpMpNlri() : BgpAttribute(0, ExtendedLength|kFlags), afi(0), safi(0) {}
     287          14 :     explicit BgpMpNlri(BgpAttribute::Code code) :
     288          14 :             BgpAttribute(code, ExtendedLength|kFlags), afi(0), safi(0) {}
     289      110980 :     explicit BgpMpNlri(BgpAttribute::Code code, uint16_t afi, uint8_t safi,
     290      110980 :                        std::vector<uint8_t> nh) :
     291      110979 :             BgpAttribute(code, ExtendedLength|kFlags), afi(afi), safi(safi),
     292      110980 :                        nexthop(nh) {}
     293       58231 :     explicit BgpMpNlri(BgpAttribute::Code code, uint16_t afi, uint8_t safi) :
     294       58231 :         BgpAttribute(code, ExtendedLength|kFlags), afi(afi), safi(safi) {
     295       58230 :         nexthop.clear();
     296       58230 :     }
     297      160938 :     explicit BgpMpNlri(const BgpAttribute &rhs)
     298      160938 :         : BgpAttribute(rhs), afi(0), safi(0) {
     299      160938 :     }
     300      729528 :     ~BgpMpNlri() {
     301      395243 :         STLDeleteValues(&nlri);
     302      729510 :     }
     303             :     virtual int CompareTo(const BgpAttribute &rhs_attr) const;
     304             :     virtual void ToCanonical(BgpAttr *attr);
     305             :     virtual size_t EncodeLength() const;
     306             : 
     307             :     uint16_t afi;
     308             :     uint8_t safi;
     309             :     std::vector<uint8_t> nexthop;
     310             : 
     311             :     std::vector<BgpProtoPrefix *> nlri;
     312             : };
     313             : 
     314             : struct PmsiTunnelSpec : public BgpAttribute {
     315             :     enum Flags {
     316             :         LeafInfoRequired = 1 << 0,
     317             :         AssistedReplicationType = 3 << 3,
     318             :         EdgeReplicationSupported = 1 << 7
     319             :     };
     320             : 
     321             :     enum ARType {
     322             :         RegularNVE = 0 << 3,
     323             :         ARReplicator = 1 << 3,
     324             :         ARLeaf = 2 << 3
     325             :     };
     326             : 
     327             :     enum Type {
     328             :         NoTunnelInfo = 0,
     329             :         RsvpP2mpLsp = 1,
     330             :         LdpP2mpLsp = 2,
     331             :         PimSsmTree = 3,
     332             :         PimSmTree = 4,
     333             :         BidirPimTree = 5,
     334             :         IngressReplication = 6,
     335             :         MldpMp2mpLsp = 7,
     336             :         AssistedReplicationContrail = 252
     337             :     };
     338             : 
     339             :     static const int kSize = -1;
     340             :     static const uint8_t kFlags = Optional | Transitive;
     341             : 
     342             :     PmsiTunnelSpec();
     343             :     explicit PmsiTunnelSpec(const BgpAttribute &rhs);
     344             : 
     345             :     virtual int CompareTo(const BgpAttribute &rhs_attr) const;
     346             :     virtual void ToCanonical(BgpAttr *attr);
     347             :     virtual std::string ToString() const;
     348             : 
     349             :     uint32_t GetLabel(const ExtCommunity *ext) const;
     350             :     void SetLabel(uint32_t label, const ExtCommunity *ext);
     351             :     Ip4Address GetIdentifier() const;
     352             :     void SetIdentifier(Ip4Address identifier);
     353             : 
     354             :     std::string GetTunnelTypeString() const;
     355             :     std::string GetTunnelArTypeString() const;
     356             :     std::vector<std::string> GetTunnelFlagsStrings() const;
     357             : 
     358             :     uint8_t tunnel_flags;
     359             :     uint8_t tunnel_type;
     360             :     uint32_t label;
     361             :     std::vector<uint8_t> identifier;
     362             : };
     363             : 
     364             : class PmsiTunnel {
     365             : public:
     366             :     PmsiTunnel(PmsiTunnelDB *pmsi_tunnel_db, const PmsiTunnelSpec &pmsi_spec);
     367       34828 :     virtual ~PmsiTunnel() { }
     368             :     virtual void Remove();
     369      478000 :     int CompareTo(const PmsiTunnel &rhs) const {
     370      478000 :         return pmsi_spec_.CompareTo(rhs.pmsi_tunnel());
     371             :     }
     372             : 
     373      478833 :     const PmsiTunnelSpec &pmsi_tunnel() const { return pmsi_spec_; }
     374             :     uint32_t GetLabel(const ExtCommunity *ext) const;
     375             : 
     376           0 :     friend std::size_t hash_value(const PmsiTunnel &pmsi_tunnel) {
     377           0 :         size_t hash = 0;
     378           0 :         boost::hash_combine(hash, pmsi_tunnel.pmsi_tunnel().ToString());
     379           0 :         return hash;
     380             :     }
     381             : 
     382      117158 :     const uint8_t tunnel_flags() const { return tunnel_flags_; }
     383       27713 :     const uint8_t tunnel_type() const { return tunnel_type_; }
     384       52373 :     const Ip4Address identifier() const { return identifier_; }
     385        4116 :     const uint32_t label() const { return label_; }
     386             : 
     387             : private:
     388             :     friend int intrusive_ptr_add_ref(const PmsiTunnel *cpmsi_tunnel);
     389             :     friend int intrusive_ptr_del_ref(const PmsiTunnel *cpmsi_tunnel);
     390             :     friend void intrusive_ptr_release(const PmsiTunnel *cpmsi_tunnel);
     391             :     friend class PmsiTunnelDB;
     392             : 
     393             :     uint8_t tunnel_flags_;
     394             :     uint8_t tunnel_type_;
     395             :     Ip4Address identifier_;
     396             :     uint32_t label_;
     397             :     mutable std::atomic<int> refcount_;
     398             :     PmsiTunnelDB *pmsi_tunnel_db_;
     399             :     PmsiTunnelSpec pmsi_spec_;
     400             : };
     401             : 
     402      366770 : inline int intrusive_ptr_add_ref(const PmsiTunnel *cpmsi_tunnel) {
     403      733540 :     return cpmsi_tunnel->refcount_.fetch_add(1);
     404             : }
     405             : 
     406      219883 : inline int intrusive_ptr_del_ref(const PmsiTunnel *cpmsi_tunnel) {
     407      439766 :     return cpmsi_tunnel->refcount_.fetch_sub(1);
     408             : }
     409             : 
     410      146881 : inline void intrusive_ptr_release(const PmsiTunnel *cpmsi_tunnel) {
     411      146881 :     int prev = cpmsi_tunnel->refcount_.fetch_sub(1);
     412      146881 :     if (prev == 1) {
     413        4965 :         PmsiTunnel *pmsi_tunnel = const_cast<PmsiTunnel *>(cpmsi_tunnel);
     414        4965 :         pmsi_tunnel->Remove();
     415        4965 :         assert(pmsi_tunnel->refcount_ == 0);
     416        4965 :         delete pmsi_tunnel;
     417             :     }
     418      146881 : }
     419             : 
     420             : typedef boost::intrusive_ptr<PmsiTunnel> PmsiTunnelPtr;
     421             : 
     422             : struct PmsiTunnelCompare {
     423      477995 :     bool operator()(const PmsiTunnel *lhs, const PmsiTunnel *rhs) const {
     424      477995 :         return lhs->CompareTo(*rhs) < 0;
     425             :     }
     426             : };
     427             : 
     428             : class PmsiTunnelDB : public BgpPathAttributeDB<PmsiTunnel, PmsiTunnelPtr,
     429             :                                                PmsiTunnelSpec,
     430             :                                                PmsiTunnelCompare,
     431             :                                                PmsiTunnelDB> {
     432             : public:
     433             :     explicit PmsiTunnelDB(BgpServer *server);
     434             : };
     435             : 
     436             : struct EdgeDiscoverySpec : public BgpAttribute {
     437             :     static const int kSize = -1;
     438             :     static const uint8_t kFlags = Optional | Transitive;
     439             :     EdgeDiscoverySpec();
     440             :     explicit EdgeDiscoverySpec(const BgpAttribute &rhs);
     441             :     explicit EdgeDiscoverySpec(const EdgeDiscoverySpec &rhs);
     442             :     ~EdgeDiscoverySpec();
     443             : 
     444             :     virtual int CompareTo(const BgpAttribute &rhs_attr) const;
     445             :     virtual void ToCanonical(BgpAttr *attr);
     446             :     virtual std::string ToString() const;
     447             :     virtual size_t EncodeLength() const;
     448             : 
     449             :     struct Edge : public ParseObject {
     450             :         Ip4Address GetIp4Address() const;
     451             :         void SetIp4Address(Ip4Address addr);
     452             :         void GetLabels(uint32_t *first_label, uint32_t *last_label) const;
     453             :         void SetLabels(uint32_t first_label, uint32_t last_label);
     454             : 
     455             :         std::vector<uint8_t> address;
     456             :         std::vector<uint32_t> labels;
     457             :     };
     458             :     typedef std::vector<Edge *> EdgeList;
     459             :     EdgeList edge_list;
     460             : };
     461             : 
     462             : class EdgeDiscovery {
     463             : public:
     464             :     EdgeDiscovery(EdgeDiscoveryDB *edge_discovery_db,
     465             :         const EdgeDiscoverySpec &edspec);
     466             :     virtual ~EdgeDiscovery();
     467             :     virtual void Remove();
     468             :     int CompareTo(const EdgeDiscovery &rhs) const;
     469             : 
     470        1052 :     const EdgeDiscoverySpec &edge_discovery() const { return edspec_; }
     471             : 
     472           0 :     friend std::size_t hash_value(const EdgeDiscovery &edge_discovery) {
     473           0 :         size_t hash = 0;
     474           0 :         boost::hash_combine(hash, edge_discovery.edge_discovery().ToString());
     475           0 :         return hash;
     476             :     }
     477             : 
     478             :     struct Edge {
     479             :         explicit Edge(const EdgeDiscoverySpec::Edge *edge_spec);
     480             :         Ip4Address address;
     481             :         LabelBlockPtr label_block;
     482             :         bool operator<(const Edge &rhs) const;
     483             :     };
     484             :     typedef std::vector<Edge *> EdgeList;
     485             : 
     486             :     struct EdgeCompare {
     487        8439 :         bool operator()(const Edge *lhs, const Edge *rhs) const {
     488        8439 :             BOOL_KEY_COMPARE(*lhs, *rhs);
     489        8408 :             return false;
     490             :         }
     491             :     };
     492             : 
     493             :     EdgeList edge_list;
     494             : 
     495             : private:
     496             :     friend int intrusive_ptr_add_ref(const EdgeDiscovery *ediscovery);
     497             :     friend int intrusive_ptr_del_ref(const EdgeDiscovery *ediscovery);
     498             :     friend void intrusive_ptr_release(const EdgeDiscovery *ediscovery);
     499             :     friend class EdgeDiscoveryDB;
     500             : 
     501             :     mutable std::atomic<int> refcount_;
     502             :     EdgeDiscoveryDB *edge_discovery_db_;
     503             :     EdgeDiscoverySpec edspec_;
     504             : };
     505             : 
     506      493252 : inline int intrusive_ptr_add_ref(const EdgeDiscovery *cediscovery) {
     507      986504 :     return cediscovery->refcount_.fetch_add(1);
     508             : }
     509             : 
     510      483409 : inline int intrusive_ptr_del_ref(const EdgeDiscovery *cediscovery) {
     511      966818 :     return cediscovery->refcount_.fetch_sub(1);
     512             : }
     513             : 
     514        9837 : inline void intrusive_ptr_release(const EdgeDiscovery *cediscovery) {
     515        9837 :     int prev = cediscovery->refcount_.fetch_sub(1);
     516        9837 :     if (prev == 1) {
     517        1844 :         EdgeDiscovery *ediscovery = const_cast<EdgeDiscovery *>(cediscovery);
     518        1844 :         ediscovery->Remove();
     519        1844 :         assert(ediscovery->refcount_ == 0);
     520        1844 :         delete ediscovery;
     521             :     }
     522        9837 : }
     523             : 
     524             : typedef boost::intrusive_ptr<EdgeDiscovery> EdgeDiscoveryPtr;
     525             : 
     526             : struct EdgeDiscoveryCompare {
     527      975780 :     bool operator()(const EdgeDiscovery *lhs, const EdgeDiscovery *rhs) const {
     528      975780 :         return lhs->CompareTo(*rhs) < 0;
     529             :     }
     530             : };
     531             : 
     532             : class EdgeDiscoveryDB : public BgpPathAttributeDB<EdgeDiscovery,
     533             :                                                   EdgeDiscoveryPtr,
     534             :                                                   EdgeDiscoverySpec,
     535             :                                                   EdgeDiscoveryCompare,
     536             :                                                   EdgeDiscoveryDB> {
     537             : public:
     538             :     explicit EdgeDiscoveryDB(BgpServer *server);
     539             : };
     540             : 
     541             : struct EdgeForwardingSpec : public BgpAttribute {
     542             :     static const int kSize = -1;
     543             :     static const uint8_t kFlags = Optional | Transitive;
     544             :     EdgeForwardingSpec();
     545             :     explicit EdgeForwardingSpec(const BgpAttribute &rhs);
     546             :     explicit EdgeForwardingSpec(const EdgeForwardingSpec &rhs);
     547             :     ~EdgeForwardingSpec();
     548             : 
     549             :     virtual int CompareTo(const BgpAttribute &rhs_attr) const;
     550             :     virtual void ToCanonical(BgpAttr *attr);
     551             :     virtual std::string ToString() const;
     552             :     virtual size_t EncodeLength() const;
     553             : 
     554             :     struct Edge : public ParseObject {
     555             :         Ip4Address GetInboundIp4Address() const;
     556             :         Ip4Address GetOutboundIp4Address() const;
     557             :         void SetInboundIp4Address(Ip4Address addr);
     558             :         void SetOutboundIp4Address(Ip4Address addr);
     559             : 
     560             :         int address_len;
     561             :         std::vector<uint8_t> inbound_address, outbound_address;
     562             :         uint32_t inbound_label, outbound_label;
     563             :     };
     564             :     typedef std::vector<Edge *> EdgeList;
     565             : 
     566             :     EdgeList edge_list;
     567             : };
     568             : 
     569             : class EdgeForwarding {
     570             : public:
     571             :     EdgeForwarding(EdgeForwardingDB *edge_forwarding_db,
     572             :         const EdgeForwardingSpec &efspec);
     573             :     virtual ~EdgeForwarding();
     574             :     virtual void Remove();
     575             :     int CompareTo(const EdgeForwarding &rhs) const;
     576             : 
     577        1727 :     const EdgeForwardingSpec &edge_forwarding() const { return efspec_; }
     578             : 
     579           0 :     friend std::size_t hash_value(const EdgeForwarding &edge_forwarding) {
     580           0 :         size_t hash = 0;
     581           0 :         boost::hash_combine(hash, edge_forwarding.edge_forwarding().ToString());
     582           0 :         return hash;
     583             :     }
     584             : 
     585             :     struct Edge {
     586             :         explicit Edge(const EdgeForwardingSpec::Edge *edge_spec);
     587             :         bool operator<(const Edge &rhs) const;
     588             :         Ip4Address inbound_address, outbound_address;
     589             :         uint32_t inbound_label, outbound_label;
     590             :     };
     591             :     typedef std::vector<Edge *> EdgeList;
     592             : 
     593             :     struct EdgeCompare {
     594        1437 :         bool operator()(const Edge *lhs, const Edge *rhs) const {
     595        1437 :             BOOL_KEY_COMPARE(*lhs, *rhs);
     596           0 :             return false;
     597             :         }
     598             :     };
     599             : 
     600             :     EdgeList edge_list;
     601             : 
     602             : private:
     603             :     friend int intrusive_ptr_add_ref(const EdgeForwarding *ceforwarding);
     604             :     friend int intrusive_ptr_del_ref(const EdgeForwarding *ceforwarding);
     605             :     friend void intrusive_ptr_release(const EdgeForwarding *ceforwarding);
     606             :     friend class EdgeForwardingDB;
     607             : 
     608             :     mutable std::atomic<int> refcount_;
     609             :     EdgeForwardingDB *edge_forwarding_db_;
     610             :     EdgeForwardingSpec efspec_;
     611             : };
     612             : 
     613      303178 : inline int intrusive_ptr_add_ref(const EdgeForwarding *ceforwarding) {
     614      606356 :     return ceforwarding->refcount_.fetch_add(1);
     615             : }
     616             : 
     617      289415 : inline int intrusive_ptr_del_ref(const EdgeForwarding *ceforwarding) {
     618      578830 :     return ceforwarding->refcount_.fetch_sub(1);
     619             : }
     620             : 
     621       13756 : inline void intrusive_ptr_release(const EdgeForwarding *ceforwarding) {
     622       13756 :     int prev = ceforwarding->refcount_.fetch_sub(1);
     623       13756 :     if (prev == 1) {
     624        2331 :         EdgeForwarding *eforwarding =
     625             :             const_cast<EdgeForwarding *>(ceforwarding);
     626        2331 :         eforwarding->Remove();
     627        2331 :         assert(eforwarding->refcount_ == 0);
     628        2331 :         delete eforwarding;
     629             :     }
     630       13756 : }
     631             : 
     632             : typedef boost::intrusive_ptr<EdgeForwarding> EdgeForwardingPtr;
     633             : 
     634             : struct EdgeForwardingCompare {
     635      592168 :     bool operator()(const EdgeForwarding *lhs, const EdgeForwarding *rhs) const {
     636      592168 :         return lhs->CompareTo(*rhs) < 0;
     637             :     }
     638             : };
     639             : 
     640             : class EdgeForwardingDB : public BgpPathAttributeDB<EdgeForwarding,
     641             :                                                    EdgeForwardingPtr,
     642             :                                                    EdgeForwardingSpec,
     643             :                                                    EdgeForwardingCompare,
     644             :                                                    EdgeForwardingDB> {
     645             : public:
     646             :     explicit EdgeForwardingDB(BgpServer *server);
     647             : };
     648             : 
     649             : struct BgpAttrLabelBlock : public BgpAttribute {
     650             :     static const int kSize = 0;
     651             :     BgpAttrLabelBlock() : BgpAttribute(0, BgpAttribute::LabelBlock, 0) {}
     652             :     explicit BgpAttrLabelBlock(const BgpAttribute &rhs) : BgpAttribute(rhs) {}
     653        1036 :     explicit BgpAttrLabelBlock(LabelBlockPtr label_block)
     654        1036 :         : BgpAttribute(0, BgpAttribute::LabelBlock, 0),
     655        1036 :           label_block(label_block) {
     656        1036 :     }
     657             :     LabelBlockPtr label_block;
     658             :     virtual int CompareTo(const BgpAttribute &rhs_attr) const;
     659             :     virtual void ToCanonical(BgpAttr *attr);
     660             :     virtual std::string ToString() const;
     661             : };
     662             : 
     663             : class BgpOListElem {
     664             : public:
     665       23171 :     BgpOListElem(Ip4Address address, uint32_t label,
     666             :         std::vector<std::string> encap = std::vector<std::string>())
     667       23171 :         : address(address), label(label), encap(encap) {
     668       23171 :     }
     669             : 
     670             :     bool operator<(const BgpOListElem &rhs) const;
     671             : 
     672             :     Ip4Address address;
     673             :     uint32_t label;
     674             :     std::vector<std::string> encap;
     675             : };
     676             : 
     677             : struct BgpOListElemCompare {
     678       32147 :     bool operator()(const BgpOListElem *lhs, const BgpOListElem *rhs) const {
     679       32147 :         BOOL_KEY_COMPARE(*lhs, *rhs);
     680           0 :         return false;
     681             :     }
     682             : };
     683             : 
     684             : struct BgpOListSpec : public BgpAttribute {
     685             :     static const int kSize = 0;
     686        1025 :     BgpOListSpec() : BgpAttribute(0, BgpAttribute::OList, 0) {}
     687       18624 :     explicit BgpOListSpec(uint8_t subcode) : BgpAttribute(0, subcode, 0) {}
     688             : 
     689             :     virtual int CompareTo(const BgpAttribute &rhs_attr) const;
     690             :     virtual void ToCanonical(BgpAttr *attr);
     691             :     virtual std::string ToString() const;
     692             : 
     693             :     typedef std::vector<BgpOListElem> Elements;
     694             :     Elements elements;
     695             : };
     696             : 
     697             : class BgpOList {
     698             : public:
     699             :     BgpOList(BgpOListDB *olist_db, const BgpOListSpec &olist_spec);
     700             :     virtual ~BgpOList();
     701             :     virtual void Remove();
     702             :     int CompareTo(const BgpOList &rhs) const;
     703             : 
     704     2697897 :     const BgpOListSpec &olist() const { return olist_spec_; }
     705             : 
     706           0 :     friend std::size_t hash_value(const BgpOList &olist) {
     707           0 :         size_t hash = 0;
     708           0 :         boost::hash_combine(hash, olist.olist().ToString());
     709           0 :         return hash;
     710             :     }
     711             : 
     712             :     typedef std::vector<BgpOListElem *> Elements;
     713             : 
     714     2672133 :     const Elements &elements() const { return elements_; }
     715             : 
     716             : private:
     717             :     friend int intrusive_ptr_add_ref(const BgpOList *colist);
     718             :     friend int intrusive_ptr_del_ref(const BgpOList *colist);
     719             :     friend void intrusive_ptr_release(const BgpOList *colist);
     720             :     friend class BgpOListDB;
     721             : 
     722             :     Elements elements_;
     723             :     mutable std::atomic<int> refcount_;
     724             :     BgpOListDB *olist_db_;
     725             :     BgpOListSpec olist_spec_;
     726             : };
     727             : 
     728      537306 : inline int intrusive_ptr_add_ref(const BgpOList *colist) {
     729     1074612 :     return colist->refcount_.fetch_add(1);
     730             : }
     731             : 
     732      297337 : inline int intrusive_ptr_del_ref(const BgpOList *colist) {
     733      594674 :     return colist->refcount_.fetch_sub(1);
     734             : }
     735             : 
     736      239965 : inline void intrusive_ptr_release(const BgpOList *colist) {
     737      239965 :     int prev = colist->refcount_.fetch_sub(1);
     738      239965 :     if (prev == 1) {
     739        9672 :         BgpOList *olist = const_cast<BgpOList *>(colist);
     740        9672 :         olist->Remove();
     741        9672 :         assert(olist->refcount_ == 0);
     742        9672 :         delete olist;
     743             :     }
     744      239965 : }
     745             : 
     746             : typedef boost::intrusive_ptr<BgpOList> BgpOListPtr;
     747             : 
     748             : struct BgpOListCompare {
     749      627341 :     bool operator()(const BgpOList *lhs, const BgpOList *rhs) const {
     750      627341 :         return lhs->CompareTo(*rhs) < 0;
     751             :     }
     752             : };
     753             : 
     754             : class BgpOListDB : public BgpPathAttributeDB<BgpOList,
     755             :                                              BgpOListPtr,
     756             :                                              BgpOListSpec,
     757             :                                              BgpOListCompare,
     758             :                                              BgpOListDB> {
     759             : public:
     760             :     explicit BgpOListDB(BgpServer *server);
     761             : };
     762             : 
     763             : struct BgpAttrUnknown : public BgpAttribute {
     764        3972 :     BgpAttrUnknown() : BgpAttribute() {}
     765        2566 :     explicit BgpAttrUnknown(const BgpAttribute &rhs) : BgpAttribute(rhs) {}
     766             :     std::vector<uint8_t> value;
     767             : };
     768             : 
     769             : struct BgpAttrSourceRd : public BgpAttribute {
     770       35986 :     BgpAttrSourceRd() : BgpAttribute(0, SourceRd, 0) {}
     771             :     explicit BgpAttrSourceRd(const BgpAttribute &rhs) : BgpAttribute(rhs) {}
     772       42635 :     explicit BgpAttrSourceRd(const RouteDistinguisher &source_rd)
     773       42635 :         : BgpAttribute(0, SourceRd, 0), source_rd(source_rd) {
     774       42635 :     }
     775             :     RouteDistinguisher source_rd;
     776             :     virtual int CompareTo(const BgpAttribute &rhs_attr) const;
     777             :     virtual void ToCanonical(BgpAttr *attr);
     778             :     virtual std::string ToString() const;
     779             : };
     780             : 
     781             : struct BgpAttrEsi : public BgpAttribute {
     782             :     BgpAttrEsi() : BgpAttribute(0, Esi, 0) {}
     783             :     explicit BgpAttrEsi(const BgpAttribute &rhs) : BgpAttribute(rhs) {}
     784          75 :     explicit BgpAttrEsi(const EthernetSegmentId &esi)
     785          75 :         : BgpAttribute(0, Esi, 0), esi(esi) {
     786          75 :     }
     787             :     EthernetSegmentId esi;
     788             :     virtual int CompareTo(const BgpAttribute &rhs_attr) const;
     789             :     virtual void ToCanonical(BgpAttr *attr);
     790             :     virtual std::string ToString() const;
     791             : };
     792             : 
     793             : struct BgpAttrSubProtocol : public BgpAttribute {
     794             :     BgpAttrSubProtocol() : BgpAttribute(0, SubProtocol, 0) {}
     795             :     explicit BgpAttrSubProtocol(const BgpAttribute &rhs) : BgpAttribute(rhs) {}
     796       22440 :     explicit BgpAttrSubProtocol(const std::string &sbp)
     797       22440 :         : BgpAttribute(0, SubProtocol, 0), sbp(sbp) {
     798       22440 :     }
     799             :     std::string sbp;
     800             :     virtual int CompareTo(const BgpAttribute &rhs_attr) const;
     801             :     virtual void ToCanonical(BgpAttr *attr);
     802             :     virtual std::string ToString() const;
     803             : };
     804             : 
     805             : struct BgpAttrParams : public BgpAttribute {
     806             :     enum Flags {
     807             :         TestFlag = 1 << 0
     808             :     };
     809             : 
     810             :     BgpAttrParams() : BgpAttribute(0, Params, 0), params(0) {}
     811             :     explicit BgpAttrParams(const BgpAttribute &rhs)
     812             :         : BgpAttribute(rhs), params(0) {
     813             :     }
     814           6 :     explicit BgpAttrParams(uint64_t params) :
     815           6 :             BgpAttribute(0, Params, 0), params(params) {}
     816             :     uint64_t params;
     817             :     virtual int CompareTo(const BgpAttribute &rhs_attr) const;
     818             :     virtual void ToCanonical(BgpAttr *attr);
     819             :     virtual std::string ToString() const;
     820             : };
     821             : 
     822             : typedef std::vector<BgpAttribute *> BgpAttrSpec;
     823             : 
     824             : // Canonicalized BGP attribute
     825             : class BgpAttr {
     826             : public:
     827             :     BgpAttr();
     828             :     explicit BgpAttr(BgpAttrDB *attr_db);
     829             :     explicit BgpAttr(const BgpAttr &rhs);
     830             :     BgpAttr(BgpAttrDB *attr_db, const BgpAttrSpec &spec);
     831     6833015 :     virtual ~BgpAttr() { }
     832             :     virtual void Remove();
     833             : 
     834             :     int CompareTo(const BgpAttr &rhs) const;
     835             : 
     836      184298 :     void set_origin(BgpAttrOrigin::OriginType org) { origin_ = org; }
     837      532115 :     void set_nexthop(IpAddress nexthop) { nexthop_ = nexthop; }
     838       80745 :     void set_med(uint32_t med) { med_ = med; }
     839      295454 :     void set_local_pref(uint32_t local_pref) { local_pref_ = local_pref; }
     840           9 :     void set_atomic_aggregate(bool ae) { atomic_aggregate_ = ae; }
     841          73 :     void set_aggregator(as_t as_num, IpAddress address) {
     842          73 :         aggregator_as_num_ = as_num;
     843          73 :         aggregator_address_ = address;
     844          73 :     }
     845          64 :     void set_as4_aggregator(as_t as_num, IpAddress address) {
     846          64 :         aggregator_as4_num_ = as_num;
     847          64 :         aggregator_address_ = address;
     848          64 :     }
     849      202877 :     void set_originator_id(Ip4Address originator_id) {
     850      202877 :         originator_id_ = originator_id;
     851      202876 :     }
     852      632829 :     void set_source_rd(const RouteDistinguisher &source_rd) {
     853      632829 :         source_rd_ = source_rd;
     854      632841 :     }
     855       17890 :     void set_esi(const EthernetSegmentId &esi) { esi_ = esi; }
     856           3 :     void set_params(uint64_t params) { params_ = params; }
     857             :     void set_as_path(AsPathPtr aspath);
     858             :     void set_as_path(const AsPathSpec *spec);
     859             :     void set_as4_path(As4PathPtr aspath);
     860             :     void set_as4_path(const As4PathSpec *spec);
     861             :     void set_aspath_4byte(AsPath4BytePtr aspath);
     862             :     void set_aspath_4byte(const AsPath4ByteSpec *spec);
     863             :     void set_cluster_list(const ClusterListSpec *spec);
     864             :     void set_community(CommunityPtr comm);
     865             :     void set_community(const CommunitySpec *comm);
     866             :     void set_ext_community(ExtCommunityPtr extcomm);
     867             :     void set_ext_community(const ExtCommunitySpec *extcomm);
     868             :     void set_large_community(LargeCommunityPtr largecomm);
     869             :     void set_large_community(const LargeCommunitySpec *largecomm);
     870             :     void set_origin_vn_path(OriginVnPathPtr ovnpath);
     871             :     void set_origin_vn_path(const OriginVnPathSpec *spec);
     872             :     void set_pmsi_tunnel(const PmsiTunnelSpec *pmsi_spec);
     873             :     void set_edge_discovery(const EdgeDiscoverySpec *edspec);
     874             :     void set_edge_forwarding(const EdgeForwardingSpec *efspec);
     875             :     void set_label_block(LabelBlockPtr label_block);
     876             :     void set_olist(const BgpOListSpec *olist_spec);
     877             :     void set_leaf_olist(const BgpOListSpec *leaf_olist_spec);
     878       24040 :     void set_sub_protocol(const std::string &sub_protocol) {
     879       24040 :         sub_protocol_ = sub_protocol;
     880       24040 :     }
     881             :     friend std::size_t hash_value(BgpAttr const &attr);
     882             : 
     883     9525659 :     BgpAttrOrigin::OriginType origin() const { return origin_; }
     884             :     static std::string OriginToString(BgpAttrOrigin::OriginType origin);
     885             :     static BgpAttrOrigin::OriginType OriginFromString(const std::string &bgp_origin_type);
     886             :     std::string origin_string() const;
     887             : 
     888     1010679 :     const IpAddress &nexthop() const { return nexthop_; }
     889             :     Address::Family nexthop_family() const;
     890     1664240 :     uint32_t med() const { return med_; }
     891    10245245 :     uint32_t local_pref() const { return local_pref_; }
     892      110978 :     bool atomic_aggregate() const { return atomic_aggregate_; }
     893      358444 :     as_t aggregator_as_num() const { return aggregator_as_num_; }
     894          64 :     as_t aggregator_as4_num() const { return aggregator_as4_num_; }
     895             :     as_t neighbor_as() const;
     896          50 :     const IpAddress &aggregator_adderess() const { return aggregator_address_; }
     897      524820 :     const Ip4Address &originator_id() const { return originator_id_; }
     898      166137 :     const RouteDistinguisher &source_rd() const { return source_rd_; }
     899       43021 :     const EthernetSegmentId &esi() const { return esi_; }
     900           3 :     uint64_t params() const { return params_; }
     901     1626008 :     const AsPath *as_path() const { return as_path_.get(); }
     902     9335938 :     int as_path_count() const { return as_path_ ? as_path_->AsCount() : 0; }
     903             :     int max_as_path_count() const;
     904      443836 :     const AsPath4Byte *aspath_4byte() const { return aspath_4byte_.get(); }
     905     9331141 :     int aspath_4byte_count() const {
     906     9331141 :         return aspath_4byte_ ? aspath_4byte_->AsCount() : 0;
     907             :     }
     908             :     int IsAsPathLoop(as_t asn, uint8_t max_loop_count = 0) const;
     909      116597 :     const ClusterList *cluster_list() const { return cluster_list_.get(); }
     910      320157 :     size_t cluster_list_length() const {
     911      320157 :         return cluster_list_ ? cluster_list_->size() : 0;
     912             :     }
     913      117849 :     const As4Path *as4_path() const { return as4_path_.get(); }
     914         125 :     int as4_path_count() const { return as4_path_ ? as4_path_->AsCount() : 0; }
     915             :      bool IsAsPathEmpty() const;
     916     6694911 :     const Community *community() const { return community_.get(); }
     917     3922354 :     const ExtCommunity *ext_community() const { return ext_community_.get(); }
     918      680141 :     const LargeCommunity *large_community() const {
     919      680141 :         return large_community_.get();
     920             :     }
     921     4352884 :     const OriginVnPath *origin_vn_path() const { return origin_vn_path_.get(); }
     922      225405 :     const PmsiTunnel *pmsi_tunnel() const { return pmsi_tunnel_.get(); }
     923      127961 :     const EdgeDiscovery *edge_discovery() const {
     924      127961 :         return edge_discovery_.get();
     925             :     }
     926      126396 :     const EdgeForwarding *edge_forwarding() const {
     927      126396 :         return edge_forwarding_.get();
     928             :     }
     929       11166 :     LabelBlockPtr label_block() const { return label_block_; }
     930      224999 :     BgpOListPtr olist() const { return olist_; }
     931       14210 :     BgpOListPtr leaf_olist() const { return leaf_olist_; }
     932       30547 :     const std::string &sub_protocol() const { return sub_protocol_; }
     933      247993 :     BgpAttrDB *attr_db() { return attr_db_; }
     934     2355287 :     const BgpAttrDB *attr_db() const { return attr_db_; }
     935             :     uint32_t sequence_number() const;
     936             :     bool evpn_sticky_mac() const;
     937             :     bool etree_leaf() const;
     938             :     bool evpn_single_active() const;
     939             :     MacAddress mac_address() const;
     940             : 
     941             : private:
     942             :     friend class BgpAttrDB;
     943             :     friend class BgpAttrTest;
     944             :     friend int intrusive_ptr_add_ref(const BgpAttr *cattrp);
     945             :     friend int intrusive_ptr_del_ref(const BgpAttr *cattrp);
     946             :     friend void intrusive_ptr_release(const BgpAttr *cattrp);
     947             : 
     948             :     mutable std::atomic<int> refcount_;
     949             :     BgpAttrDB *attr_db_;
     950             :     BgpAttrOrigin::OriginType origin_;
     951             :     IpAddress nexthop_;
     952             :     uint32_t med_;
     953             :     uint32_t local_pref_;
     954             :     bool atomic_aggregate_;
     955             :     as_t aggregator_as_num_;
     956             :     as_t aggregator_as4_num_;
     957             :     IpAddress aggregator_address_;
     958             :     Ip4Address originator_id_;
     959             :     RouteDistinguisher source_rd_;
     960             :     EthernetSegmentId esi_;
     961             :     uint64_t params_;
     962             :     AsPathPtr as_path_;
     963             :     AsPath4BytePtr aspath_4byte_;
     964             :     As4PathPtr as4_path_;
     965             :     ClusterListPtr cluster_list_;
     966             :     CommunityPtr community_;
     967             :     ExtCommunityPtr ext_community_;
     968             :     LargeCommunityPtr large_community_;
     969             :     std::unique_ptr<LargeCommunitySpec> deferred_large_spec_;
     970             :     OriginVnPathPtr origin_vn_path_;
     971             :     PmsiTunnelPtr pmsi_tunnel_;
     972             :     EdgeDiscoveryPtr edge_discovery_;
     973             :     EdgeForwardingPtr edge_forwarding_;
     974             :     LabelBlockPtr label_block_;
     975             :     BgpOListPtr olist_;
     976             :     BgpOListPtr leaf_olist_;
     977             :     std::string sub_protocol_;
     978             : };
     979             : 
     980    17948853 : inline int intrusive_ptr_add_ref(const BgpAttr *cattrp) {
     981    35897706 :     return cattrp->refcount_.fetch_add(1);
     982             : }
     983             : 
     984     3561174 : inline int intrusive_ptr_del_ref(const BgpAttr *cattrp) {
     985     7122348 :     return cattrp->refcount_.fetch_sub(1);
     986             : }
     987             : 
     988    14390837 : inline void intrusive_ptr_release(const BgpAttr *cattrp) {
     989    14390837 :     int prev = cattrp->refcount_.fetch_sub(1);
     990    14390837 :     if (prev == 1) {
     991      438945 :         BgpAttr *attrp = const_cast<BgpAttr *>(cattrp);
     992      438945 :         attrp->Remove();
     993      438946 :         assert(attrp->refcount_ == 0);
     994      438943 :         delete attrp;
     995             :     }
     996    14390825 : }
     997             : 
     998             : typedef boost::intrusive_ptr<const BgpAttr> BgpAttrPtr;
     999             : 
    1000             : struct BgpAttrCompare {
    1001    25545178 :     bool operator()(const BgpAttr *lhs, const BgpAttr *rhs) const {
    1002    25545178 :         return lhs->CompareTo(*rhs) < 0;
    1003             :     }
    1004             : };
    1005             : 
    1006             : class BgpAttrDB : public BgpPathAttributeDB<BgpAttr, BgpAttrPtr, BgpAttrSpec,
    1007             :                                             BgpAttrCompare, BgpAttrDB> {
    1008             : public:
    1009             :     explicit BgpAttrDB(BgpServer *server);
    1010             :     BgpAttrPtr ReplaceAsPathAndLocate(const BgpAttr *attr,
    1011             :                                       AsPathPtr aspath);
    1012             :     BgpAttrPtr ReplaceCommunityAndLocate(const BgpAttr *attr,
    1013             :                                          CommunityPtr community);
    1014             :     BgpAttrPtr ReplaceOriginAndLocate(const BgpAttr *attr,
    1015             :                                       BgpAttrOrigin::OriginType origin);
    1016             :     BgpAttrPtr ReplaceExtCommunityAndLocate(const BgpAttr *attr,
    1017             :                                             ExtCommunityPtr extcomm);
    1018             :     BgpAttrPtr ReplaceLargeCommunityAndLocate(const BgpAttr *attr,
    1019             :                                             LargeCommunityPtr largecomm);
    1020             :     BgpAttrPtr ReplaceOriginVnPathAndLocate(const BgpAttr *attr,
    1021             :                                             OriginVnPathPtr ovnpath);
    1022             :     BgpAttrPtr ReplaceLocalPreferenceAndLocate(const BgpAttr *attr,
    1023             :                                                uint32_t local_pref);
    1024             :     BgpAttrPtr ReplaceOriginatorIdAndLocate(const BgpAttr *attr,
    1025             :                                             Ip4Address originator_id);
    1026             :     BgpAttrPtr ReplaceSourceRdAndLocate(const BgpAttr *attr,
    1027             :                                         const RouteDistinguisher &source_rd);
    1028             :     BgpAttrPtr ReplaceEsiAndLocate(const BgpAttr *attr,
    1029             :                                    const EthernetSegmentId &esi);
    1030             :     BgpAttrPtr ReplaceOListAndLocate(const BgpAttr *attr,
    1031             :                                      const BgpOListSpec *olist_spec);
    1032             :     BgpAttrPtr ReplaceLeafOListAndLocate(const BgpAttr *attr,
    1033             :                                          const BgpOListSpec *leaf_olist_spec);
    1034             :     BgpAttrPtr ReplacePmsiTunnelAndLocate(const BgpAttr *attr,
    1035             :                                           const PmsiTunnelSpec *pmsi_spec);
    1036             :     BgpAttrPtr ReplaceNexthopAndLocate(const BgpAttr *attr,
    1037             :                                        const IpAddress &addr);
    1038             :     BgpAttrPtr ReplaceSubProtocolAndLocate(const BgpAttr *attr,
    1039             :                                            const std::string &sbp);
    1040      769965 :     BgpServer *server() { return server_; }
    1041     2355284 :     const BgpServer *server() const { return server_; }
    1042             : 
    1043             : private:
    1044             :     BgpServer *server_;
    1045             : };
    1046             : 
    1047             : #endif  // SRC_BGP_BGP_ATTR_H_

Generated by: LCOV version 1.14