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

Generated by: LCOV version 1.14