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: 235 772 30.4 %
Date: 2026-09-09 08:39:22 Functions: 41 101 40.6 %
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          12 : void CommunitySpec::ToCanonical(BgpAttr *attr) {
      43          12 :     attr->set_community(this);
      44          12 : }
      45             : 
      46           0 : string CommunitySpec::ToString() const {
      47           0 :     string repr;
      48             :     char start[32];
      49           0 :     snprintf(start, sizeof(start), "Communities: %zu [", communities.size());
      50           0 :     repr += start;
      51             : 
      52           0 :     for (size_t i = 0; i < communities.size(); ++i) {
      53             :         char community[12];
      54           0 :         snprintf(community, sizeof(community), " %X", communities[i]);
      55           0 :         repr += community;
      56             :     }
      57           0 :     repr += " ]";
      58             : 
      59           0 :     return repr;
      60           0 : }
      61             : 
      62          12 : Community::Community(CommunityDB *comm_db, const CommunitySpec spec)
      63          12 :     : comm_db_(comm_db), communities_(spec.communities) {
      64          12 :     refcount_ = 0;
      65          12 :     sort(communities_.begin(), communities_.end());
      66             :     vector<uint32_t>::iterator it =
      67          12 :         unique(communities_.begin(), communities_.end());
      68          12 :     communities_.erase(it, communities_.end());
      69          12 : }
      70             : 
      71        7696 : int Community::CompareTo(const Community &rhs) const {
      72        7696 :     KEY_COMPARE(communities_, rhs.communities_);
      73        7604 :     return 0;
      74             : }
      75             : 
      76           0 : size_t CommunitySpec::EncodeLength() const {
      77           0 :     return communities.size() * sizeof(uint32_t);
      78             : }
      79             : 
      80        3790 : void Community::Append(uint32_t value) {
      81        3790 :     if (ContainsValue(value))
      82         224 :         return;
      83        3566 :     communities_.push_back(value);
      84        3566 :     sort(communities_.begin(), communities_.end());
      85             : }
      86             : 
      87           0 : void Community::Append(const std::vector<uint32_t> &communities) {
      88           0 :     for (auto community : communities) {
      89           0 :         communities_.push_back(community);
      90             :     }
      91           0 :     sort(communities_.begin(), communities_.end());
      92             :     vector<uint32_t>::iterator it =
      93           0 :         unique(communities_.begin(), communities_.end());
      94           0 :     communities_.erase(it, communities_.end());
      95           0 : }
      96             : 
      97           0 : void Community::Set(const std::vector<uint32_t> &communities) {
      98           0 :     communities_.clear();
      99           0 :     for (auto community : communities) {
     100           0 :         communities_.push_back(community);
     101             :     }
     102           0 : }
     103             : 
     104           0 : void Community::Remove(const std::vector<uint32_t> &communities) {
     105           0 :     for (auto community : communities) {
     106           0 :         communities_.erase(
     107           0 :                std::remove(communities_.begin(), communities_.end(), community),
     108           0 :                communities_.end());
     109             :     }
     110           0 : }
     111         298 : void Community::Remove() {
     112         298 :     comm_db_->Delete(this);
     113         298 : }
     114             : 
     115       13565 : bool Community::ContainsValue(uint32_t value) const {
     116       23436 :     for (auto community : communities_) {
     117       10103 :         if (community == value)
     118         232 :             return true;
     119             :     }
     120       13334 :     return false;
     121             : }
     122             : 
     123          48 : void Community::BuildStringList(vector<string> *list) const {
     124          96 :     for (auto community : communities_) {
     125          48 :         string name = CommunityType::CommunityToString(community);
     126          48 :         list->push_back(name);
     127          48 :     }
     128          48 : }
     129             : 
     130         698 : CommunityDB::CommunityDB(BgpServer *server) {
     131         698 : }
     132             : 
     133        3790 : CommunityPtr CommunityDB::AppendAndLocate(const Community *src,
     134             :     uint32_t value) {
     135             :     Community *clone;
     136        3790 :     if (src) {
     137         232 :         clone = new Community(*src);
     138             :     } else {
     139        3558 :         clone = new Community(this);
     140             :     }
     141             : 
     142        3790 :     clone->Append(value);
     143        3790 :     return Locate(clone);
     144             : }
     145             : 
     146           0 : CommunityPtr CommunityDB::AppendAndLocate(const Community *src,
     147             :     const std::vector<uint32_t> &value) {
     148             :     Community *clone;
     149           0 :     if (src) {
     150           0 :         clone = new Community(*src);
     151             :     } else {
     152           0 :         clone = new Community(this);
     153             :     }
     154             : 
     155           0 :     clone->Append(value);
     156           0 :     return Locate(clone);
     157             : }
     158             : 
     159           0 : CommunityPtr CommunityDB::SetAndLocate(const Community *src,
     160             :     const std::vector<uint32_t> &value) {
     161             :     Community *clone;
     162           0 :     if (src) {
     163           0 :         clone = new Community(*src);
     164             :     } else {
     165           0 :         clone = new Community(this);
     166             :     }
     167             : 
     168           0 :     clone->Set(value);
     169           0 :     return Locate(clone);
     170             : }
     171             : 
     172           0 : CommunityPtr CommunityDB::RemoveAndLocate(const Community *src,
     173             :     const std::vector<uint32_t> &value) {
     174             :     Community *clone;
     175           0 :     if (src) {
     176           0 :         clone = new Community(*src);
     177             :     } else {
     178           0 :         clone = new Community(this);
     179             :     }
     180             : 
     181           0 :     clone->Remove(value);
     182           0 :     return Locate(clone);
     183             : }
     184             : 
     185           0 : CommunityPtr CommunityDB::RemoveAndLocate(const Community *src,
     186             :                                           uint32_t value) {
     187           0 :     Community::CommunityList communities;
     188           0 :     communities.push_back(value);
     189           0 :     return RemoveAndLocate(src, communities);
     190           0 : }
     191             : 
     192           0 : string ExtCommunitySpec::ToString() const {
     193             :     char repr[80];
     194           0 :     snprintf(repr, sizeof(repr), "ExtCommunity <code: %d, flags: %02x>:%d",
     195           0 :              code, flags, (uint32_t)communities.size());
     196           0 :     return string(repr);
     197             : }
     198             : 
     199        4064 : LargeCommunitySpec LargeCommunitySpec::FromTag(
     200             :     const ExtCommunitySpec &ex_spec) {
     201        4064 :     LargeCommunitySpec large_spec;
     202             :     using extcomm_iterator = decltype(large_spec.communities)::iterator;
     203        4064 :     std::map<uint16_t, extcomm_iterator> tno_vs_tspec;
     204        4064 :     std::vector<std::pair<uint32_t,uint16_t> > asn4_vs_tno;
     205        4064 :     const uint64_t ExtCommTag = uint64_t(
     206             :         (BgpExtendedCommunityType::Experimental << 8) |
     207             :         (BgpExtendedCommunityExperimentalSubType::Tag)) << 48;
     208        4064 :     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        5256 :     for (const auto &val64 : ex_spec.communities) {
     215        1192 :         if ((0xFFFF000000000000 & val64) == ExtCommTag) {
     216           0 :             asn_or_tno = (0x0000FFFF00000000 & val64) >> 32;
     217             :             std::vector<uint32_t> large_comm = {
     218           0 :                 asn_or_tno,
     219           0 :                 0x01000000 | uint32_t((val64 & 0x00000000FFFF0000) >> 16),
     220           0 :                 uint32_t(val64 & 0x000000000000FFFF)
     221           0 :             };
     222           0 :             extcomm_iterator it_tspec =  large_spec.communities.insert(
     223           0 :                 large_spec.communities.end(),
     224             :                 large_comm.begin(),
     225             :                 large_comm.end());
     226           0 :             tno_vs_tspec.insert({asn_or_tno,
     227             :                                 it_tspec});
     228           0 :             continue;
     229           0 :         }
     230             : 
     231        1192 :         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        4064 :     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        8128 :     return large_spec;
     246        4064 : }
     247             : 
     248           0 : ExtCommunitySpec LargeCommunitySpec::RemoveTags(
     249             :     const ExtCommunitySpec& ex_spec) {
     250           0 :     const uint64_t ExtCommTag = uint64_t(
     251             :         (BgpExtendedCommunityType::Experimental << 8) |
     252             :         (BgpExtendedCommunityExperimentalSubType::Tag)) << 48;
     253           0 :     const uint64_t ExtCommTag4 = uint64_t(
     254             :         (BgpExtendedCommunityType::Experimental4ByteAs << 8) |
     255             :         (BgpExtendedCommunityExperimentalSubType::Tag)) << 48;
     256           0 :     ExtCommunitySpec new_ex_spec;
     257           0 :     for (const auto &val64 : ex_spec.communities) {
     258           0 :         if ((0xFFFF000000000000 & val64) != ExtCommTag &&
     259           0 :             (0xFFFF000000000000 & val64) != ExtCommTag4) {
     260           0 :             new_ex_spec.communities.push_back(val64);
     261             :         }
     262             :     }
     263           0 :     return new_ex_spec;
     264           0 : }
     265             : 
     266          30 : size_t ExtCommunitySpec::EncodeLength() const {
     267          30 :     return communities.size() * sizeof(uint64_t);
     268             : }
     269             : 
     270           0 : int ExtCommunitySpec::CompareTo(const BgpAttribute &rhs_attr) const {
     271           0 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     272           0 :     if (ret != 0) return ret;
     273           0 :     KEY_COMPARE(communities,
     274             :         static_cast<const ExtCommunitySpec &>(rhs_attr).communities);
     275           0 :     return 0;
     276             : }
     277             : 
     278        4064 : void ExtCommunitySpec::ToCanonical(BgpAttr *attr) {
     279        4064 :     attr->set_ext_community(this);
     280        4064 : }
     281             : 
     282           0 : void ExtCommunitySpec::AddTunnelEncaps(vector<string> encaps) {
     283           0 :     for (vector<string>::size_type i = 0; i < encaps.size(); i++) {
     284           0 :         string encap_str = encaps[i];
     285           0 :         TunnelEncap tun_encap(encap_str);
     286           0 :         communities.push_back(tun_encap.GetExtCommunityValue());
     287           0 :     }
     288           0 : }
     289             : 
     290      205699 : int ExtCommunity::CompareTo(const ExtCommunity &rhs) const {
     291      205699 :     KEY_COMPARE(communities_.size(), rhs.communities_.size());
     292             : 
     293      121717 :     ExtCommunityList::const_iterator i, j;
     294      121717 :     for (i = communities_.begin(), j = rhs.communities_.begin();
     295      225515 :          i < communities_.end(); ++i, ++j) {
     296      153281 :         if (*i < *j) {
     297       33128 :             return -1;
     298             :         }
     299      120153 :         if (*i > *j) {
     300       16355 :             return 1;
     301             :         }
     302             :     }
     303       72234 :     return 0;
     304             : }
     305             : 
     306           0 : void ExtCommunity::Remove(const ExtCommunityList &list) {
     307           0 :     for (ExtCommunityList::const_iterator it = list.begin();
     308           0 :          it != list.end(); ++it) {
     309           0 :         communities_.erase(std::remove(communities_.begin(),
     310           0 :                     communities_.end(), *it), communities_.end());
     311             :     }
     312           0 : }
     313        9584 : void ExtCommunity::Remove() {
     314        9584 :     extcomm_db_->Delete(this);
     315        9584 : }
     316             : 
     317           0 : void ExtCommunity::Set(const ExtCommunityList &list) {
     318           0 :     communities_.clear();
     319           0 :     for (ExtCommunityList::const_iterator it = list.begin();
     320           0 :          it != list.end(); ++it) {
     321           0 :         communities_.push_back(*it);
     322             :     }
     323           0 : }
     324             : 
     325       19573 : void ExtCommunity::Append(const ExtCommunityList &list) {
     326       19573 :     communities_.insert(communities_.end(), list.begin(), list.end());
     327       19462 :     sort(communities_.begin(), communities_.end());
     328             :     ExtCommunityList::iterator it =
     329       19478 :         unique(communities_.begin(), communities_.end());
     330       19479 :     communities_.erase(it, communities_.end());
     331       19463 : }
     332             : 
     333        7645 : void ExtCommunity::Append(const ExtCommunityValue &value) {
     334        7645 :     communities_.push_back(value);
     335        7633 :     sort(communities_.begin(), communities_.end());
     336             :     ExtCommunityList::iterator it =
     337        7630 :         unique(communities_.begin(), communities_.end());
     338        7627 :     communities_.erase(it, communities_.end());
     339        7620 : }
     340             : 
     341           0 : ExtCommunity::ExtCommunityValue ExtCommunity::FromHexString(
     342             :         const string &comm, boost::system::error_code *errorp) {
     343             :     ExtCommunityValue data;
     344           0 :     put_value(&data[0], 8, 0);
     345             :     char *end;
     346           0 :     uint64_t value = strtoull(comm.c_str(), &end, 16);
     347           0 :     if (value == 0 || *end) {
     348             :         // e.g. 0 or 12x34ff (invalid hex)
     349           0 :         if (errorp != NULL) {
     350           0 :             *errorp = make_error_code(
     351             :                     boost::system::errc::invalid_argument);
     352           0 :             return data;
     353             :         }
     354             :     }
     355           0 :     if (comm[0] == '0' && (comm[1] == 'x' || comm[1] == 'X')) {
     356           0 :         if (comm.length() > 18 && errorp != NULL) {
     357             :             // e.g. 0xabcdef0123456789f is an invalid 8byte hex value
     358           0 :             *errorp = make_error_code(
     359             :                     boost::system::errc::invalid_argument);
     360           0 :             return data;
     361             :         }
     362             :     } else {
     363           0 :         if (comm.length() > 16 && errorp != NULL) {
     364             :             // e.g. abcdef0123456789f is an invalid 8byte hex value
     365           0 :             *errorp = make_error_code(
     366             :                     boost::system::errc::invalid_argument);
     367           0 :             return data;
     368             :         }
     369             :     }
     370           0 :     put_value(&data[0], 8, value);
     371           0 :     return data;
     372             : }
     373             : 
     374           0 : ExtCommunity::ExtCommunityList ExtCommunity::ExtCommunityFromString(
     375             :         const string &comm) {
     376           0 :     ExtCommunityList commList;
     377             :     ExtCommunityValue value;
     378           0 :     size_t pos = comm.find(':');
     379           0 :     string first(comm.substr(0, pos));
     380           0 :     boost::system::error_code error;
     381           0 :     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           0 :     } else if (first == "target") {
     388           0 :         RouteTarget rt = RouteTarget::FromString(comm, &error);
     389           0 :         if (error) {
     390           0 :             return commList;
     391             :         }
     392           0 :         commList.push_back(rt.GetExtCommunity());
     393           0 :     } 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           0 :     } 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           0 :     } else if (first == "subcluster") {
     406           0 :         SubCluster sc = SubCluster::FromString(comm, &error);
     407           0 :         if (error) {
     408           0 :             return commList;
     409             :         }
     410           0 :         commList.push_back(sc.GetExtCommunity());
     411             :     } else {
     412           0 :         value = FromHexString(comm, &error);
     413           0 :         if (error) {
     414           0 :             return commList;
     415             :         }
     416           0 :         commList.push_back(value);
     417             :     }
     418           0 :     return commList;
     419           0 : }
     420             : 
     421           0 : string ExtCommunity::ToHexString(const ExtCommunityValue &comm) {
     422             :     char temp[50];
     423           0 :     int len = 0;
     424           0 :     for (size_t i = 0; i < comm.size(); i++) {
     425           0 :         len += snprintf(temp+len, sizeof(temp) - len, "%02x", (comm)[i]);
     426             :     }
     427           0 :     return(string(temp));
     428             : }
     429             : 
     430           0 : string ExtCommunity::ToString(const ExtCommunityValue &comm) {
     431           0 :     if (is_route_target(comm)) {
     432           0 :         RouteTarget rt(comm);
     433           0 :         return(rt.ToString());
     434           0 :     } else if (is_default_gateway(comm)) {
     435           0 :         DefaultGateway dgw(comm);
     436           0 :         return(dgw.ToString());
     437           0 :     } else if (is_es_import(comm)) {
     438           0 :         EsImport es_import(comm);
     439           0 :         return(es_import.ToString());
     440           0 :     } else if (is_esi_label(comm)) {
     441           0 :         EsiLabel esi_label(comm);
     442           0 :         return(esi_label.ToString());
     443           0 :     } else if (is_mac_mobility(comm)) {
     444           0 :         MacMobility mm(comm);
     445           0 :         return(mm.ToString());
     446           0 :     } else if (is_local_sequence_number(comm)) {
     447           0 :         LocalSequenceNumber lsn(comm);
     448           0 :         return lsn.ToString();
     449           0 :     } else if (is_etree(comm)) {
     450           0 :         ETree etree(comm);
     451           0 :         return(etree.ToString());
     452           0 :     } else if (is_router_mac(comm)) {
     453           0 :         RouterMac router_mac(comm);
     454           0 :         return(router_mac.ToString());
     455           0 :     } else if (is_origin_vn(comm)) {
     456           0 :         OriginVn origin_vn(comm);
     457           0 :         return(origin_vn.ToString());
     458           0 :     } else if (is_security_group(comm)) {
     459           0 :         SecurityGroup sg(comm);
     460           0 :         return(sg.ToString());
     461           0 :     } else if (is_site_of_origin(comm)) {
     462           0 :         SiteOfOrigin soo(comm);
     463           0 :         return(soo.ToString());
     464           0 :     } else if (is_tunnel_encap(comm)) {
     465           0 :         TunnelEncap encap(comm);
     466           0 :         return(encap.ToString());
     467           0 :     } else if (is_load_balance(comm)) {
     468           0 :         LoadBalance load_balance(comm);
     469           0 :         return(load_balance.ToString());
     470           0 :     } else if (is_tag(comm)) {
     471           0 :         Tag tag(comm);
     472           0 :         return(tag.ToString());
     473           0 :     } else if (is_source_as(comm)) {
     474           0 :         SourceAs sas(comm);
     475           0 :         return(sas.ToString());
     476           0 :     } else if (is_vrf_route_import(comm)) {
     477           0 :         VrfRouteImport rt_import(comm);
     478           0 :         return(rt_import.ToString());
     479           0 :     } else if (is_sub_cluster(comm)) {
     480           0 :         SubCluster sc(comm);
     481           0 :         return(sc.ToString());
     482             :     }
     483           0 :     return ToHexString(comm);
     484             : }
     485             : 
     486           0 : bool ExtCommunity::ContainsRTarget(const ExtCommunityValue &val) const {
     487           0 :     for (ExtCommunityList::const_iterator it = communities_.begin();
     488           0 :          it != communities_.end(); ++it) {
     489           0 :         if (ExtCommunity::is_route_target(*it) && *it == val)
     490           0 :             return true;
     491             :     }
     492           0 :     return false;
     493             : }
     494             : 
     495           0 : bool ExtCommunity::ContainsOriginVn(const ExtCommunityValue &val) const {
     496           0 :     for (ExtCommunityList::const_iterator it = communities_.begin();
     497           0 :          it != communities_.end(); ++it) {
     498           0 :         if (ExtCommunity::is_origin_vn(*it) && *it == val)
     499           0 :             return true;
     500             :     }
     501           0 :     return false;
     502             : }
     503             : 
     504           0 : bool ExtCommunity::ContainsOriginVn(as_t asn, uint32_t vn_index) const {
     505             :     if (asn <= 0xffffffff) {
     506           0 :         OriginVn origin_vn(asn, vn_index);
     507           0 :         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           0 : bool ExtCommunity::ContainsSourceAs(const ExtCommunityValue &val) const {
     516           0 :     for (ExtCommunityList::const_iterator it = communities_.begin();
     517           0 :          it != communities_.end(); ++it) {
     518           0 :         if (ExtCommunity::is_source_as(*it) && *it == val)
     519           0 :             return true;
     520             :     }
     521           0 :     return false;
     522             : }
     523             : 
     524        4415 : uint32_t ExtCommunity::GetSubClusterId() const {
     525        4415 :     for (ExtCommunityList::const_iterator it = communities_.begin();
     526       13705 :             it != communities_.end(); ++it) {
     527        9291 :         if (ExtCommunity::is_sub_cluster(*it)) {
     528           0 :             SubCluster sc(*it);
     529           0 :             return sc.GetId();
     530             :         }
     531             :     }
     532        4406 :     return 0;
     533             : }
     534             : 
     535           0 : bool ExtCommunity::ContainsVrfRouteImport(const ExtCommunityValue &val) const {
     536           0 :     for (ExtCommunityList::const_iterator it = communities_.begin();
     537           0 :          it != communities_.end(); ++it) {
     538           0 :         if (ExtCommunity::is_vrf_route_import(*it) && *it == val)
     539           0 :             return true;
     540             :     }
     541           0 :     return false;
     542             : }
     543             : 
     544           0 : void ExtCommunity::RemoveMFlags() {
     545           0 :     for (ExtCommunityList::iterator it = communities_.begin();
     546           0 :          it != communities_.end(); ) {
     547           0 :         if (ExtCommunity::is_multicast_flags(*it)) {
     548           0 :             it = communities_.erase(it);
     549             :         } else {
     550           0 :             ++it;
     551             :         }
     552             :     }
     553           0 : }
     554             : 
     555        4038 : void ExtCommunity::RemoveRTarget() {
     556        4038 :     for (ExtCommunityList::iterator it = communities_.begin();
     557       12626 :          it != communities_.end(); ) {
     558        8588 :         if (ExtCommunity::is_route_target(*it)) {
     559        4038 :             it = communities_.erase(it);
     560             :         } else {
     561        4550 :             ++it;
     562             :         }
     563             :     }
     564        4038 : }
     565             : 
     566        4038 : void ExtCommunity::RemoveSGID() {
     567        4038 :     for (ExtCommunityList::iterator it = communities_.begin();
     568        8588 :          it != communities_.end(); ) {
     569        8716 :         if (ExtCommunity::is_security_group(*it) ||
     570        4166 :                 ExtCommunity::is_security_group4(*it)) {
     571         384 :             it = communities_.erase(it);
     572             :         } else {
     573        4166 :             ++it;
     574             :         }
     575             :     }
     576        4038 : }
     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        4038 : void ExtCommunity::RemoveSiteOfOrigin() {
     590        4038 :     for (ExtCommunityList::iterator it = communities_.begin();
     591        8588 :          it != communities_.end(); ) {
     592        4550 :         if (ExtCommunity::is_site_of_origin(*it)) {
     593           0 :             it = communities_.erase(it);
     594             :         } else {
     595        4550 :             ++it;
     596             :         }
     597             :     }
     598        4038 : }
     599             : 
     600           0 : void ExtCommunity::RemoveSourceAS() {
     601           0 :     for (ExtCommunityList::iterator it = communities_.begin();
     602           0 :          it != communities_.end(); ) {
     603           0 :         if (ExtCommunity::is_source_as(*it)) {
     604           0 :             it = communities_.erase(it);
     605             :         } else {
     606           0 :             ++it;
     607             :         }
     608             :     }
     609           0 : }
     610           0 : void ExtCommunity::RemoveVrfRouteImport() {
     611           0 :     for (ExtCommunityList::iterator it = communities_.begin();
     612           0 :          it != communities_.end(); ) {
     613           0 :         if (ExtCommunity::is_vrf_route_import(*it)) {
     614           0 :             it = communities_.erase(it);
     615             :         } else {
     616           0 :             ++it;
     617             :         }
     618             :     }
     619           0 : }
     620             : 
     621        7648 : void ExtCommunity::RemoveOriginVn() {
     622        7648 :     for (ExtCommunityList::iterator it = communities_.begin();
     623       16026 :          it != communities_.end(); ) {
     624        8384 :         if (ExtCommunity::is_origin_vn(*it))
     625        4038 :             it = communities_.erase(it);
     626             :         else
     627        4345 :             ++it;
     628             :     }
     629        7638 : }
     630             : 
     631        2019 : void ExtCommunity::RemoveTunnelEncapsulation() {
     632        2019 :     for (ExtCommunityList::iterator it = communities_.begin();
     633        4310 :          it != communities_.end(); ) {
     634        2291 :         if (ExtCommunity::is_tunnel_encap(*it)) {
     635          40 :             it = communities_.erase(it);
     636             :         } else {
     637        2251 :             ++it;
     638             :         }
     639             :     }
     640        2019 : }
     641             : 
     642           0 : void ExtCommunity::RemoveLoadBalance() {
     643           0 :     for (ExtCommunityList::iterator it = communities_.begin();
     644           0 :          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           0 : }
     652             : 
     653           0 : void ExtCommunity::RemoveSubCluster() {
     654           0 :     for (ExtCommunityList::iterator it = communities_.begin();
     655           0 :          it != communities_.end(); ) {
     656           0 :         if (ExtCommunity::is_sub_cluster(*it)) {
     657           0 :             it = communities_.erase(it);
     658             :         } else {
     659           0 :             ++it;
     660             :         }
     661             :     }
     662           0 : }
     663             : 
     664           0 : vector<string> ExtCommunity::GetTunnelEncap() const {
     665           0 :     vector<string> encap_list;
     666           0 :     for (ExtCommunityList::const_iterator iter = communities_.begin();
     667           0 :          iter != communities_.end(); ++iter) {
     668           0 :         if (!ExtCommunity::is_tunnel_encap(*iter))
     669           0 :             continue;
     670           0 :         TunnelEncap encap(*iter);
     671           0 :         if (encap.tunnel_encap() == TunnelEncapType::UNSPEC)
     672           0 :             continue;
     673           0 :         encap_list.push_back(encap.ToXmppString());
     674             :     }
     675             : 
     676           0 :     sort(encap_list.begin(), encap_list.end());
     677             :     vector<string>::iterator encap_iter =
     678           0 :         unique(encap_list.begin(), encap_list.end());
     679           0 :     encap_list.erase(encap_iter, encap_list.end());
     680           0 :     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           0 : bool ExtCommunity::ContainsTunnelEncapVxlan() const {
     725           0 :     for (ExtCommunityList::const_iterator iter = communities_.begin();
     726           0 :          iter != communities_.end(); ++iter) {
     727           0 :         if (!ExtCommunity::is_tunnel_encap(*iter))
     728           0 :             continue;
     729           0 :         TunnelEncap encap(*iter);
     730           0 :         if (encap.tunnel_encap() == TunnelEncapType::VXLAN)
     731           0 :             return true;
     732             :     }
     733           0 :     return false;
     734             : }
     735             : 
     736           0 : int ExtCommunity::GetOriginVnIndex() const {
     737           0 :     for (ExtCommunityList::const_iterator iter = communities_.begin();
     738           0 :          iter != communities_.end(); ++iter) {
     739           0 :         if (ExtCommunity::is_origin_vn(*iter)) {
     740           0 :             OriginVn origin_vn(*iter);
     741           0 :             return origin_vn.vn_index();
     742             :         }
     743             :     }
     744           0 :     return -1;
     745             : }
     746             : 
     747        4064 : ExtCommunity::ExtCommunity(ExtCommunityDB *extcomm_db,
     748        4064 :         const ExtCommunitySpec spec) : extcomm_db_(extcomm_db) {
     749        4064 :     refcount_ = 0;
     750        4064 :     for (vector<uint64_t>::const_iterator it = spec.communities.begin();
     751        5256 :          it < spec.communities.end(); ++it) {
     752             :         ExtCommunityValue comm;
     753        1192 :         put_value(comm.data(), comm.size(), *it);
     754        1192 :         communities_.push_back(comm);
     755             :     }
     756        4064 :     sort(communities_.begin(), communities_.end());
     757             :     ExtCommunityList::iterator it =
     758        4064 :         unique(communities_.begin(), communities_.end());
     759        4064 :     communities_.erase(it, communities_.end());
     760        4064 : }
     761             : 
     762         698 : ExtCommunityDB::ExtCommunityDB(BgpServer *server) {
     763         698 : }
     764             : 
     765        9340 : ExtCommunityPtr ExtCommunityDB::AppendAndLocate(const ExtCommunity *src,
     766             :         const ExtCommunity::ExtCommunityList &list) {
     767             :     ExtCommunity *clone;
     768        9340 :     if (src) {
     769        9340 :         clone = new ExtCommunity(*src);
     770             :     } else {
     771           0 :         clone = new ExtCommunity(this);
     772             :     }
     773             : 
     774        9483 :     clone->Append(list);
     775        9368 :     return Locate(clone);
     776             : }
     777             : 
     778          16 : ExtCommunityPtr ExtCommunityDB::AppendAndLocate(const ExtCommunity *src,
     779             :         const ExtCommunity::ExtCommunityValue &value) {
     780          16 :     ExtCommunity::ExtCommunityList list;
     781          16 :     list.push_back(value);
     782          32 :     return AppendAndLocate(src, list);
     783          16 : }
     784             : 
     785           0 : ExtCommunityPtr ExtCommunityDB::RemoveAndLocate(const ExtCommunity *src,
     786             :         const ExtCommunity::ExtCommunityList &list) {
     787             :     ExtCommunity *clone;
     788           0 :     if (src) {
     789           0 :         clone = new ExtCommunity(*src);
     790             :     } else {
     791           0 :         clone = new ExtCommunity(this);
     792             :     }
     793             : 
     794           0 :     clone->Remove(list);
     795           0 :     return Locate(clone);
     796             : }
     797             : 
     798           0 : ExtCommunityPtr ExtCommunityDB::ReplaceMFlagsAndLocate(const ExtCommunity *src,
     799             :         const ExtCommunity::ExtCommunityList &export_list) {
     800             :     ExtCommunity *clone;
     801           0 :     if (src) {
     802           0 :         clone = new ExtCommunity(*src);
     803             :     } else {
     804           0 :         clone = new ExtCommunity(this);
     805             :     }
     806             : 
     807           0 :     clone->RemoveMFlags();
     808           0 :     clone->Append(export_list);
     809           0 :     return Locate(clone);
     810             : }
     811             : 
     812        4038 : ExtCommunityPtr ExtCommunityDB::ReplaceRTargetAndLocate(const ExtCommunity *src,
     813             :         const ExtCommunity::ExtCommunityList &export_list) {
     814             :     ExtCommunity *clone;
     815        4038 :     if (src) {
     816        4038 :         clone = new ExtCommunity(*src);
     817             :     } else {
     818           0 :         clone = new ExtCommunity(this);
     819             :     }
     820             : 
     821        4038 :     clone->RemoveRTarget();
     822        4038 :     clone->Append(export_list);
     823        4038 :     return Locate(clone);
     824             : }
     825             : 
     826        4038 : ExtCommunityPtr ExtCommunityDB::ReplaceSGIDListAndLocate(
     827             :     const ExtCommunity *src,
     828             :     const ExtCommunity::ExtCommunityList &sgid_list) {
     829             :     ExtCommunity *clone;
     830        4038 :     if (src) {
     831        4038 :         clone = new ExtCommunity(*src);
     832             :     } else {
     833           0 :         clone = new ExtCommunity(this);
     834             :     }
     835             : 
     836        4038 :     clone->RemoveSGID();
     837        4038 :     clone->Append(sgid_list);
     838        4038 :     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        4022 : ExtCommunityPtr ExtCommunityDB::RemoveSiteOfOriginAndLocate(
     857             :         const ExtCommunity *src) {
     858             :     ExtCommunity *clone;
     859        4022 :     if (src) {
     860        4022 :         clone = new ExtCommunity(*src);
     861             :     } else {
     862           0 :         clone = new ExtCommunity(this);
     863             :     }
     864             : 
     865        4022 :     clone->RemoveSiteOfOrigin();
     866        4022 :     return Locate(clone);
     867             : }
     868             : 
     869          16 : ExtCommunityPtr ExtCommunityDB::ReplaceSiteOfOriginAndLocate(
     870             :         const ExtCommunity *src,
     871             :         const ExtCommunity::ExtCommunityValue &soo) {
     872             :     ExtCommunity *clone;
     873          16 :     if (src) {
     874          16 :         clone = new ExtCommunity(*src);
     875             :     } else {
     876           0 :         clone = new ExtCommunity(this);
     877             :     }
     878             : 
     879          16 :     clone->RemoveSiteOfOrigin();
     880          16 :     clone->Append(soo);
     881          16 :     return Locate(clone);
     882             : }
     883             : 
     884           0 : ExtCommunityPtr ExtCommunityDB::RemoveSourceASAndLocate(
     885             :         const ExtCommunity *src) {
     886             :     ExtCommunity *clone;
     887           0 :     if (src) {
     888           0 :         clone = new ExtCommunity(*src);
     889             :     } else {
     890           0 :         clone = new ExtCommunity(this);
     891             :     }
     892             : 
     893           0 :     clone->RemoveSourceAS();
     894           0 :     return Locate(clone);
     895             : }
     896             : 
     897           0 : ExtCommunityPtr ExtCommunityDB::ReplaceSourceASAndLocate(
     898             :         const ExtCommunity *src,
     899             :         const ExtCommunity::ExtCommunityValue &sas) {
     900             :     ExtCommunity *clone;
     901           0 :     if (src) {
     902           0 :         clone = new ExtCommunity(*src);
     903             :     } else {
     904           0 :         clone = new ExtCommunity(this);
     905             :     }
     906             : 
     907           0 :     clone->RemoveSourceAS();
     908           0 :     clone->Append(sas);
     909           0 :     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           0 : ExtCommunityPtr ExtCommunityDB::ReplaceVrfRouteImportAndLocate(
     926             :         const ExtCommunity *src,
     927             :         const ExtCommunity::ExtCommunityValue &vit) {
     928             :     ExtCommunity *clone;
     929           0 :     if (src) {
     930           0 :         clone = new ExtCommunity(*src);
     931             :     } else {
     932           0 :         clone = new ExtCommunity(this);
     933             :     }
     934             : 
     935           0 :     clone->RemoveVrfRouteImport();
     936           0 :     clone->Append(vit);
     937           0 :     return Locate(clone);
     938             : }
     939             : 
     940           8 : ExtCommunityPtr ExtCommunityDB::RemoveOriginVnAndLocate(
     941             :         const ExtCommunity *src) {
     942             :     ExtCommunity *clone;
     943           8 :     if (src) {
     944           8 :         clone = new ExtCommunity(*src);
     945             :     } else {
     946           0 :         clone = new ExtCommunity(this);
     947             :     }
     948             : 
     949           8 :     clone->RemoveOriginVn();
     950           8 :     return Locate(clone);
     951             : }
     952             : 
     953        7634 : ExtCommunityPtr ExtCommunityDB::ReplaceOriginVnAndLocate(
     954             :         const ExtCommunity *src,
     955             :         const ExtCommunity::ExtCommunityValue &origin_vn) {
     956             :     ExtCommunity *clone;
     957        7634 :     if (src) {
     958        7636 :         clone = new ExtCommunity(*src);
     959             :     } else {
     960           0 :         clone = new ExtCommunity(this);
     961             :     }
     962             : 
     963        7641 :     clone->RemoveOriginVn();
     964        7630 :     clone->Append(origin_vn);
     965        7604 :     return Locate(clone);
     966             : }
     967             : 
     968        2019 : ExtCommunityPtr ExtCommunityDB::ReplaceTunnelEncapsulationAndLocate(
     969             :         const ExtCommunity *src,
     970             :         const ExtCommunity::ExtCommunityList &tunnel_encaps) {
     971             :     ExtCommunity *clone;
     972        2019 :     if (src) {
     973        2019 :         clone = new ExtCommunity(*src);
     974             :     } else {
     975           0 :         clone = new ExtCommunity(this);
     976             :     }
     977             : 
     978        2019 :     clone->RemoveTunnelEncapsulation();
     979        2019 :     clone->Append(tunnel_encaps);
     980        2019 :     return Locate(clone);
     981             : }
     982             : 
     983           0 : ExtCommunityPtr ExtCommunityDB::ReplaceLoadBalanceAndLocate(
     984             :         const ExtCommunity *src,
     985             :         const ExtCommunity::ExtCommunityValue &lb) {
     986             :     ExtCommunity *clone;
     987           0 :     if (src) {
     988           0 :         clone = new ExtCommunity(*src);
     989             :     } else {
     990           0 :         clone = new ExtCommunity(this);
     991             :     }
     992             : 
     993           0 :     clone->RemoveLoadBalance();
     994           0 :     clone->Append(lb);
     995           0 :     return Locate(clone);
     996             : }
     997             : 
     998           0 : ExtCommunityPtr ExtCommunityDB::ReplaceSubClusterAndLocate(
     999             :         const ExtCommunity *src,
    1000             :         const ExtCommunity::ExtCommunityValue &sc) {
    1001             :     ExtCommunity *clone;
    1002           0 :     if (src) {
    1003           0 :         clone = new ExtCommunity(*src);
    1004             :     } else {
    1005           0 :         clone = new ExtCommunity(this);
    1006             :     }
    1007             : 
    1008           0 :     clone->RemoveSubCluster();
    1009           0 :     clone->Append(sc);
    1010           0 :     return Locate(clone);
    1011             : }
    1012             : 
    1013           0 : ExtCommunityPtr ExtCommunityDB::SetAndLocate(const ExtCommunity *src,
    1014             :         const ExtCommunity::ExtCommunityList &value) {
    1015             :     ExtCommunity *clone;
    1016           0 :     if (src) {
    1017           0 :         clone = new ExtCommunity(*src);
    1018             :     } else {
    1019           0 :         clone = new ExtCommunity(this);
    1020             :     }
    1021             : 
    1022           0 :     clone->Set(value);
    1023           0 :     return Locate(clone);
    1024             : }
    1025             : 
    1026           0 : string LargeCommunitySpec::ToString() const {
    1027             :     char repr[80];
    1028           0 :     snprintf(repr, sizeof(repr), "LargeCommunity <code: %d, flags: %02x>:%d",
    1029           0 :              code, flags, (uint32_t)communities.size() / 3);
    1030           0 :     return string(repr);
    1031             : }
    1032             : 
    1033           0 : size_t LargeCommunitySpec::EncodeLength() const {
    1034           0 :     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           8 : void LargeCommunitySpec::ToCanonical(BgpAttr *attr) {
    1046             :     // add LarceComm to attr
    1047           8 :     attr->set_large_community(this);
    1048           8 : }
    1049             : 
    1050       16280 : int LargeCommunity::CompareTo(const LargeCommunity &rhs) const {
    1051       16280 :     KEY_COMPARE(communities_.size(), rhs.communities_.size());
    1052             : 
    1053       16236 :     LargeCommunityList::const_iterator i, j;
    1054       16236 :     for (i = communities_.begin(), j = rhs.communities_.begin();
    1055       16300 :          i < communities_.end(); ++i, ++j) {
    1056          80 :         if (*i < *j) {
    1057           8 :             return -1;
    1058             :         }
    1059          72 :         if (*i > *j) {
    1060           8 :             return 1;
    1061             :         }
    1062             :     }
    1063       16220 :     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         246 : void LargeCommunity::Remove() {
    1074         246 :     largecomm_db_->Delete(this);
    1075         246 : }
    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        4038 : void LargeCommunity::Append(const LargeCommunityList &list) {
    1086        4038 :     communities_.insert(communities_.end(), list.begin(), list.end());
    1087        4038 :     sort(communities_.begin(), communities_.end());
    1088             :     LargeCommunityList::iterator it =
    1089        4038 :         unique(communities_.begin(), communities_.end());
    1090        4038 :     communities_.erase(it, communities_.end());
    1091        4038 : }
    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        4038 : void LargeCommunity::RemoveTag() {
    1167        4038 :     for (LargeCommunityList::iterator it = communities_.begin();
    1168        4038 :          it != communities_.end(); ) {
    1169           0 :         if (LargeCommunity::is_tag(*it)) {
    1170           0 :             it = communities_.erase(it);
    1171             :         } else {
    1172           0 :             ++it;
    1173             :         }
    1174             :     }
    1175        4038 : }
    1176             : 
    1177           0 : vector<uint64_t> LargeCommunity::GetTagList(as_t asn) const {
    1178           0 :     vector<uint64_t> tag_list;
    1179           0 :     for (const auto &lc : communities_) {
    1180           0 :         if (!LargeCommunity::is_tag(lc))
    1181           0 :             continue;
    1182           0 :         TagLC tag_comm(lc);
    1183           0 :         if (asn && tag_comm.as_number() != asn && !tag_comm.IsGlobal())
    1184           0 :             continue;
    1185           0 :         tag_list.push_back(tag_comm.tag());
    1186             :     }
    1187             : 
    1188           0 :     sort(tag_list.begin(), tag_list.end());
    1189           0 :     vector<uint64_t>::iterator tag_iter = unique(tag_list.begin(),
    1190             :                                                  tag_list.end());
    1191           0 :     tag_list.erase(tag_iter, tag_list.end());
    1192           0 :     return tag_list;
    1193           0 : }
    1194             : 
    1195             : 
    1196        4072 : LargeCommunity::LargeCommunity(LargeCommunityDB *largecomm_db,
    1197        4072 :         const LargeCommunitySpec spec) : largecomm_db_(largecomm_db) {
    1198        4072 :     refcount_ = 0;
    1199        4072 :     std::vector<uint32_t>::const_iterator lcit = spec.communities.begin();
    1200        4088 :     while (lcit < spec.communities.end()) {
    1201             :         LargeCommunityValue comm;
    1202          16 :         put_value(comm.data(), 4, *lcit);
    1203          16 :         lcit++;
    1204          16 :         put_value(comm.data()+4, 4, *lcit);
    1205          16 :         lcit++;
    1206          16 :         put_value(comm.data()+8, 4, *lcit);
    1207          16 :         lcit++;
    1208          16 :         communities_.push_back(comm);
    1209             :     }
    1210        4072 :     sort(communities_.begin(), communities_.end());
    1211             :     LargeCommunityList::iterator it =
    1212        4072 :         unique(communities_.begin(), communities_.end());
    1213        4072 :     communities_.erase(it, communities_.end());
    1214        4072 : }
    1215             : 
    1216         698 : LargeCommunityDB::LargeCommunityDB(BgpServer *server) {
    1217         698 : }
    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        4038 : LargeCommunityPtr LargeCommunityDB::ReplaceTagListAndLocate(
    1240             :     const LargeCommunity *src,
    1241             :     const LargeCommunity::LargeCommunityList &tag_list) {
    1242             :     LargeCommunity *clone;
    1243        4038 :     if (src) {
    1244           0 :         clone = new LargeCommunity(*src);
    1245             :     } else {
    1246        4038 :         clone = new LargeCommunity(this);
    1247             :     }
    1248             : 
    1249        4038 :     clone->RemoveTag();
    1250        4038 :     clone->Append(tag_list);
    1251        4038 :     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