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

Generated by: LCOV version 1.14