LCOV - code coverage report
Current view: top level - bgp - community.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 554 772 71.8 %
Date: 2026-11-09 02:10:49 Functions: 84 101 83.2 %
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             : #include "bgp/community.h"
       7             : 
       8             : #include <boost/foreach.hpp>
       9             : 
      10             : #include <algorithm>
      11             : #include <string>
      12             : #include <map>
      13             : 
      14             : #include "base/string_util.h"
      15             : #include "bgp/bgp_proto.h"
      16             : #include "bgp/extended-community/tag.h"
      17             : #include "bgp/extended-community/default_gateway.h"
      18             : #include "bgp/extended-community/es_import.h"
      19             : #include "bgp/extended-community/esi_label.h"
      20             : #include "bgp/extended-community/etree.h"
      21             : #include "bgp/extended-community/load_balance.h"
      22             : #include "bgp/extended-community/mac_mobility.h"
      23             : #include "bgp/extended-community/local_sequence_number.h"
      24             : #include "bgp/extended-community/router_mac.h"
      25             : #include "bgp/extended-community/site_of_origin.h"
      26             : #include "bgp/extended-community/source_as.h"
      27             : #include "bgp/extended-community/sub_cluster.h"
      28             : #include "bgp/extended-community/tag.h"
      29             : #include "bgp/extended-community/vrf_route_import.h"
      30             : #include "bgp/large-community/tag.h"
      31             : #include "bgp/tunnel_encap/tunnel_encap.h"
      32             : #include "bgp/origin-vn/origin_vn.h"
      33             : #include "bgp/rtarget/rtarget_address.h"
      34             : #include "bgp/security_group/security_group.h"
      35             : #include "bgp/tunnel_encap/tunnel_encap.h"
      36             : #include "net/community_type.h"
      37             : 
      38             : using std::sort;
      39             : using std::string;
      40             : using std::unique;
      41             : using std::vector;
      42             : 
      43        4285 : void CommunitySpec::ToCanonical(BgpAttr *attr) {
      44        4285 :     attr->set_community(this);
      45        4285 : }
      46             : 
      47        4011 : string CommunitySpec::ToString() const {
      48        4011 :     string repr;
      49             :     char start[32];
      50        4011 :     snprintf(start, sizeof(start), "Communities: %zu [", communities.size());
      51        4011 :     repr += start;
      52             : 
      53        8032 :     for (size_t i = 0; i < communities.size(); ++i) {
      54             :         char community[12];
      55        4021 :         snprintf(community, sizeof(community), " %X", communities[i]);
      56        4021 :         repr += community;
      57             :     }
      58        4011 :     repr += " ]";
      59             : 
      60        8022 :     return repr;
      61           0 : }
      62             : 
      63        5645 : Community::Community(CommunityDB *comm_db, const CommunitySpec spec)
      64        5645 :     : comm_db_(comm_db), communities_(spec.communities) {
      65        5644 :     refcount_ = 0;
      66        5659 :     sort(communities_.begin(), communities_.end());
      67             :     vector<uint32_t>::iterator it =
      68        5650 :         unique(communities_.begin(), communities_.end());
      69        5643 :     communities_.erase(it, communities_.end());
      70        5634 : }
      71             : 
      72      338506 : int Community::CompareTo(const Community &rhs) const {
      73      338506 :     KEY_COMPARE(communities_, rhs.communities_);
      74      337295 :     return 0;
      75             : }
      76             : 
      77       22926 : size_t CommunitySpec::EncodeLength() const {
      78       22926 :     return communities.size() * sizeof(uint32_t);
      79             : }
      80             : 
      81       23292 : void Community::Append(uint32_t value) {
      82       23292 :     if (ContainsValue(value))
      83         897 :         return;
      84       22395 :     communities_.push_back(value);
      85       22395 :     sort(communities_.begin(), communities_.end());
      86             : }
      87             : 
      88          31 : void Community::Append(const std::vector<uint32_t> &communities) {
      89          66 :     for (auto community : communities) {
      90          35 :         communities_.push_back(community);
      91             :     }
      92          31 :     sort(communities_.begin(), communities_.end());
      93             :     vector<uint32_t>::iterator it =
      94          31 :         unique(communities_.begin(), communities_.end());
      95          31 :     communities_.erase(it, communities_.end());
      96          31 : }
      97             : 
      98           7 : void Community::Set(const std::vector<uint32_t> &communities) {
      99           7 :     communities_.clear();
     100          26 :     for (auto community : communities) {
     101          19 :         communities_.push_back(community);
     102             :     }
     103           7 : }
     104             : 
     105          13 : void Community::Remove(const std::vector<uint32_t> &communities) {
     106          30 :     for (auto community : communities) {
     107          34 :         communities_.erase(
     108          17 :                std::remove(communities_.begin(), communities_.end(), community),
     109          34 :                communities_.end());
     110             :     }
     111          13 : }
     112        2352 : void Community::Remove() {
     113        2352 :     comm_db_->Delete(this);
     114        2352 : }
     115             : 
     116      115377 : bool Community::ContainsValue(uint32_t value) const {
     117      194552 :     for (auto community : communities_) {
     118       93837 :         if (community == value)
     119       14662 :             return true;
     120             :     }
     121      100719 :     return false;
     122             : }
     123             : 
     124         194 : void Community::BuildStringList(vector<string> *list) const {
     125         402 :     for (auto community : communities_) {
     126         208 :         string name = CommunityType::CommunityToString(community);
     127         208 :         list->push_back(name);
     128         208 :     }
     129         194 : }
     130             : 
     131        9743 : CommunityDB::CommunityDB(BgpServer *server) {
     132        9743 : }
     133             : 
     134       23292 : CommunityPtr CommunityDB::AppendAndLocate(const Community *src,
     135             :     uint32_t value) {
     136             :     Community *clone;
     137       23292 :     if (src) {
     138         937 :         clone = new Community(*src);
     139             :     } else {
     140       22355 :         clone = new Community(this);
     141             :     }
     142             : 
     143       23292 :     clone->Append(value);
     144       23291 :     return Locate(clone);
     145             : }
     146             : 
     147          31 : CommunityPtr CommunityDB::AppendAndLocate(const Community *src,
     148             :     const std::vector<uint32_t> &value) {
     149             :     Community *clone;
     150          31 :     if (src) {
     151          30 :         clone = new Community(*src);
     152             :     } else {
     153           1 :         clone = new Community(this);
     154             :     }
     155             : 
     156          31 :     clone->Append(value);
     157          31 :     return Locate(clone);
     158             : }
     159             : 
     160           7 : CommunityPtr CommunityDB::SetAndLocate(const Community *src,
     161             :     const std::vector<uint32_t> &value) {
     162             :     Community *clone;
     163           7 :     if (src) {
     164           6 :         clone = new Community(*src);
     165             :     } else {
     166           1 :         clone = new Community(this);
     167             :     }
     168             : 
     169           7 :     clone->Set(value);
     170           7 :     return Locate(clone);
     171             : }
     172             : 
     173          13 : CommunityPtr CommunityDB::RemoveAndLocate(const Community *src,
     174             :     const std::vector<uint32_t> &value) {
     175             :     Community *clone;
     176          13 :     if (src) {
     177          13 :         clone = new Community(*src);
     178             :     } else {
     179           0 :         clone = new Community(this);
     180             :     }
     181             : 
     182          13 :     clone->Remove(value);
     183          13 :     return Locate(clone);
     184             : }
     185             : 
     186           8 : CommunityPtr CommunityDB::RemoveAndLocate(const Community *src,
     187             :                                           uint32_t value) {
     188           8 :     Community::CommunityList communities;
     189           8 :     communities.push_back(value);
     190          16 :     return RemoveAndLocate(src, communities);
     191           8 : }
     192             : 
     193       90308 : string ExtCommunitySpec::ToString() const {
     194             :     char repr[80];
     195       90308 :     snprintf(repr, sizeof(repr), "ExtCommunity <code: %d, flags: %02x>:%d",
     196       90308 :              code, flags, (uint32_t)communities.size());
     197       90308 :     return string(repr);
     198             : }
     199             : 
     200      183846 : LargeCommunitySpec LargeCommunitySpec::FromTag(
     201             :     const ExtCommunitySpec &ex_spec) {
     202      183846 :     LargeCommunitySpec large_spec;
     203             :     using extcomm_iterator = decltype(large_spec.communities)::iterator;
     204      183845 :     std::map<uint16_t, extcomm_iterator> tno_vs_tspec;
     205      183844 :     std::vector<std::pair<uint32_t,uint16_t> > asn4_vs_tno;
     206      183843 :     const uint64_t ExtCommTag = uint64_t(
     207             :         (BgpExtendedCommunityType::Experimental << 8) |
     208             :         (BgpExtendedCommunityExperimentalSubType::Tag)) << 48;
     209      183843 :     const uint64_t ExtCommTag4 = uint64_t(
     210             :         (BgpExtendedCommunityType::Experimental4ByteAs << 8) |
     211             :         (BgpExtendedCommunityExperimentalSubType::Tag)) << 48;
     212             :     uint16_t asn_or_tno;
     213             :     uint32_t asn4;
     214             :     uint16_t tno;
     215     1367448 :     for (const auto &val64 : ex_spec.communities) {
     216     1183605 :         if ((0xFFFF000000000000 & val64) == ExtCommTag) {
     217           8 :             asn_or_tno = (0x0000FFFF00000000 & val64) >> 32;
     218             :             std::vector<uint32_t> large_comm = {
     219           8 :                 asn_or_tno,
     220           8 :                 0x01000000 | uint32_t((val64 & 0x00000000FFFF0000) >> 16),
     221           8 :                 uint32_t(val64 & 0x000000000000FFFF)
     222           8 :             };
     223          16 :             extcomm_iterator it_tspec =  large_spec.communities.insert(
     224           8 :                 large_spec.communities.end(),
     225             :                 large_comm.begin(),
     226             :                 large_comm.end());
     227           8 :             tno_vs_tspec.insert({asn_or_tno,
     228             :                                 it_tspec});
     229           8 :             continue;
     230           8 :         }
     231             : 
     232     1183597 :         if ((0xFFFF000000000000 & val64) == ExtCommTag4) {
     233           0 :             asn4 = (0x0000FFFFFFFF0000 & val64) >> 16;
     234           0 :             tno  = (0x000000000000FFFF & val64);
     235           0 :             asn4_vs_tno.push_back({asn4, tno});
     236             :         }
     237             :     }
     238             :     // loop over all 4-byte ASNs and modify their value in large_spec
     239      183834 :     for(const auto &[asn4, tno] : asn4_vs_tno) {
     240           0 :         auto &large_comm_asn = tno_vs_tspec[tno];
     241           0 :         if (large_comm_asn == large_spec.communities.end()) {
     242           0 :             continue;
     243             :         }
     244           0 :         *large_comm_asn = asn4;
     245             :     }
     246      367683 :     return large_spec;
     247      183842 : }
     248             : 
     249           4 : ExtCommunitySpec LargeCommunitySpec::RemoveTags(
     250             :     const ExtCommunitySpec& ex_spec) {
     251           4 :     const uint64_t ExtCommTag = uint64_t(
     252             :         (BgpExtendedCommunityType::Experimental << 8) |
     253             :         (BgpExtendedCommunityExperimentalSubType::Tag)) << 48;
     254           4 :     const uint64_t ExtCommTag4 = uint64_t(
     255             :         (BgpExtendedCommunityType::Experimental4ByteAs << 8) |
     256             :         (BgpExtendedCommunityExperimentalSubType::Tag)) << 48;
     257           4 :     ExtCommunitySpec new_ex_spec;
     258          32 :     for (const auto &val64 : ex_spec.communities) {
     259          28 :         if ((0xFFFF000000000000 & val64) != ExtCommTag &&
     260          20 :             (0xFFFF000000000000 & val64) != ExtCommTag4) {
     261          20 :             new_ex_spec.communities.push_back(val64);
     262             :         }
     263             :     }
     264           4 :     return new_ex_spec;
     265           0 : }
     266             : 
     267      392943 : size_t ExtCommunitySpec::EncodeLength() const {
     268      392943 :     return communities.size() * sizeof(uint64_t);
     269             : }
     270             : 
     271        1941 : int ExtCommunitySpec::CompareTo(const BgpAttribute &rhs_attr) const {
     272        1941 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     273        1941 :     if (ret != 0) return ret;
     274        1941 :     KEY_COMPARE(communities,
     275             :         static_cast<const ExtCommunitySpec &>(rhs_attr).communities);
     276        1941 :     return 0;
     277             : }
     278             : 
     279      183805 : void ExtCommunitySpec::ToCanonical(BgpAttr *attr) {
     280      183805 :     attr->set_ext_community(this);
     281      183806 : }
     282             : 
     283        2079 : void ExtCommunitySpec::AddTunnelEncaps(vector<string> encaps) {
     284        2255 :     for (vector<string>::size_type i = 0; i < encaps.size(); i++) {
     285         176 :         string encap_str = encaps[i];
     286         176 :         TunnelEncap tun_encap(encap_str);
     287         176 :         communities.push_back(tun_encap.GetExtCommunityValue());
     288         176 :     }
     289        2079 : }
     290             : 
     291     4970527 : int ExtCommunity::CompareTo(const ExtCommunity &rhs) const {
     292     4970527 :     KEY_COMPARE(communities_.size(), rhs.communities_.size());
     293             : 
     294     3545553 :     ExtCommunityList::const_iterator i, j;
     295     3545553 :     for (i = communities_.begin(), j = rhs.communities_.begin();
     296    11891910 :          i < communities_.end(); ++i, ++j) {
     297     9440266 :         if (*i < *j) {
     298      659822 :             return -1;
     299             :         }
     300     8780779 :         if (*i > *j) {
     301      434304 :             return 1;
     302             :         }
     303             :     }
     304     2451467 :     return 0;
     305             : }
     306             : 
     307           6 : void ExtCommunity::Remove(const ExtCommunityList &list) {
     308           6 :     for (ExtCommunityList::const_iterator it = list.begin();
     309          18 :          it != list.end(); ++it) {
     310          24 :         communities_.erase(std::remove(communities_.begin(),
     311          36 :                     communities_.end(), *it), communities_.end());
     312             :     }
     313           6 : }
     314      184062 : void ExtCommunity::Remove() {
     315      184062 :     extcomm_db_->Delete(this);
     316      184062 : }
     317             : 
     318          41 : void ExtCommunity::Set(const ExtCommunityList &list) {
     319          41 :     communities_.clear();
     320          41 :     for (ExtCommunityList::const_iterator it = list.begin();
     321         155 :          it != list.end(); ++it) {
     322         114 :         communities_.push_back(*it);
     323             :     }
     324          41 : }
     325             : 
     326      425120 : void ExtCommunity::Append(const ExtCommunityList &list) {
     327      425120 :     communities_.insert(communities_.end(), list.begin(), list.end());
     328      425083 :     sort(communities_.begin(), communities_.end());
     329             :     ExtCommunityList::iterator it =
     330      425089 :         unique(communities_.begin(), communities_.end());
     331      425088 :     communities_.erase(it, communities_.end());
     332      425081 : }
     333             : 
     334       73189 : void ExtCommunity::Append(const ExtCommunityValue &value) {
     335       73189 :     communities_.push_back(value);
     336       73191 :     sort(communities_.begin(), communities_.end());
     337             :     ExtCommunityList::iterator it =
     338       73188 :         unique(communities_.begin(), communities_.end());
     339       73191 :     communities_.erase(it, communities_.end());
     340       73186 : }
     341             : 
     342          13 : ExtCommunity::ExtCommunityValue ExtCommunity::FromHexString(
     343             :         const string &comm, boost::system::error_code *errorp) {
     344             :     ExtCommunityValue data;
     345          13 :     put_value(&data[0], 8, 0);
     346             :     char *end;
     347          13 :     uint64_t value = strtoull(comm.c_str(), &end, 16);
     348          13 :     if (value == 0 || *end) {
     349             :         // e.g. 0 or 12x34ff (invalid hex)
     350           4 :         if (errorp != NULL) {
     351           4 :             *errorp = make_error_code(
     352             :                     boost::system::errc::invalid_argument);
     353           4 :             return data;
     354             :         }
     355             :     }
     356           9 :     if (comm[0] == '0' && (comm[1] == 'x' || comm[1] == 'X')) {
     357           5 :         if (comm.length() > 18 && errorp != NULL) {
     358             :             // e.g. 0xabcdef0123456789f is an invalid 8byte hex value
     359           1 :             *errorp = make_error_code(
     360             :                     boost::system::errc::invalid_argument);
     361           1 :             return data;
     362             :         }
     363             :     } else {
     364           4 :         if (comm.length() > 16 && errorp != NULL) {
     365             :             // e.g. abcdef0123456789f is an invalid 8byte hex value
     366           1 :             *errorp = make_error_code(
     367             :                     boost::system::errc::invalid_argument);
     368           1 :             return data;
     369             :         }
     370             :     }
     371           7 :     put_value(&data[0], 8, value);
     372           7 :     return data;
     373             : }
     374             : 
     375         371 : ExtCommunity::ExtCommunityList ExtCommunity::ExtCommunityFromString(
     376             :         const string &comm) {
     377         371 :     ExtCommunityList commList;
     378             :     ExtCommunityValue value;
     379         371 :     size_t pos = comm.find(':');
     380         371 :     string first(comm.substr(0, pos));
     381         371 :     boost::system::error_code error;
     382         371 :     if (first == "soo") {
     383           0 :         SiteOfOrigin soo = SiteOfOrigin::FromString(comm, &error);
     384           0 :         if (error) {
     385           0 :             return commList;
     386             :         }
     387           0 :         commList.push_back(soo.GetExtCommunity());
     388         371 :     } else if (first == "target") {
     389         357 :         RouteTarget rt = RouteTarget::FromString(comm, &error);
     390         357 :         if (error) {
     391          98 :             return commList;
     392             :         }
     393         259 :         commList.push_back(rt.GetExtCommunity());
     394          14 :     } else if (first == "source-as") {
     395           0 :         SourceAs sas = SourceAs::FromString(comm, &error);
     396           0 :         if (error) {
     397           0 :             return commList;
     398             :         }
     399           0 :         commList.push_back(sas.GetExtCommunity());
     400          14 :     } else if (first == "rt-import") {
     401           0 :         VrfRouteImport vit = VrfRouteImport::FromString(comm, &error);
     402           0 :         if (error) {
     403           0 :             return commList;
     404             :         }
     405           0 :         commList.push_back(vit.GetExtCommunity());
     406          14 :     } else if (first == "subcluster") {
     407           1 :         SubCluster sc = SubCluster::FromString(comm, &error);
     408           1 :         if (error) {
     409           0 :             return commList;
     410             :         }
     411           1 :         commList.push_back(sc.GetExtCommunity());
     412             :     } else {
     413          13 :         value = FromHexString(comm, &error);
     414          13 :         if (error) {
     415           6 :             return commList;
     416             :         }
     417           7 :         commList.push_back(value);
     418             :     }
     419         267 :     return commList;
     420         371 : }
     421             : 
     422         106 : string ExtCommunity::ToHexString(const ExtCommunityValue &comm) {
     423             :     char temp[50];
     424         106 :     int len = 0;
     425         954 :     for (size_t i = 0; i < comm.size(); i++) {
     426         848 :         len += snprintf(temp+len, sizeof(temp) - len, "%02x", (comm)[i]);
     427             :     }
     428         106 :     return(string(temp));
     429             : }
     430             : 
     431         223 : string ExtCommunity::ToString(const ExtCommunityValue &comm) {
     432         223 :     if (is_route_target(comm)) {
     433         217 :         RouteTarget rt(comm);
     434         217 :         return(rt.ToString());
     435           6 :     } else if (is_default_gateway(comm)) {
     436           0 :         DefaultGateway dgw(comm);
     437           0 :         return(dgw.ToString());
     438           6 :     } else if (is_es_import(comm)) {
     439           0 :         EsImport es_import(comm);
     440           0 :         return(es_import.ToString());
     441           6 :     } else if (is_esi_label(comm)) {
     442           0 :         EsiLabel esi_label(comm);
     443           0 :         return(esi_label.ToString());
     444           6 :     } else if (is_mac_mobility(comm)) {
     445           0 :         MacMobility mm(comm);
     446           0 :         return(mm.ToString());
     447           6 :     } else if (is_local_sequence_number(comm)) {
     448           0 :         LocalSequenceNumber lsn(comm);
     449           0 :         return lsn.ToString();
     450           6 :     } else if (is_etree(comm)) {
     451           0 :         ETree etree(comm);
     452           0 :         return(etree.ToString());
     453           6 :     } else if (is_router_mac(comm)) {
     454           0 :         RouterMac router_mac(comm);
     455           0 :         return(router_mac.ToString());
     456           6 :     } else if (is_origin_vn(comm)) {
     457           0 :         OriginVn origin_vn(comm);
     458           0 :         return(origin_vn.ToString());
     459           6 :     } else if (is_security_group(comm)) {
     460           0 :         SecurityGroup sg(comm);
     461           0 :         return(sg.ToString());
     462           6 :     } else if (is_site_of_origin(comm)) {
     463           0 :         SiteOfOrigin soo(comm);
     464           0 :         return(soo.ToString());
     465           6 :     } else if (is_tunnel_encap(comm)) {
     466           0 :         TunnelEncap encap(comm);
     467           0 :         return(encap.ToString());
     468           6 :     } else if (is_load_balance(comm)) {
     469           0 :         LoadBalance load_balance(comm);
     470           0 :         return(load_balance.ToString());
     471           6 :     } else if (is_tag(comm)) {
     472           0 :         Tag tag(comm);
     473           0 :         return(tag.ToString());
     474           6 :     } else if (is_source_as(comm)) {
     475           0 :         SourceAs sas(comm);
     476           0 :         return(sas.ToString());
     477           6 :     } else if (is_vrf_route_import(comm)) {
     478           0 :         VrfRouteImport rt_import(comm);
     479           0 :         return(rt_import.ToString());
     480           6 :     } else if (is_sub_cluster(comm)) {
     481           3 :         SubCluster sc(comm);
     482           3 :         return(sc.ToString());
     483             :     }
     484           3 :     return ToHexString(comm);
     485             : }
     486             : 
     487           4 : bool ExtCommunity::ContainsRTarget(const ExtCommunityValue &val) const {
     488           4 :     for (ExtCommunityList::const_iterator it = communities_.begin();
     489           4 :          it != communities_.end(); ++it) {
     490           4 :         if (ExtCommunity::is_route_target(*it) && *it == val)
     491           4 :             return true;
     492             :     }
     493           0 :     return false;
     494             : }
     495             : 
     496       97871 : bool ExtCommunity::ContainsOriginVn(const ExtCommunityValue &val) const {
     497       97871 :     for (ExtCommunityList::const_iterator it = communities_.begin();
     498      833403 :          it != communities_.end(); ++it) {
     499      742561 :         if (ExtCommunity::is_origin_vn(*it) && *it == val)
     500        7027 :             return true;
     501             :     }
     502       90842 :     return false;
     503             : }
     504             : 
     505       97870 : bool ExtCommunity::ContainsOriginVn(as_t asn, uint32_t vn_index) const {
     506             :     if (asn <= 0xffffffff) {
     507       97870 :         OriginVn origin_vn(asn, vn_index);
     508       97871 :         return ContainsOriginVn(origin_vn.GetExtCommunity());
     509             :     }
     510             :     OriginVn origin_vn4(asn, AS_TRANS);
     511             :     OriginVn origin_vn(AS_TRANS, vn_index);
     512             :     return (ContainsOriginVn(origin_vn.GetExtCommunity()) &&
     513             :                 ContainsOriginVn(origin_vn4.GetExtCommunity()));
     514             : }
     515             : 
     516          80 : bool ExtCommunity::ContainsSourceAs(const ExtCommunityValue &val) const {
     517          80 :     for (ExtCommunityList::const_iterator it = communities_.begin();
     518         168 :          it != communities_.end(); ++it) {
     519         168 :         if (ExtCommunity::is_source_as(*it) && *it == val)
     520          80 :             return true;
     521             :     }
     522           0 :     return false;
     523             : }
     524             : 
     525      387189 : uint32_t ExtCommunity::GetSubClusterId() const {
     526      387189 :     for (ExtCommunityList::const_iterator it = communities_.begin();
     527     2863790 :             it != communities_.end(); ++it) {
     528     2476613 :         if (ExtCommunity::is_sub_cluster(*it)) {
     529           2 :             SubCluster sc(*it);
     530           2 :             return sc.GetId();
     531             :         }
     532             :     }
     533      387150 :     return 0;
     534             : }
     535             : 
     536          80 : bool ExtCommunity::ContainsVrfRouteImport(const ExtCommunityValue &val) const {
     537          80 :     for (ExtCommunityList::const_iterator it = communities_.begin();
     538         248 :          it != communities_.end(); ++it) {
     539         248 :         if (ExtCommunity::is_vrf_route_import(*it) && *it == val)
     540          80 :             return true;
     541             :     }
     542           0 :     return false;
     543             : }
     544             : 
     545       19890 : void ExtCommunity::RemoveMFlags() {
     546       19890 :     for (ExtCommunityList::iterator it = communities_.begin();
     547       46296 :          it != communities_.end(); ) {
     548       26406 :         if (ExtCommunity::is_multicast_flags(*it)) {
     549           0 :             it = communities_.erase(it);
     550             :         } else {
     551       26406 :             ++it;
     552             :         }
     553             :     }
     554       19890 : }
     555             : 
     556       32585 : void ExtCommunity::RemoveRTarget() {
     557       32585 :     for (ExtCommunityList::iterator it = communities_.begin();
     558       82224 :          it != communities_.end(); ) {
     559       49638 :         if (ExtCommunity::is_route_target(*it)) {
     560       25458 :             it = communities_.erase(it);
     561             :         } else {
     562       24180 :             ++it;
     563             :         }
     564             :     }
     565       32586 : }
     566             : 
     567       24230 : void ExtCommunity::RemoveSGID() {
     568       24230 :     for (ExtCommunityList::iterator it = communities_.begin();
     569       44351 :          it != communities_.end(); ) {
     570       36427 :         if (ExtCommunity::is_security_group(*it) ||
     571       16306 :                 ExtCommunity::is_security_group4(*it)) {
     572        3815 :             it = communities_.erase(it);
     573             :         } else {
     574       16306 :             ++it;
     575             :         }
     576             :     }
     577       24230 : }
     578             : 
     579           0 : void ExtCommunity::RemoveTag() {
     580           0 :     for (ExtCommunityList::iterator it = communities_.begin();
     581           0 :          it != communities_.end(); ) {
     582           0 :         if (ExtCommunity::is_tag(*it) || ExtCommunity::is_tag4(*it)) {
     583           0 :             it = communities_.erase(it);
     584             :         } else {
     585           0 :             ++it;
     586             :         }
     587             :     }
     588           0 : }
     589             : 
     590       18971 : void ExtCommunity::RemoveSiteOfOrigin() {
     591       18971 :     for (ExtCommunityList::iterator it = communities_.begin();
     592       38101 :          it != communities_.end(); ) {
     593       19130 :         if (ExtCommunity::is_site_of_origin(*it)) {
     594           0 :             it = communities_.erase(it);
     595             :         } else {
     596       19130 :             ++it;
     597             :         }
     598             :     }
     599       18971 : }
     600             : 
     601         380 : void ExtCommunity::RemoveSourceAS() {
     602         380 :     for (ExtCommunityList::iterator it = communities_.begin();
     603        1888 :          it != communities_.end(); ) {
     604        1508 :         if (ExtCommunity::is_source_as(*it)) {
     605         156 :             it = communities_.erase(it);
     606             :         } else {
     607        1352 :             ++it;
     608             :         }
     609             :     }
     610         380 : }
     611         114 : void ExtCommunity::RemoveVrfRouteImport() {
     612         114 :     for (ExtCommunityList::iterator it = communities_.begin();
     613         242 :          it != communities_.end(); ) {
     614         128 :         if (ExtCommunity::is_vrf_route_import(*it)) {
     615           0 :             it = communities_.erase(it);
     616             :         } else {
     617         128 :             ++it;
     618             :         }
     619             :     }
     620         114 : }
     621             : 
     622      244718 : void ExtCommunity::RemoveOriginVn() {
     623      244718 :     for (ExtCommunityList::iterator it = communities_.begin();
     624     1807618 :          it != communities_.end(); ) {
     625     1562965 :         if (ExtCommunity::is_origin_vn(*it))
     626       15416 :             it = communities_.erase(it);
     627             :         else
     628     1547504 :             ++it;
     629             :     }
     630      244558 : }
     631             : 
     632       17768 : void ExtCommunity::RemoveTunnelEncapsulation() {
     633       17768 :     for (ExtCommunityList::iterator it = communities_.begin();
     634       36915 :          it != communities_.end(); ) {
     635       19147 :         if (ExtCommunity::is_tunnel_encap(*it)) {
     636         167 :             it = communities_.erase(it);
     637             :         } else {
     638       18980 :             ++it;
     639             :         }
     640             :     }
     641       17768 : }
     642             : 
     643           8 : void ExtCommunity::RemoveLoadBalance() {
     644           8 :     for (ExtCommunityList::iterator it = communities_.begin();
     645           8 :          it != communities_.end(); ) {
     646           0 :         if (ExtCommunity::is_load_balance(*it)) {
     647           0 :             it = communities_.erase(it);
     648             :         } else {
     649           0 :             ++it;
     650             :         }
     651             :     }
     652           8 : }
     653             : 
     654           1 : void ExtCommunity::RemoveSubCluster() {
     655           1 :     for (ExtCommunityList::iterator it = communities_.begin();
     656           2 :          it != communities_.end(); ) {
     657           1 :         if (ExtCommunity::is_sub_cluster(*it)) {
     658           1 :             it = communities_.erase(it);
     659             :         } else {
     660           0 :             ++it;
     661             :         }
     662             :     }
     663           1 : }
     664             : 
     665      475187 : vector<string> ExtCommunity::GetTunnelEncap() const {
     666      475187 :     vector<string> encap_list;
     667      475232 :     for (ExtCommunityList::const_iterator iter = communities_.begin();
     668     3289874 :          iter != communities_.end(); ++iter) {
     669     2814439 :         if (!ExtCommunity::is_tunnel_encap(*iter))
     670     2338444 :             continue;
     671      476124 :         TunnelEncap encap(*iter);
     672      476136 :         if (encap.tunnel_encap() == TunnelEncapType::UNSPEC)
     673           0 :             continue;
     674      476105 :         encap_list.push_back(encap.ToXmppString());
     675             :     }
     676             : 
     677      475325 :     sort(encap_list.begin(), encap_list.end());
     678             :     vector<string>::iterator encap_iter =
     679      475326 :         unique(encap_list.begin(), encap_list.end());
     680      475275 :     encap_list.erase(encap_iter, encap_list.end());
     681      950388 :     return encap_list;
     682           0 : }
     683             : 
     684           0 : vector<int> ExtCommunity::GetTagList(as2_t asn) const {
     685           0 :     vector<int> tag_list;
     686           0 :     for (ExtCommunityList::const_iterator iter = communities_.begin();
     687           0 :          iter != communities_.end(); ++iter) {
     688           0 :         if (!ExtCommunity::is_tag(*iter))
     689           0 :             continue;
     690           0 :         Tag tag_comm(*iter);
     691           0 :         if (asn && tag_comm.as_number() != asn && !tag_comm.IsGlobal())
     692           0 :             continue;
     693           0 :         tag_list.push_back(tag_comm.tag());
     694             :     }
     695             : 
     696           0 :     sort(tag_list.begin(), tag_list.end());
     697           0 :     vector<int>::iterator tag_iter = unique(tag_list.begin(), tag_list.end());
     698           0 :     tag_list.erase(tag_iter, tag_list.end());
     699           0 :     return tag_list;
     700           0 : }
     701             : 
     702           0 : vector<int> ExtCommunity::GetTag4List(as_t asn) const {
     703           0 :     vector<int> tag_list;
     704           0 :     for (ExtCommunityList::const_iterator iter = communities_.begin();
     705           0 :          iter != communities_.end(); ++iter) {
     706           0 :         if (!ExtCommunity::is_tag4(*iter))
     707           0 :             continue;
     708           0 :         Tag4ByteAs tag_comm(*iter);
     709           0 :         if (asn && tag_comm.as_number() != asn && !tag_comm.IsGlobal())
     710           0 :             continue;
     711           0 :         vector<int> matching_tag_list = GetTagList(tag_comm.tag());
     712           0 :         tag_list.insert(tag_list.end(), matching_tag_list.begin(),
     713             :                         matching_tag_list.end());
     714           0 :         tag_list.push_back(tag_comm.tag());
     715           0 :     }
     716           0 :     if ((asn <= 0xffff) && tag_list.size() == 0)
     717           0 :         tag_list = GetTagList(asn);
     718             : 
     719           0 :     sort(tag_list.begin(), tag_list.end());
     720           0 :     vector<int>::iterator tag_iter = unique(tag_list.begin(), tag_list.end());
     721           0 :     tag_list.erase(tag_iter, tag_list.end());
     722           0 :     return tag_list;
     723           0 : }
     724             : 
     725      139468 : bool ExtCommunity::ContainsTunnelEncapVxlan() const {
     726      139468 :     for (ExtCommunityList::const_iterator iter = communities_.begin();
     727     1968772 :          iter != communities_.end(); ++iter) {
     728     1829744 :         if (!ExtCommunity::is_tunnel_encap(*iter))
     729     1658103 :             continue;
     730      171657 :         TunnelEncap encap(*iter);
     731      171658 :         if (encap.tunnel_encap() == TunnelEncapType::VXLAN)
     732         448 :             return true;
     733             :     }
     734      139005 :     return false;
     735             : }
     736             : 
     737      449190 : int ExtCommunity::GetOriginVnIndex() const {
     738      449190 :     for (ExtCommunityList::const_iterator iter = communities_.begin();
     739     3151305 :          iter != communities_.end(); ++iter) {
     740     2733157 :         if (ExtCommunity::is_origin_vn(*iter)) {
     741       31023 :             OriginVn origin_vn(*iter);
     742       31025 :             return origin_vn.vn_index();
     743             :         }
     744             :     }
     745      418226 :     return -1;
     746             : }
     747             : 
     748      190474 : ExtCommunity::ExtCommunity(ExtCommunityDB *extcomm_db,
     749      190474 :         const ExtCommunitySpec spec) : extcomm_db_(extcomm_db) {
     750      190472 :     refcount_ = 0;
     751      190483 :     for (vector<uint64_t>::const_iterator it = spec.communities.begin();
     752     1379544 :          it < spec.communities.end(); ++it) {
     753             :         ExtCommunityValue comm;
     754     1189061 :         put_value(comm.data(), comm.size(), *it);
     755     1189060 :         communities_.push_back(comm);
     756             :     }
     757      190476 :     sort(communities_.begin(), communities_.end());
     758             :     ExtCommunityList::iterator it =
     759      190477 :         unique(communities_.begin(), communities_.end());
     760      190470 :     communities_.erase(it, communities_.end());
     761      190471 : }
     762             : 
     763        9743 : ExtCommunityDB::ExtCommunityDB(BgpServer *server) {
     764        9743 : }
     765             : 
     766      330594 : ExtCommunityPtr ExtCommunityDB::AppendAndLocate(const ExtCommunity *src,
     767             :         const ExtCommunity::ExtCommunityList &list) {
     768             :     ExtCommunity *clone;
     769      330594 :     if (src) {
     770      188991 :         clone = new ExtCommunity(*src);
     771             :     } else {
     772      141603 :         clone = new ExtCommunity(this);
     773             :     }
     774             : 
     775      330666 :     clone->Append(list);
     776      330614 :     return Locate(clone);
     777             : }
     778             : 
     779          64 : ExtCommunityPtr ExtCommunityDB::AppendAndLocate(const ExtCommunity *src,
     780             :         const ExtCommunity::ExtCommunityValue &value) {
     781          64 :     ExtCommunity::ExtCommunityList list;
     782          64 :     list.push_back(value);
     783         128 :     return AppendAndLocate(src, list);
     784          64 : }
     785             : 
     786           6 : ExtCommunityPtr ExtCommunityDB::RemoveAndLocate(const ExtCommunity *src,
     787             :         const ExtCommunity::ExtCommunityList &list) {
     788             :     ExtCommunity *clone;
     789           6 :     if (src) {
     790           5 :         clone = new ExtCommunity(*src);
     791             :     } else {
     792           1 :         clone = new ExtCommunity(this);
     793             :     }
     794             : 
     795           6 :     clone->Remove(list);
     796           6 :     return Locate(clone);
     797             : }
     798             : 
     799       19890 : ExtCommunityPtr ExtCommunityDB::ReplaceMFlagsAndLocate(const ExtCommunity *src,
     800             :         const ExtCommunity::ExtCommunityList &export_list) {
     801             :     ExtCommunity *clone;
     802       19890 :     if (src) {
     803       19890 :         clone = new ExtCommunity(*src);
     804             :     } else {
     805           0 :         clone = new ExtCommunity(this);
     806             :     }
     807             : 
     808       19890 :     clone->RemoveMFlags();
     809       19890 :     clone->Append(export_list);
     810       19890 :     return Locate(clone);
     811             : }
     812             : 
     813       32586 : ExtCommunityPtr ExtCommunityDB::ReplaceRTargetAndLocate(const ExtCommunity *src,
     814             :         const ExtCommunity::ExtCommunityList &export_list) {
     815             :     ExtCommunity *clone;
     816       32586 :     if (src) {
     817       27298 :         clone = new ExtCommunity(*src);
     818             :     } else {
     819        5288 :         clone = new ExtCommunity(this);
     820             :     }
     821             : 
     822       32586 :     clone->RemoveRTarget();
     823       32586 :     clone->Append(export_list);
     824       32586 :     return Locate(clone);
     825             : }
     826             : 
     827       24230 : ExtCommunityPtr ExtCommunityDB::ReplaceSGIDListAndLocate(
     828             :     const ExtCommunity *src,
     829             :     const ExtCommunity::ExtCommunityList &sgid_list) {
     830             :     ExtCommunity *clone;
     831       24230 :     if (src) {
     832       24230 :         clone = new ExtCommunity(*src);
     833             :     } else {
     834           0 :         clone = new ExtCommunity(this);
     835             :     }
     836             : 
     837       24230 :     clone->RemoveSGID();
     838       24230 :     clone->Append(sgid_list);
     839       24230 :     return Locate(clone);
     840             : }
     841             : 
     842           0 : ExtCommunityPtr ExtCommunityDB::ReplaceTagListAndLocate(
     843             :     const ExtCommunity *src,
     844             :     const ExtCommunity::ExtCommunityList &tag_list) {
     845             :     ExtCommunity *clone;
     846           0 :     if (src) {
     847           0 :         clone = new ExtCommunity(*src);
     848             :     } else {
     849           0 :         clone = new ExtCommunity(this);
     850             :     }
     851             : 
     852           0 :     clone->RemoveTag();
     853           0 :     clone->Append(tag_list);
     854           0 :     return Locate(clone);
     855             : }
     856             : 
     857       18760 : ExtCommunityPtr ExtCommunityDB::RemoveSiteOfOriginAndLocate(
     858             :         const ExtCommunity *src) {
     859             :     ExtCommunity *clone;
     860       18760 :     if (src) {
     861       18760 :         clone = new ExtCommunity(*src);
     862             :     } else {
     863           0 :         clone = new ExtCommunity(this);
     864             :     }
     865             : 
     866       18760 :     clone->RemoveSiteOfOrigin();
     867       18760 :     return Locate(clone);
     868             : }
     869             : 
     870         211 : ExtCommunityPtr ExtCommunityDB::ReplaceSiteOfOriginAndLocate(
     871             :         const ExtCommunity *src,
     872             :         const ExtCommunity::ExtCommunityValue &soo) {
     873             :     ExtCommunity *clone;
     874         211 :     if (src) {
     875         211 :         clone = new ExtCommunity(*src);
     876             :     } else {
     877           0 :         clone = new ExtCommunity(this);
     878             :     }
     879             : 
     880         211 :     clone->RemoveSiteOfOrigin();
     881         211 :     clone->Append(soo);
     882         211 :     return Locate(clone);
     883             : }
     884             : 
     885         156 : ExtCommunityPtr ExtCommunityDB::RemoveSourceASAndLocate(
     886             :         const ExtCommunity *src) {
     887             :     ExtCommunity *clone;
     888         156 :     if (src) {
     889         156 :         clone = new ExtCommunity(*src);
     890             :     } else {
     891           0 :         clone = new ExtCommunity(this);
     892             :     }
     893             : 
     894         156 :     clone->RemoveSourceAS();
     895         156 :     return Locate(clone);
     896             : }
     897             : 
     898         224 : ExtCommunityPtr ExtCommunityDB::ReplaceSourceASAndLocate(
     899             :         const ExtCommunity *src,
     900             :         const ExtCommunity::ExtCommunityValue &sas) {
     901             :     ExtCommunity *clone;
     902         224 :     if (src) {
     903         224 :         clone = new ExtCommunity(*src);
     904             :     } else {
     905           0 :         clone = new ExtCommunity(this);
     906             :     }
     907             : 
     908         224 :     clone->RemoveSourceAS();
     909         224 :     clone->Append(sas);
     910         224 :     return Locate(clone);
     911             : }
     912             : 
     913           0 : ExtCommunityPtr ExtCommunityDB::RemoveVrfRouteImportAndLocate(
     914             :         const ExtCommunity *src) {
     915             :     ExtCommunity *clone;
     916           0 :     if (src) {
     917           0 :         clone = new ExtCommunity(*src);
     918             :     } else {
     919           0 :         clone = new ExtCommunity(this);
     920             :     }
     921             : 
     922           0 :     clone->RemoveVrfRouteImport();
     923           0 :     return Locate(clone);
     924             : }
     925             : 
     926         114 : ExtCommunityPtr ExtCommunityDB::ReplaceVrfRouteImportAndLocate(
     927             :         const ExtCommunity *src,
     928             :         const ExtCommunity::ExtCommunityValue &vit) {
     929             :     ExtCommunity *clone;
     930         114 :     if (src) {
     931          66 :         clone = new ExtCommunity(*src);
     932             :     } else {
     933          48 :         clone = new ExtCommunity(this);
     934             :     }
     935             : 
     936         114 :     clone->RemoveVrfRouteImport();
     937         114 :     clone->Append(vit);
     938         114 :     return Locate(clone);
     939             : }
     940             : 
     941      172052 : ExtCommunityPtr ExtCommunityDB::RemoveOriginVnAndLocate(
     942             :         const ExtCommunity *src) {
     943             :     ExtCommunity *clone;
     944      172052 :     if (src) {
     945      172052 :         clone = new ExtCommunity(*src);
     946             :     } else {
     947           0 :         clone = new ExtCommunity(this);
     948             :     }
     949             : 
     950      172112 :     clone->RemoveOriginVn();
     951      171922 :     return Locate(clone);
     952             : }
     953             : 
     954       72635 : ExtCommunityPtr ExtCommunityDB::ReplaceOriginVnAndLocate(
     955             :         const ExtCommunity *src,
     956             :         const ExtCommunity::ExtCommunityValue &origin_vn) {
     957             :     ExtCommunity *clone;
     958       72635 :     if (src) {
     959       72630 :         clone = new ExtCommunity(*src);
     960             :     } else {
     961           5 :         clone = new ExtCommunity(this);
     962             :     }
     963             : 
     964       72640 :     clone->RemoveOriginVn();
     965       72633 :     clone->Append(origin_vn);
     966       72628 :     return Locate(clone);
     967             : }
     968             : 
     969       17768 : ExtCommunityPtr ExtCommunityDB::ReplaceTunnelEncapsulationAndLocate(
     970             :         const ExtCommunity *src,
     971             :         const ExtCommunity::ExtCommunityList &tunnel_encaps) {
     972             :     ExtCommunity *clone;
     973       17768 :     if (src) {
     974       17768 :         clone = new ExtCommunity(*src);
     975             :     } else {
     976           0 :         clone = new ExtCommunity(this);
     977             :     }
     978             : 
     979       17768 :     clone->RemoveTunnelEncapsulation();
     980       17768 :     clone->Append(tunnel_encaps);
     981       17768 :     return Locate(clone);
     982             : }
     983             : 
     984           8 : ExtCommunityPtr ExtCommunityDB::ReplaceLoadBalanceAndLocate(
     985             :         const ExtCommunity *src,
     986             :         const ExtCommunity::ExtCommunityValue &lb) {
     987             :     ExtCommunity *clone;
     988           8 :     if (src) {
     989           8 :         clone = new ExtCommunity(*src);
     990             :     } else {
     991           0 :         clone = new ExtCommunity(this);
     992             :     }
     993             : 
     994           8 :     clone->RemoveLoadBalance();
     995           8 :     clone->Append(lb);
     996           8 :     return Locate(clone);
     997             : }
     998             : 
     999           1 : ExtCommunityPtr ExtCommunityDB::ReplaceSubClusterAndLocate(
    1000             :         const ExtCommunity *src,
    1001             :         const ExtCommunity::ExtCommunityValue &sc) {
    1002             :     ExtCommunity *clone;
    1003           1 :     if (src) {
    1004           1 :         clone = new ExtCommunity(*src);
    1005             :     } else {
    1006           0 :         clone = new ExtCommunity(this);
    1007             :     }
    1008             : 
    1009           1 :     clone->RemoveSubCluster();
    1010           1 :     clone->Append(sc);
    1011           1 :     return Locate(clone);
    1012             : }
    1013             : 
    1014          41 : ExtCommunityPtr ExtCommunityDB::SetAndLocate(const ExtCommunity *src,
    1015             :         const ExtCommunity::ExtCommunityList &value) {
    1016             :     ExtCommunity *clone;
    1017          41 :     if (src) {
    1018           2 :         clone = new ExtCommunity(*src);
    1019             :     } else {
    1020          39 :         clone = new ExtCommunity(this);
    1021             :     }
    1022             : 
    1023          41 :     clone->Set(value);
    1024          41 :     return Locate(clone);
    1025             : }
    1026             : 
    1027           6 : string LargeCommunitySpec::ToString() const {
    1028             :     char repr[80];
    1029           6 :     snprintf(repr, sizeof(repr), "LargeCommunity <code: %d, flags: %02x>:%d",
    1030           6 :              code, flags, (uint32_t)communities.size() / 3);
    1031           6 :     return string(repr);
    1032             : }
    1033             : 
    1034          18 : size_t LargeCommunitySpec::EncodeLength() const {
    1035          18 :     return communities.size() * sizeof(uint32_t);
    1036             : }
    1037             : 
    1038           0 : int LargeCommunitySpec::CompareTo(const BgpAttribute &rhs_attr) const {
    1039           0 :     int ret = BgpAttribute::CompareTo(rhs_attr);
    1040           0 :     if (ret != 0) return ret;
    1041           0 :     KEY_COMPARE(communities,
    1042             :         static_cast<const LargeCommunitySpec &>(rhs_attr).communities);
    1043           0 :     return 0;
    1044             : }
    1045             : 
    1046          44 : void LargeCommunitySpec::ToCanonical(BgpAttr *attr) {
    1047             :     // add LarceComm to attr
    1048          44 :     attr->set_large_community(this);
    1049          44 : }
    1050             : 
    1051      407053 : int LargeCommunity::CompareTo(const LargeCommunity &rhs) const {
    1052      407053 :     KEY_COMPARE(communities_.size(), rhs.communities_.size());
    1053             : 
    1054      406845 :     LargeCommunityList::const_iterator i, j;
    1055      406845 :     for (i = communities_.begin(), j = rhs.communities_.begin();
    1056      407180 :          i < communities_.end(); ++i, ++j) {
    1057         409 :         if (*i < *j) {
    1058          38 :             return -1;
    1059             :         }
    1060         371 :         if (*i > *j) {
    1061          35 :             return 1;
    1062             :         }
    1063             :     }
    1064      406771 :     return 0;
    1065             : }
    1066             : 
    1067           0 : void LargeCommunity::Remove(const LargeCommunityList &list) {
    1068           0 :     for (LargeCommunityList::const_iterator it = list.begin();
    1069           0 :          it != list.end(); ++it) {
    1070           0 :         communities_.erase(std::remove(communities_.begin(),
    1071           0 :                     communities_.end(), *it), communities_.end());
    1072             :     }
    1073           0 : }
    1074        6443 : void LargeCommunity::Remove() {
    1075        6443 :     largecomm_db_->Delete(this);
    1076        6443 : }
    1077             : 
    1078           0 : void LargeCommunity::Set(const LargeCommunityList &list) {
    1079           0 :     communities_.clear();
    1080           0 :     for (LargeCommunityList::const_iterator it = list.begin();
    1081           0 :          it != list.end(); ++it) {
    1082           0 :         communities_.push_back(*it);
    1083             :     }
    1084           0 : }
    1085             : 
    1086       18971 : void LargeCommunity::Append(const LargeCommunityList &list) {
    1087       18971 :     communities_.insert(communities_.end(), list.begin(), list.end());
    1088       18971 :     sort(communities_.begin(), communities_.end());
    1089             :     LargeCommunityList::iterator it =
    1090       18971 :         unique(communities_.begin(), communities_.end());
    1091       18971 :     communities_.erase(it, communities_.end());
    1092       18971 : }
    1093             : 
    1094           0 : void LargeCommunity::Append(const LargeCommunityValue &value) {
    1095           0 :     communities_.push_back(value);
    1096           0 :     sort(communities_.begin(), communities_.end());
    1097             :     LargeCommunityList::iterator it =
    1098           0 :         unique(communities_.begin(), communities_.end());
    1099           0 :     communities_.erase(it, communities_.end());
    1100           0 : }
    1101             : 
    1102           0 : LargeCommunity::LargeCommunityValue LargeCommunity::FromHexString(
    1103             :         const string &comm, boost::system::error_code *errorp) {
    1104             :     LargeCommunityValue data;
    1105           0 :     put_value(&data[0], 12, 0);
    1106             :     char *end;
    1107           0 :     uint64_t value = strtoull(comm.c_str(), &end, 24);
    1108           0 :     if (value == 0 || *end) {
    1109             :         // e.g. 0 or 12x34ff (invalid hex)
    1110           0 :         if (errorp != NULL) {
    1111           0 :             *errorp = make_error_code(
    1112             :                     boost::system::errc::invalid_argument);
    1113           0 :             return data;
    1114             :         }
    1115             :     }
    1116           0 :     if (comm[0] == '0' && (comm[1] == 'x' || comm[1] == 'X')) {
    1117           0 :         if (comm.length() > 26 && errorp != NULL) {
    1118             :             // e.g. 0xabcdef0123456789abcdef012 is an invalid 8byte hex value
    1119           0 :             *errorp = make_error_code(
    1120             :                     boost::system::errc::invalid_argument);
    1121           0 :             return data;
    1122             :         }
    1123             :     } else {
    1124           0 :         if (comm.length() > 24 && errorp != NULL) {
    1125             :             // e.g. abcdef0123456789abcdef012 is an invalid 8byte hex value
    1126           0 :             *errorp = make_error_code(
    1127             :                     boost::system::errc::invalid_argument);
    1128           0 :             return data;
    1129             :         }
    1130             :     }
    1131           0 :     put_value(&data[0], 12, value);
    1132           0 :     return data;
    1133             : }
    1134             : 
    1135           0 : LargeCommunity::LargeCommunityList LargeCommunity::LargeCommunityFromString(
    1136             :         const string &comm) {
    1137           0 :     LargeCommunityList commList;
    1138             :     LargeCommunityValue value;
    1139           0 :     size_t pos = comm.find(':');
    1140           0 :     string first(comm.substr(0, pos));
    1141           0 :     boost::system::error_code error;
    1142           0 :     value = FromHexString(comm, &error);
    1143           0 :     if (error) {
    1144           0 :         return commList;
    1145             :     }
    1146           0 :     commList.push_back(value);
    1147           0 :     return commList;
    1148           0 : }
    1149             : 
    1150           0 : string LargeCommunity::ToHexString(const LargeCommunityValue &comm) {
    1151             :     char temp[50];
    1152           0 :     int len = 0;
    1153           0 :     for (size_t i = 0; i < comm.size(); i++) {
    1154           0 :         len += snprintf(temp+len, sizeof(temp) - len, "%02x", (comm)[i]);
    1155             :     }
    1156           0 :     return(string(temp));
    1157             : }
    1158             : 
    1159           0 : string LargeCommunity::ToString(const LargeCommunityValue &comm) {
    1160           0 :     if (is_tag(comm)) {
    1161           0 :         TagLC tag(comm);
    1162           0 :         return(tag.ToString());
    1163             :     }
    1164           0 :     return ToHexString(comm);
    1165             : }
    1166             : 
    1167       18971 : void LargeCommunity::RemoveTag() {
    1168       18971 :     for (LargeCommunityList::iterator it = communities_.begin();
    1169       18971 :          it != communities_.end(); ) {
    1170           0 :         if (LargeCommunity::is_tag(*it)) {
    1171           0 :             it = communities_.erase(it);
    1172             :         } else {
    1173           0 :             ++it;
    1174             :         }
    1175             :     }
    1176       18971 : }
    1177             : 
    1178      445547 : vector<uint64_t> LargeCommunity::GetTagList(as_t asn) const {
    1179      445547 :     vector<uint64_t> tag_list;
    1180      445609 :     for (const auto &lc : communities_) {
    1181          32 :         if (!LargeCommunity::is_tag(lc))
    1182           2 :             continue;
    1183          32 :         TagLC tag_comm(lc);
    1184          32 :         if (asn && tag_comm.as_number() != asn && !tag_comm.IsGlobal())
    1185           2 :             continue;
    1186          30 :         tag_list.push_back(tag_comm.tag());
    1187             :     }
    1188             : 
    1189      445543 :     sort(tag_list.begin(), tag_list.end());
    1190      445527 :     vector<uint64_t>::iterator tag_iter = unique(tag_list.begin(),
    1191             :                                                  tag_list.end());
    1192      445485 :     tag_list.erase(tag_iter, tag_list.end());
    1193      890970 :     return tag_list;
    1194           0 : }
    1195             : 
    1196             : 
    1197      183880 : LargeCommunity::LargeCommunity(LargeCommunityDB *largecomm_db,
    1198      183880 :         const LargeCommunitySpec spec) : largecomm_db_(largecomm_db) {
    1199      183881 :     refcount_ = 0;
    1200      183890 :     std::vector<uint32_t>::const_iterator lcit = spec.communities.begin();
    1201      183994 :     while (lcit < spec.communities.end()) {
    1202             :         LargeCommunityValue comm;
    1203         104 :         put_value(comm.data(), 4, *lcit);
    1204         104 :         lcit++;
    1205         104 :         put_value(comm.data()+4, 4, *lcit);
    1206         104 :         lcit++;
    1207         104 :         put_value(comm.data()+8, 4, *lcit);
    1208         104 :         lcit++;
    1209         104 :         communities_.push_back(comm);
    1210             :     }
    1211      183888 :     sort(communities_.begin(), communities_.end());
    1212             :     LargeCommunityList::iterator it =
    1213      183881 :         unique(communities_.begin(), communities_.end());
    1214      183883 :     communities_.erase(it, communities_.end());
    1215      183880 : }
    1216             : 
    1217        9743 : LargeCommunityDB::LargeCommunityDB(BgpServer *server) {
    1218        9743 : }
    1219             : 
    1220           0 : LargeCommunityPtr LargeCommunityDB::AppendAndLocate(const LargeCommunity *src,
    1221             :         const LargeCommunity::LargeCommunityList &list) {
    1222             :     LargeCommunity *clone;
    1223           0 :     if (src) {
    1224           0 :         clone = new LargeCommunity(*src);
    1225             :     } else {
    1226           0 :         clone = new LargeCommunity(this);
    1227             :     }
    1228             : 
    1229           0 :     clone->Append(list);
    1230           0 :     return Locate(clone);
    1231             : }
    1232             : 
    1233           0 : LargeCommunityPtr LargeCommunityDB::AppendAndLocate(const LargeCommunity *src,
    1234             :         const LargeCommunity::LargeCommunityValue &value) {
    1235           0 :     LargeCommunity::LargeCommunityList list;
    1236           0 :     list.push_back(value);
    1237           0 :     return AppendAndLocate(src, list);
    1238           0 : }
    1239             : 
    1240       18971 : LargeCommunityPtr LargeCommunityDB::ReplaceTagListAndLocate(
    1241             :     const LargeCommunity *src,
    1242             :     const LargeCommunity::LargeCommunityList &tag_list) {
    1243             :     LargeCommunity *clone;
    1244       18971 :     if (src) {
    1245           0 :         clone = new LargeCommunity(*src);
    1246             :     } else {
    1247       18971 :         clone = new LargeCommunity(this);
    1248             :     }
    1249             : 
    1250       18971 :     clone->RemoveTag();
    1251       18971 :     clone->Append(tag_list);
    1252       18971 :     return Locate(clone);
    1253             : }
    1254             : 
    1255           0 : LargeCommunityPtr LargeCommunityDB::RemoveAndLocate(const LargeCommunity *src,
    1256             :         const LargeCommunity::LargeCommunityList &list) {
    1257             :     LargeCommunity *clone;
    1258           0 :     if (src) {
    1259           0 :         clone = new LargeCommunity(*src);
    1260             :     } else {
    1261           0 :         clone = new LargeCommunity(this);
    1262             :     }
    1263             : 
    1264           0 :     clone->Remove(list);
    1265           0 :     return Locate(clone);
    1266             : }
    1267             : 
    1268             : 
    1269           0 : LargeCommunityPtr LargeCommunityDB::SetAndLocate(const LargeCommunity *src,
    1270             :         const LargeCommunity::LargeCommunityList &list) {
    1271             :     LargeCommunity *clone;
    1272           0 :     if (src) {
    1273           0 :         clone = new LargeCommunity(*src);
    1274             :     } else {
    1275           0 :         clone = new LargeCommunity(this);
    1276             :     }
    1277             : 
    1278           0 :     clone->Set(list);
    1279           0 :     return Locate(clone);
    1280             : }
    1281             : 

Generated by: LCOV version 1.14