LCOV - code coverage report
Current view: top level - bgp - community.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 162 187 86.6 %
Date: 2026-05-18 11:54:02 Functions: 56 61 91.8 %
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_COMMUNITY_H_
       6             : #define SRC_BGP_COMMUNITY_H_
       7             : 
       8             : #include <boost/array.hpp>
       9             : #include <boost/intrusive_ptr.hpp>
      10             : #include <boost/system/error_code.hpp>
      11             : 
      12             : #include <atomic>
      13             : #include <set>
      14             : #include <string>
      15             : #include <vector>
      16             : 
      17             : #include "base/parse_object.h"
      18             : #include "base/util.h"
      19             : #include "bgp/bgp_attr_base.h"
      20             : #include "bgp/bgp_common.h"
      21             : #include "bgp/extended-community/types.h"
      22             : #include "bgp/large-community/types.h"
      23             : 
      24             : class BgpAttr;
      25             : class CommunityDB;
      26             : class ExtCommunityDB;
      27             : class LargeCommunityDB;
      28             : class BgpServer;
      29             : 
      30             : struct CommunitySpec : public BgpAttribute {
      31             :     static const int kSize = -1;
      32             :     static const uint8_t kFlags = Optional | Transitive;
      33       62109 :     CommunitySpec() : BgpAttribute(Communities, kFlags) { }
      34        6664 :     explicit CommunitySpec(const BgpAttribute &rhs) : BgpAttribute(rhs) { }
      35             :     std::vector<uint32_t> communities;
      36        2009 :     virtual int CompareTo(const BgpAttribute &rhs_attr) const {
      37        2009 :         int ret = BgpAttribute::CompareTo(rhs_attr);
      38        2009 :         if (ret != 0) return ret;
      39        2009 :         KEY_COMPARE(communities,
      40             :                     static_cast<const CommunitySpec &>(rhs_attr).communities);
      41        2009 :         return 0;
      42             :     }
      43             :     virtual void ToCanonical(BgpAttr *attr);
      44             :     virtual std::string ToString() const;
      45             :     virtual size_t EncodeLength() const;
      46             : };
      47             : 
      48             : class Community {
      49             : public:
      50             :     typedef std::vector<uint32_t> CommunityList;
      51       22390 :     explicit Community(CommunityDB *comm_db)
      52       22390 :         : comm_db_(comm_db) {
      53       22390 :         refcount_ = 0;
      54       22390 :     }
      55         985 :     explicit Community(const Community &rhs)
      56         985 :         : comm_db_(rhs.comm_db_), communities_(rhs.communities_) {
      57         985 :         refcount_ = 0;
      58         985 :     }
      59             :     explicit Community(CommunityDB *comm_db, const CommunitySpec spec);
      60       56950 :     virtual ~Community() { }
      61             :     virtual void Remove();
      62             : 
      63             :     int CompareTo(const Community &rhs) const;
      64             :     bool ContainsValue(uint32_t value) const;
      65             :     void BuildStringList(std::vector<std::string> *list) const;
      66             : 
      67       39334 :     const std::vector<uint32_t> &communities() const { return communities_; }
      68             : 
      69           0 :     friend std::size_t hash_value(Community const &comm) {
      70           0 :         size_t hash = 0;
      71           0 :         boost::hash_range(hash, comm.communities_.begin(),
      72             :                           comm.communities_.end());
      73           0 :         return hash;
      74             :     }
      75             : 
      76             : private:
      77             :     friend int intrusive_ptr_add_ref(const Community *ccomm);
      78             :     friend int intrusive_ptr_del_ref(const Community *ccomm);
      79             :     friend void intrusive_ptr_release(const Community *ccomm);
      80             :     friend class CommunityDB;
      81             :     friend class BgpAttrTest;
      82             : 
      83             :     void Append(uint32_t value);
      84             :     void Append(const std::vector<uint32_t> &communities);
      85             :     void Set(const std::vector<uint32_t> &communities);
      86             :     void Remove(const std::vector<uint32_t> &communities);
      87             : 
      88             :     mutable std::atomic<int> refcount_;
      89             :     CommunityDB *comm_db_;
      90             :     std::vector<uint32_t> communities_;
      91             : };
      92             : 
      93      373098 : inline int intrusive_ptr_add_ref(const Community *ccomm) {
      94      746196 :     return ccomm->refcount_.fetch_add(1);
      95             : }
      96             : 
      97      107826 : inline int intrusive_ptr_del_ref(const Community *ccomm) {
      98      215652 :     return ccomm->refcount_.fetch_sub(1);
      99             : }
     100             : 
     101      265295 : inline void intrusive_ptr_release(const Community *ccomm) {
     102      265295 :     int prev = ccomm->refcount_.fetch_sub(1);
     103      265295 :     if (prev == 1) {
     104        2348 :         Community *comm = const_cast<Community *>(ccomm);
     105        2348 :         comm->Remove();
     106        2348 :         assert(comm->refcount_ == 0);
     107        2348 :         delete comm;
     108             :     }
     109      265295 : }
     110             : 
     111             : typedef boost::intrusive_ptr<const Community> CommunityPtr;
     112             : 
     113             : struct CommunityCompare {
     114      216856 :     bool operator()(const Community *lhs, const Community *rhs) const {
     115      216856 :         return lhs->CompareTo(*rhs) < 0;
     116             :     }
     117             : };
     118             : 
     119             : class CommunityDB : public BgpPathAttributeDB<Community, CommunityPtr,
     120             :                                               CommunitySpec, CommunityCompare,
     121             :                                               CommunityDB> {
     122             : public:
     123             :     explicit CommunityDB(BgpServer *server);
     124       19484 :     virtual ~CommunityDB() { }
     125             : 
     126             :     CommunityPtr AppendAndLocate(const Community *src, uint32_t value);
     127             :     CommunityPtr AppendAndLocate(const Community *src,
     128             :                                  const std::vector<uint32_t> &value);
     129             :     CommunityPtr SetAndLocate(const Community *src,
     130             :                               const std::vector<uint32_t> &value);
     131             :     CommunityPtr RemoveAndLocate(const Community *src,
     132             :                                  const std::vector<uint32_t> &value);
     133             :     CommunityPtr RemoveAndLocate(const Community *src, uint32_t value);
     134             : 
     135             : private:
     136             : };
     137             : 
     138             : class ExtCommunitySpec : public BgpAttribute {
     139             : public:
     140             :     static const int kSize = -1;
     141             :     static const uint8_t kFlags = Optional | Transitive;
     142      235438 :     ExtCommunitySpec() : BgpAttribute(ExtendedCommunities, kFlags) { }
     143       92280 :     explicit ExtCommunitySpec(const BgpAttribute &rhs) : BgpAttribute(rhs) { }
     144             :     virtual size_t EncodeLength() const;
     145             :     std::vector<uint64_t> communities;
     146             :     void AddTunnelEncaps(std::vector<std::string> encaps);
     147             :     virtual int CompareTo(const BgpAttribute &rhs_attr) const;
     148             :     virtual void ToCanonical(BgpAttr *attr);
     149             :     virtual std::string ToString() const;
     150             : };
     151             : 
     152             : class ExtCommunity {
     153             : public:
     154             :     typedef boost::array<uint8_t, 8> ExtCommunityValue;
     155             :     typedef std::vector<ExtCommunityValue> ExtCommunityList;
     156             : 
     157      147034 :     explicit ExtCommunity(ExtCommunityDB *extcomm_db)
     158      147034 :         : extcomm_db_(extcomm_db) {
     159      147034 :         refcount_ = 0;
     160      147036 :     }
     161      541185 :     explicit ExtCommunity(const ExtCommunity &rhs)
     162      541185 :         : extcomm_db_(rhs.extcomm_db_),
     163      541185 :           communities_(rhs.communities_) {
     164      541109 :         refcount_ = 0;
     165      541259 :     }
     166             : 
     167             :     explicit ExtCommunity(ExtCommunityDB *extcomm_db,
     168             :                           const ExtCommunitySpec spec);
     169     1749870 :     virtual ~ExtCommunity() { }
     170             :     virtual void Remove();
     171             :     int CompareTo(const ExtCommunity &rhs) const;
     172             : 
     173             :     bool ContainsRTarget(const ExtCommunityValue &val) const;
     174             :     bool ContainsOriginVn(as_t asn, uint32_t vn_index) const;
     175             :     bool ContainsOriginVn(const ExtCommunityValue &val) const;
     176             :     bool ContainsOriginVn4(const ExtCommunityValue &val) const;
     177             :     bool ContainsVrfRouteImport(const ExtCommunityValue &val) const;
     178             :     bool ContainsSourceAs(const ExtCommunityValue &val) const;
     179             :     uint32_t GetSubClusterId() const;
     180             : 
     181             :     // Return vector of communities
     182    84375412 :     const ExtCommunityList &communities() const {
     183    84375412 :         return communities_;
     184             :     }
     185             : 
     186             :     std::vector<std::string> GetTunnelEncap() const;
     187             :     std::vector<int> GetTagList(as2_t asn = 0) const;
     188             :     std::vector<int> GetTag4List(as_t asn = 0) const;
     189             :     bool ContainsTunnelEncapVxlan() const;
     190             :     int GetOriginVnIndex() const;
     191             :     static ExtCommunityList ExtCommunityFromString(const std::string &comm);
     192             :     static ExtCommunityValue FromHexString(const std::string &comm,
     193             :             boost::system::error_code *errorp);
     194             : 
     195     9330880 :     static bool is_origin_vn(const ExtCommunityValue &val) {
     196             :         //
     197             :         // Origin VN extended community
     198             :         // 2 Octet AS specific extended community
     199             :         //
     200     9330880 :         return ((val[0] == BgpExtendedCommunityType::Experimental ||
     201    10145923 :                     val[0] == BgpExtendedCommunityType::Experimental4ByteAs) &&
     202    10145689 :                (val[1] == BgpExtendedCommunityExperimentalSubType::OriginVn));
     203             :     }
     204             : 
     205         432 :     static bool is_default_gateway(const ExtCommunityValue &val) {
     206             :         //
     207             :         // Default Gateway extended community
     208             :         //
     209         552 :         return (val[0] == BgpExtendedCommunityType::Opaque) &&
     210         552 :                (val[1] == BgpExtendedCommunityOpaqueSubType::DefaultGateway);
     211             :     }
     212             : 
     213         432 :     static bool is_es_import(const ExtCommunityValue &val) {
     214             :         //
     215             :         // ES Import extended community
     216             :         //
     217         434 :         return (val[0] == BgpExtendedCommunityType::Evpn) &&
     218         434 :                (val[1] == BgpExtendedCommunityEvpnSubType::EsImport);
     219             :     }
     220             : 
     221         542 :     static bool is_esi_label(const ExtCommunityValue &val) {
     222             :         //
     223             :         // ESI Label extended community
     224             :         //
     225         599 :         return (val[0] == BgpExtendedCommunityType::Evpn) &&
     226         599 :                (val[1] == BgpExtendedCommunityEvpnSubType::EsiMplsLabel);
     227             :     }
     228             : 
     229    33598500 :     static bool is_mac_mobility(const ExtCommunityValue &val) {
     230             :         //
     231             :         // MAC Mobility extended community
     232             :         //
     233    33962586 :         return (val[0] == BgpExtendedCommunityType::Evpn) &&
     234    33962553 :                (val[1] == BgpExtendedCommunityEvpnSubType::MacMobility);
     235             :     }
     236             : 
     237         432 :     static bool is_local_sequence_number(const ExtCommunityValue &val) {
     238         432 :         return (val[0] == BgpExtendedCommunityType::ExperimentalNonTransitive &&
     239         432 :                 val[1] == BgpExtendedCommunityExperimentalNonTransitiveSubType::LocalSequenceNumber);
     240             :     }
     241             : 
     242    12745738 :     static bool is_etree(const ExtCommunityValue &val) {
     243             :         //
     244             :         // ETree extended community
     245             :         //
     246    12869540 :         return (val[0] == BgpExtendedCommunityType::Evpn) &&
     247    12869570 :                (val[1] == BgpExtendedCommunityEvpnSubType::ETree);
     248             :     }
     249             : 
     250       26684 :     static bool is_multicast_flags(const ExtCommunityValue &val) {
     251             :         //
     252             :         // Multicast Flags extended community
     253             :         //
     254       28625 :         return (val[0] == BgpExtendedCommunityType::Evpn) &&
     255       28625 :                (val[1] == BgpExtendedCommunityEvpnSubType::MulticastFlags);
     256             :     }
     257             : 
     258             : 
     259     2736397 :     static bool is_router_mac(const ExtCommunityValue &val) {
     260             :         //
     261             :         // Router MAC extended community
     262             :         //
     263     2747257 :         return (val[0] == BgpExtendedCommunityType::Evpn) &&
     264     2747248 :                (val[1] == BgpExtendedCommunityEvpnSubType::RouterMac);
     265             :     }
     266             : 
     267    10085770 :     static bool is_route_target(const ExtCommunityValue &val) {
     268             :         //
     269             :         // Route target extended community
     270             :         // 1. 2 Octet AS specific extended community Route Target
     271             :         // 2. IPv4 Address specific extended community Route Target
     272             :         // 3. 4 Octet AS specific extended community Route Target
     273             :         //
     274    10085770 :         return ((val[0] == BgpExtendedCommunityType::TwoOctetAS ||
     275     2411905 :                 (val[0] == BgpExtendedCommunityType::FourOctetAS) ||
     276    20494287 :                 (val[0] == BgpExtendedCommunityType::IPv4Address)) &&
     277    18082392 :                 (val[1] == BgpExtendedCommunitySubType::RouteTarget));
     278             :     }
     279             : 
     280        8252 :     static uint32_t get_rtarget_val(const ExtCommunityValue &val) {
     281             :         //
     282             :         // Get non user-configured RT value from Route Target extended
     283             :         // community for
     284             :         // 1. 2 Octet AS specific extended community Route Target
     285             :         // 2. 4 Octet AS specific extended community Route Target
     286             :         //
     287        8252 :         if (is_route_target(val)) {
     288             :             uint8_t data[8];
     289             :             uint32_t rt;
     290        8252 :             std::copy(val.begin(), val.end(), &data[0]);
     291        8252 :             if (data[0] == BgpExtendedCommunityType::TwoOctetAS) {
     292        8249 :                 rt = get_value(data + 4, 4);
     293        8249 :                 if (rt >= BGP_RTGT_MIN_ID_AS2 && rt <= BGP_RTGT_MAX_ID_AS2) {
     294           4 :                     return (rt);
     295             :                 }
     296           3 :             } else if (data[0] == BgpExtendedCommunityType::FourOctetAS) {
     297           3 :                 rt = get_value(data + 6, 2);
     298           3 :                 if (rt >= BGP_RTGT_MIN_ID_AS4 && rt <= BGP_RTGT_MAX_ID_AS4) {
     299           2 :                     return (rt);
     300             :                 }
     301             :             }
     302             :         }
     303        8248 :         return (0);
     304             :     }
     305             : 
     306     3101892 :     static bool is_security_group(const ExtCommunityValue &val) {
     307             :         //
     308             :         // SG ID extended community
     309             :         // 2 Octet AS specific extended community
     310             :         //
     311     3586147 :         return (val[0] == BgpExtendedCommunityType::Experimental) &&
     312     3586097 :                (val[1] == BgpExtendedCommunityExperimentalSubType::SgId);
     313             :     }
     314             : 
     315     2651307 :     static bool is_security_group4(const ExtCommunityValue &val) {
     316             :         //
     317             :         // SG ID extended community
     318             :         // 2 Octet AS specific extended community
     319             :         //
     320     2847915 :         return (val[0] == BgpExtendedCommunityType::Experimental4ByteAs) &&
     321     2847914 :                (val[1] == BgpExtendedCommunityExperimentalSubType::SgId);
     322             :     }
     323             : 
     324       27199 :     static bool is_site_of_origin(const ExtCommunityValue &val) {
     325             :         //
     326             :         // Site of Origin / Route Origin extended community
     327             :         // 1. 2 Octet AS specific extended community
     328             :         // 2. IPv4 Address specific extended community
     329             :         // 3. 4 Octet AS specific extended community Route Target
     330             :         //
     331       27199 :         return ((val[0] == BgpExtendedCommunityType::TwoOctetAS ||
     332       24845 :                 (val[0] == BgpExtendedCommunityType::FourOctetAS) ||
     333       54398 :                 (val[0] == BgpExtendedCommunityType::IPv4Address)) &&
     334       29553 :                 (val[1] == BgpExtendedCommunitySubType::RouteOrigin));
     335             :     }
     336             : 
     337        3500 :     static bool is_source_as(const ExtCommunityValue &val) {
     338             :         //
     339             :         // Source AS extended community
     340             :         // 1. 2 Octet AS specific extended community
     341             :         // 2. 4 Octet AS specific extended community
     342             :         //
     343        3500 :         return ((val[0] == BgpExtendedCommunityType::TwoOctetAS ||
     344        4102 :                 (val[0] == BgpExtendedCommunityType::FourOctetAS)) &&
     345        4102 :                 (val[1] == BgpExtendedCommunitySubType::SourceAS));
     346             :     }
     347             : 
     348     2479255 :     static bool is_sub_cluster(const ExtCommunityValue &val) {
     349             :         //
     350             :         // Sub Cluster extended community
     351             :         // 1. Experimental AS specific extended community
     352             :         // 2. Experimental4Byte  AS specific extended community
     353             :         //
     354     2479255 :         return (((val[0] == BgpExtendedCommunityType::Experimental) ||
     355     2695515 :                 (val[0] == BgpExtendedCommunityType::Experimental4ByteAs)) &&
     356     2695522 :                 (val[1] == BgpExtendedCommunitySubType::SubCluster));
     357             :     }
     358             : 
     359        2126 :     static bool is_vrf_route_import(const ExtCommunityValue &val) {
     360             :         //
     361             :         // VRF Route Import extended community
     362             :         // IPv4 Address specific extended community
     363             :         //
     364        2426 :         return ((val[0] == BgpExtendedCommunityType::IPv4Address) &&
     365        2426 :                 (val[1] == BgpExtendedCommunitySubType::VrfRouteImport));
     366             :     }
     367             : 
     368     4684416 :     static bool is_tunnel_encap(const ExtCommunityValue &val) {
     369             :         // Tunnel encap extended community
     370     5344095 :         return (val[0] == BgpExtendedCommunityType::Opaque) &&
     371     5344028 :                (val[1] == BgpExtendedCommunityOpaqueSubType::TunnelEncap);
     372             :     }
     373             : 
     374     2484360 :     static bool is_load_balance(const ExtCommunityValue &val) {
     375             :         // Load Balance extended community
     376     2932798 :         return (val[0] == BgpExtendedCommunityType::Opaque) &&
     377     2932789 :                (val[1] == BgpExtendedCommunityOpaqueSubType::LoadBalance);
     378             :     }
     379             : 
     380           6 :     static bool is_tag(const ExtCommunityValue &val) {
     381             :         // Tag extended community
     382           9 :         return (val[0] == BgpExtendedCommunityType::Experimental) &&
     383           9 :                (val[1] == BgpExtendedCommunityExperimentalSubType::Tag);
     384             :     }
     385             : 
     386           0 :     static bool is_tag4(const ExtCommunityValue &val) {
     387             :         // Tag extended community
     388           0 :         return (val[0] == BgpExtendedCommunityType::Experimental4ByteAs) &&
     389           0 :                (val[1] == BgpExtendedCommunityExperimentalSubType::Tag);
     390             :     }
     391             : 
     392           0 :     friend std::size_t hash_value(ExtCommunity const &comm) {
     393           0 :         size_t hash = 0;
     394           0 :         for (ExtCommunityList::const_iterator iter = comm.communities_.begin();
     395           0 :                 iter != comm.communities_.end(); iter++) {
     396           0 :             boost::hash_range(hash, iter->begin(), iter->end());
     397             :         }
     398           0 :         return hash;
     399             :     }
     400             : 
     401             :     static std::string ToString(const ExtCommunityValue &val);
     402             :     static std::string ToHexString(const ExtCommunityValue &val);
     403             : 
     404             : private:
     405             :     friend int intrusive_ptr_add_ref(const ExtCommunity *cextcomm);
     406             :     friend int intrusive_ptr_del_ref(const ExtCommunity *cextcomm);
     407             :     friend void intrusive_ptr_release(const ExtCommunity *cextcomm);
     408             :     friend class ExtCommunityDB;
     409             :     friend class BgpAttrTest;
     410             : 
     411             :     void Append(const ExtCommunityValue &value);
     412             :     void Append(const ExtCommunityList &list);
     413             :     void Remove(const ExtCommunityList &list);
     414             :     void RemoveMFlags();
     415             :     void RemoveRTarget();
     416             :     void RemoveSGID();
     417             :     void RemoveTag();
     418             :     void RemoveSiteOfOrigin();
     419             :     void RemoveSourceAS();
     420             :     void RemoveVrfRouteImport();
     421             :     void RemoveOriginVn();
     422             :     void RemoveTunnelEncapsulation();
     423             :     void RemoveLoadBalance();
     424             :     void RemoveSubCluster();
     425             :     void Set(const ExtCommunityList &list);
     426             : 
     427             :     mutable std::atomic<int> refcount_;
     428             :     ExtCommunityDB *extcomm_db_;
     429             :     ExtCommunityList communities_;
     430             : };
     431             : 
     432    10866111 : inline int intrusive_ptr_add_ref(const ExtCommunity *cextcomm) {
     433    21732222 :     return cextcomm->refcount_.fetch_add(1);
     434             : }
     435             : 
     436     1154427 : inline int intrusive_ptr_del_ref(const ExtCommunity *cextcomm) {
     437     2308854 :     return cextcomm->refcount_.fetch_sub(1);
     438             : }
     439             : 
     440     9713333 : inline void intrusive_ptr_release(const ExtCommunity *cextcomm) {
     441     9713333 :     int prev = cextcomm->refcount_.fetch_sub(1);
     442     9713333 :     if (prev == 1) {
     443      185254 :         ExtCommunity *extcomm = const_cast<ExtCommunity *>(cextcomm);
     444      185254 :         extcomm->Remove();
     445      185254 :         assert(extcomm->refcount_ == 0);
     446      185254 :         delete extcomm;
     447             :     }
     448     9713333 : }
     449             : 
     450             : typedef boost::intrusive_ptr<const ExtCommunity> ExtCommunityPtr;
     451             : 
     452             : struct ExtCommunityCompare {
     453     4878746 :     bool operator()(const ExtCommunity *lhs, const ExtCommunity *rhs) const {
     454     4878746 :         return lhs->CompareTo(*rhs) < 0;
     455             :     }
     456             : };
     457             : 
     458             : class ExtCommunityDB : public BgpPathAttributeDB<ExtCommunity, ExtCommunityPtr,
     459             :                                                  ExtCommunitySpec,
     460             :                                                  ExtCommunityCompare,
     461             :                                                  ExtCommunityDB> {
     462             : public:
     463             :     explicit ExtCommunityDB(BgpServer *server);
     464             : 
     465             :     ExtCommunityPtr AppendAndLocate(const ExtCommunity *src,
     466             :             const ExtCommunity::ExtCommunityList &list);
     467             :     ExtCommunityPtr AppendAndLocate(const ExtCommunity *src,
     468             :             const ExtCommunity::ExtCommunityValue &value);
     469             :     ExtCommunityPtr RemoveAndLocate(const ExtCommunity *src,
     470             :         const ExtCommunity::ExtCommunityList &list);
     471             : 
     472             :     ExtCommunityPtr ReplaceMFlagsAndLocate(const ExtCommunity *src,
     473             :             const ExtCommunity::ExtCommunityList &export_list);
     474             :     ExtCommunityPtr ReplaceRTargetAndLocate(const ExtCommunity *src,
     475             :             const ExtCommunity::ExtCommunityList &export_list);
     476             :     ExtCommunityPtr ReplaceSGIDListAndLocate(const ExtCommunity *src,
     477             :             const ExtCommunity::ExtCommunityList &sgid_list);
     478             :     ExtCommunityPtr ReplaceTagListAndLocate(const ExtCommunity *src,
     479             :             const ExtCommunity::ExtCommunityList &tag_list);
     480             :     ExtCommunityPtr RemoveSiteOfOriginAndLocate(const ExtCommunity *src);
     481             :     ExtCommunityPtr ReplaceSiteOfOriginAndLocate(const ExtCommunity *src,
     482             :             const ExtCommunity::ExtCommunityValue &soo);
     483             :     ExtCommunityPtr RemoveVrfRouteImportAndLocate(const ExtCommunity *src);
     484             :     ExtCommunityPtr ReplaceVrfRouteImportAndLocate(const ExtCommunity *src,
     485             :             const ExtCommunity::ExtCommunityValue &vit);
     486             :     ExtCommunityPtr RemoveSourceASAndLocate(const ExtCommunity *src);
     487             :     ExtCommunityPtr ReplaceSourceASAndLocate(const ExtCommunity *src,
     488             :             const ExtCommunity::ExtCommunityValue &sas);
     489             :     ExtCommunityPtr RemoveOriginVnAndLocate(const ExtCommunity *src);
     490             :     ExtCommunityPtr ReplaceOriginVnAndLocate(const ExtCommunity *src,
     491             :             const ExtCommunity::ExtCommunityValue &origin_vn);
     492             :     ExtCommunityPtr ReplaceTunnelEncapsulationAndLocate(
     493             :             const ExtCommunity *src,
     494             :             const ExtCommunity::ExtCommunityList &tunnel_encaps);
     495             :     ExtCommunityPtr ReplaceLoadBalanceAndLocate(const ExtCommunity *src,
     496             :             const ExtCommunity::ExtCommunityValue &lb);
     497             :     ExtCommunityPtr ReplaceSubClusterAndLocate(const ExtCommunity *src,
     498             :             const ExtCommunity::ExtCommunityValue &sc);
     499             :     ExtCommunityPtr SetAndLocate(const ExtCommunity *src,
     500             :             const ExtCommunity::ExtCommunityList &list);
     501             : 
     502             : private:
     503             : };
     504             : 
     505             : /// @brief This class encapsulates the wire-format representation of a BGP
     506             : /// Large Community attribute and provides encoding, comparison, and
     507             : /// canonicalization functions for Large Community attributes.
     508             : class LargeCommunitySpec : public BgpAttribute {
     509             : public:
     510             :     /// Indicates variable size of BGP attribute in encoded form (used
     511             :     /// internally by encoding functions). -1 means the total size depends on
     512             :     /// how many communities are present.
     513             :     static const int kSize = -1;
     514             : 
     515             :     /// Flags indicating whether the attribute is Optional and Transitive per BGP
     516             :     /// standards.
     517             :     static const uint8_t kFlags = Optional | Transitive;
     518             : 
     519             :     /// @brief Constructs a new instance using the attribute type and
     520             :     /// flags.
     521      534435 :     LargeCommunitySpec() : BgpAttribute(LargeCommunities, kFlags) { }
     522             : 
     523             :     /// @brief Constructs from an existing BgpAttribute.
     524           6 :     explicit LargeCommunitySpec(const BgpAttribute &rhs) :
     525           6 :         BgpAttribute(rhs) { }
     526             : 
     527             :     /// @brief Constructs an instance from an Extened Community specification
     528             :     /// by distributing its bits inside a new Large Community spec.
     529             :     static LargeCommunitySpec FromTag(const ExtCommunitySpec &ex_spec);
     530             : 
     531             :     /// @brief Removes extended communities corresponding to tags
     532             :     /// from the given ExtCommunitySpec.
     533             :     static ExtCommunitySpec RemoveTags(const ExtCommunitySpec& ex_spec);
     534             : 
     535             :     /// @brief Compute the encoded length of the attribute.
     536             :     virtual size_t EncodeLength() const;
     537             : 
     538             :     /// @brief Vector of community values. Each Large Community value consists
     539             :     /// of three 4-byte fields (12 bytes total).
     540             :     std::vector<uint32_t> communities;
     541             : 
     542             :     /// @brief Compare the attribute with another BgpAttribute.
     543             :     virtual int CompareTo(const BgpAttribute &rhs_attr) const;
     544             : 
     545             :     /// @brief Convert the attribute to its canonical form.
     546             :     virtual void ToCanonical(BgpAttr *attr);
     547             : 
     548             :     /// @brief Generate a human-readable string representation.
     549             :     virtual std::string ToString() const;
     550             : };
     551             : 
     552             : /// @brief This class represents an array of BGP Large Community values.
     553             : /// A LargeCommunity consists of one or more 12-byte tuples. This class
     554             : /// provides manipulation (append, remove, set), comparison, hashing, and
     555             : /// conversion to/from human-readable formats.
     556             : class LargeCommunity {
     557             : public:
     558             :     /// A single Large Community value.
     559             :     typedef boost::array<uint8_t, 12> LargeCommunityValue;
     560             : 
     561             :     /// A list (vector) of LargeCommunityValue items.
     562             :     typedef std::vector<LargeCommunityValue> LargeCommunityList;
     563             : 
     564             :     /// @brief Constructs an instance of the class and links to the
     565             :     /// given LargeCommunityDB instance.
     566       18862 :     explicit LargeCommunity(LargeCommunityDB *largecomm_db)
     567       18862 :         : largecomm_db_(largecomm_db) {
     568       18862 :         refcount_ = 0;
     569       18862 :     }
     570             : 
     571             :     /// @brief Copy constructor.
     572           0 :     explicit LargeCommunity(const LargeCommunity &rhs)
     573           0 :         : largecomm_db_(rhs.largecomm_db_),
     574           0 :           communities_(rhs.communities_) {
     575           0 :         refcount_ = 0;
     576           0 :     }
     577             : 
     578             :     /// @brief Constructs an instance of the class using the given
     579             :     /// LargeCommunitySpec and links to the given LargeCommunityDB
     580             :     /// instance.
     581             :     explicit LargeCommunity(LargeCommunityDB *largecomm_db,
     582             :                           const LargeCommunitySpec spec);
     583             : 
     584             :     /// @brief Destroys an instance.
     585      404373 :     virtual ~LargeCommunity() { }
     586             : 
     587             :     /// @brief Remove this community.
     588             :     virtual void Remove();
     589             : 
     590             :     /// @brief Compare this LargeCommunity to another.
     591             :     int CompareTo(const LargeCommunity &rhs) const;
     592             : 
     593             :     /// @brief Get the list of Large Community values.
     594      100439 :     const LargeCommunityList &communities() const {
     595      100439 :         return communities_;
     596             :     }
     597             : 
     598             :     /// @brief Get the list of tags with the specified ASN.
     599             :     std::vector<uint64_t> GetTagList(as_t asn = 0) const;
     600             : 
     601             :     /// @brief Parse a string into a list of LargeCommunity values.
     602             :     static LargeCommunityList LargeCommunityFromString(
     603             :         const std::string &comm);
     604             : 
     605             :     /// @brief Convert a hexadecimal string to a LargeCommunityValue.
     606             :     static LargeCommunityValue FromHexString(const std::string &comm,
     607             :             boost::system::error_code *errorp);
     608             : 
     609             :     /// @brief Compute the hash value for a LargeCommunity object.
     610           0 :     friend std::size_t hash_value(LargeCommunity const &comm) {
     611           0 :         size_t hash = 0;
     612           0 :         for (LargeCommunityList::const_iterator iter =
     613           0 :                 comm.communities_.begin();
     614           0 :                 iter != comm.communities_.end(); iter++) {
     615           0 :             boost::hash_range(hash, iter->begin(), iter->end());
     616             :         }
     617           0 :         return hash;
     618             :     }
     619             : 
     620             :     /// @brief Check if the LargeCommunity value is tag.
     621         160 :     static bool is_tag(const LargeCommunityValue &val) {
     622         160 :         return (val[4] == BgpLargeCommunityType::TagLC);
     623             :     }
     624             : 
     625             :     /// @brief Convert a LargeCommunityValue to a human-readable string.
     626             :     static std::string ToString(const LargeCommunityValue &val);
     627             : 
     628             :     /// @brief Convert a LargeCommunityValue to a hexadecimal string.
     629             :     static std::string ToHexString(const LargeCommunityValue &val);
     630             : 
     631             : private:
     632             :     /// @brief Increment reference count atomically.
     633             :     friend int intrusive_ptr_add_ref(const LargeCommunity *clargecomm);
     634             :     /// @brief Decrement reference count of an clargecomm.
     635             :     friend int intrusive_ptr_del_ref(const LargeCommunity *clargecomm);
     636             :     /// @brief Release a LargeCommunity instance when the reference count
     637             :     /// reaches zero.
     638             :     friend void intrusive_ptr_release(const LargeCommunity *clargecomm);
     639             :     /// @brief Enables the access to private members for LargeCommunityDB.
     640             :     friend class LargeCommunityDB;
     641             :     /// @brief Enables the access to private members for BgpAttrTest.
     642             :     friend class BgpAttrTest;
     643             : 
     644             :     /// Append a single LargeCommunity value.
     645             :     void Append(const LargeCommunityValue &value);
     646             :     /// Append a list of LargeCommunity values.
     647             :     void Append(const LargeCommunityList &list);
     648             :     /// Remove specific LargeCommunity values.
     649             :     void Remove(const LargeCommunityList &list);
     650             :     /// Remove all the tags.
     651             :     void RemoveTag();
     652             :     /// Replace all existing values with the provided list.
     653             :     void Set(const LargeCommunityList &list);
     654             : 
     655             :     /// @brief A reference counter, needed for memory management.
     656             :     mutable std::atomic<int> refcount_;
     657             :     /// @brief A pointer to the managing LargeCommunityDB.
     658             :     LargeCommunityDB *largecomm_db_;
     659             :     /// @brief A list of LargeCommunity storing BGP Large Community values.
     660             :     LargeCommunityList communities_;
     661             : };
     662             : 
     663             : /// @brief Increment reference count atomically.
     664     2940843 : inline int intrusive_ptr_add_ref(const LargeCommunity *clargecomm) {
     665     5881686 :     return clargecomm->refcount_.fetch_add(1);
     666             : }
     667             : 
     668             : /// @brief Decrement reference count of given large community.
     669      205222 : inline int intrusive_ptr_del_ref(const LargeCommunity *clargecomm) {
     670      410444 :     return clargecomm->refcount_.fetch_sub(1);
     671             : }
     672             : 
     673             : /// @brief Release a LargeCommunity instance when the reference count reaches
     674             : /// zero.
     675     2735168 : inline void intrusive_ptr_release(const LargeCommunity *clargecomm) {
     676     2735168 :     int prev = clargecomm->refcount_.fetch_sub(1);
     677     2735168 :     if (prev == 1) {
     678        6124 :         LargeCommunity *largecomm = const_cast<LargeCommunity *>(clargecomm);
     679        6124 :         largecomm->Remove();
     680        6124 :         assert(largecomm->refcount_ == 0);
     681        6124 :         delete largecomm;
     682             :     }
     683     2735168 : }
     684             : 
     685             : /// @brief Defines a type for automatic storage of a LargeCommunity instance.
     686             : typedef boost::intrusive_ptr<const LargeCommunity> LargeCommunityPtr;
     687             : 
     688             : /// @brief A structure to compare order LargeCommunity objects.
     689             : struct LargeCommunityCompare {
     690      410721 :     bool operator()(const LargeCommunity *lhs, const LargeCommunity *rhs) const {
     691      410721 :         return lhs->CompareTo(*rhs) < 0;
     692             :     }
     693             : };
     694             : 
     695             : /// @brief This class represents a database for managing LargeCommunity
     696             : /// objects. It is used to store, deduplicate, and retrieve canonical
     697             : /// instances of LargeCommunity.
     698             : class LargeCommunityDB : public BgpPathAttributeDB<LargeCommunity,
     699             :                                                    LargeCommunityPtr,
     700             :                                                    LargeCommunitySpec,
     701             :                                                    LargeCommunityCompare,
     702             :                                                    LargeCommunityDB> {
     703             : public:
     704             :     /// @brief Constructs an instance of the class and links to the
     705             :     /// given BgpServer instance.
     706             :     explicit LargeCommunityDB(BgpServer *server);
     707             : 
     708             :     /// @brief Append a list of LargeCommunity values to an existing attribute.
     709             :     LargeCommunityPtr AppendAndLocate(
     710             :         const LargeCommunity *src,
     711             :         const LargeCommunity::LargeCommunityList &list);
     712             : 
     713             :     /// @brief Append a single LargeCommunity value to an existing attribute.
     714             :     LargeCommunityPtr AppendAndLocate(
     715             :         const LargeCommunity *src,
     716             :         const LargeCommunity::LargeCommunityValue &value);
     717             : 
     718             :     /// @brief Remove a list of LargeCommunity values from an existing
     719             :     /// attribute.
     720             :     LargeCommunityPtr RemoveAndLocate(
     721             :         const LargeCommunity *src,
     722             :         const LargeCommunity::LargeCommunityList &list);
     723             : 
     724             :     /// @brief Replace all tags in a LargeCommunity with a new tag list.
     725             :     LargeCommunityPtr ReplaceTagListAndLocate(
     726             :         const LargeCommunity *src,
     727             :         const LargeCommunity::LargeCommunityList &tag_list);
     728             : 
     729             :     /// @brief Replace all values in a LargeCommunity with a new list.
     730             :     LargeCommunityPtr SetAndLocate(
     731             :         const LargeCommunity *src,
     732             :         const LargeCommunity::LargeCommunityList &list);
     733             : 
     734             : private:
     735             : };
     736             : 
     737             : #endif  // SRC_BGP_COMMUNITY_H_

Generated by: LCOV version 1.14