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

Generated by: LCOV version 1.14