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: 172 772 22.3 %
Date: 2026-05-20 15:35:45 Functions: 32 101 31.7 %
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         192 : void CommunitySpec::ToCanonical(BgpAttr *attr) {
      43         192 :     attr->set_community(this);
      44         192 : }
      45             : 
      46         192 : string CommunitySpec::ToString() const {
      47         192 :     string repr;
      48             :     char start[32];
      49         192 :     snprintf(start, sizeof(start), "Communities: %zu [", communities.size());
      50         192 :     repr += start;
      51             : 
      52         384 :     for (size_t i = 0; i < communities.size(); ++i) {
      53             :         char community[12];
      54         192 :         snprintf(community, sizeof(community), " %X", communities[i]);
      55         192 :         repr += community;
      56             :     }
      57         192 :     repr += " ]";
      58             : 
      59         384 :     return repr;
      60           0 : }
      61             : 
      62         192 : Community::Community(CommunityDB *comm_db, const CommunitySpec spec)
      63         192 :     : comm_db_(comm_db), communities_(spec.communities) {
      64         192 :     refcount_ = 0;
      65         192 :     sort(communities_.begin(), communities_.end());
      66             :     vector<uint32_t>::iterator it =
      67         192 :         unique(communities_.begin(), communities_.end());
      68         192 :     communities_.erase(it, communities_.end());
      69         192 : }
      70             : 
      71        1152 : int Community::CompareTo(const Community &rhs) const {
      72        1152 :     KEY_COMPARE(communities_, rhs.communities_);
      73        1152 :     return 0;
      74             : }
      75             : 
      76         576 : size_t CommunitySpec::EncodeLength() const {
      77         576 :     return communities.size() * sizeof(uint32_t);
      78             : }
      79             : 
      80         384 : void Community::Append(uint32_t value) {
      81         384 :     if (ContainsValue(value))
      82           0 :         return;
      83         384 :     communities_.push_back(value);
      84         384 :     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          84 : void Community::Remove() {
     112          84 :     comm_db_->Delete(this);
     113          84 : }
     114             : 
     115         576 : bool Community::ContainsValue(uint32_t value) const {
     116         576 :     for (auto community : communities_) {
     117         192 :         if (community == value)
     118         192 :             return true;
     119             :     }
     120         384 :     return false;
     121             : }
     122             : 
     123           0 : void Community::BuildStringList(vector<string> *list) const {
     124           0 :     for (auto community : communities_) {
     125           0 :         string name = CommunityType::CommunityToString(community);
     126           0 :         list->push_back(name);
     127           0 :     }
     128           0 : }
     129             : 
     130          68 : CommunityDB::CommunityDB(BgpServer *server) {
     131          68 : }
     132             : 
     133         384 : CommunityPtr CommunityDB::AppendAndLocate(const Community *src,
     134             :     uint32_t value) {
     135             :     Community *clone;
     136         384 :     if (src) {
     137           0 :         clone = new Community(*src);
     138             :     } else {
     139         384 :         clone = new Community(this);
     140             :     }
     141             : 
     142         384 :     clone->Append(value);
     143         384 :     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         160 : LargeCommunitySpec LargeCommunitySpec::FromTag(
     200             :     const ExtCommunitySpec &ex_spec) {
     201         160 :     LargeCommunitySpec large_spec;
     202             :     using extcomm_iterator = decltype(large_spec.communities)::iterator;
     203         160 :     std::map<uint16_t, extcomm_iterator> tno_vs_tspec;
     204         160 :     std::vector<std::pair<uint32_t,uint16_t> > asn4_vs_tno;
     205         160 :     const uint64_t ExtCommTag = uint64_t(
     206             :         (BgpExtendedCommunityType::Experimental << 8) |
     207             :         (BgpExtendedCommunityExperimentalSubType::Tag)) << 48;
     208         160 :     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         480 :     for (const auto &val64 : ex_spec.communities) {
     215         320 :         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         320 :         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         160 :     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         320 :     return large_spec;
     246         160 : }
     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        2388 : size_t ExtCommunitySpec::EncodeLength() const {
     267        2388 :     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         160 : void ExtCommunitySpec::ToCanonical(BgpAttr *attr) {
     279         160 :     attr->set_ext_community(this);
     280         160 : }
     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       42819 : int ExtCommunity::CompareTo(const ExtCommunity &rhs) const {
     291       42819 :     KEY_COMPARE(communities_.size(), rhs.communities_.size());
     292             : 
     293       16848 :     ExtCommunityList::const_iterator i, j;
     294       16848 :     for (i = communities_.begin(), j = rhs.communities_.begin();
     295       38516 :          i < communities_.end(); ++i, ++j) {
     296       21668 :         if (*i < *j) {
     297           0 :             return -1;
     298             :         }
     299       21668 :         if (*i > *j) {
     300           0 :             return 1;
     301             :         }
     302             :     }
     303       16848 :     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        3783 : void ExtCommunity::Remove() {
     314        3783 :     extcomm_db_->Delete(this);
     315        3783 : }
     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        7054 : void ExtCommunity::Append(const ExtCommunityList &list) {
     326        7054 :     communities_.insert(communities_.end(), list.begin(), list.end());
     327        7049 :     sort(communities_.begin(), communities_.end());
     328             :     ExtCommunityList::iterator it =
     329        7050 :         unique(communities_.begin(), communities_.end());
     330        7048 :     communities_.erase(it, communities_.end());
     331        7044 : }
     332             : 
     333           0 : void ExtCommunity::Append(const ExtCommunityValue &value) {
     334           0 :     communities_.push_back(value);
     335           0 :     sort(communities_.begin(), communities_.end());
     336             :     ExtCommunityList::iterator it =
     337           0 :         unique(communities_.begin(), communities_.end());
     338           0 :     communities_.erase(it, communities_.end());
     339           0 : }
     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           0 : uint32_t ExtCommunity::GetSubClusterId() const {
     525           0 :     for (ExtCommunityList::const_iterator it = communities_.begin();
     526           0 :             it != communities_.end(); ++it) {
     527           0 :         if (ExtCommunity::is_sub_cluster(*it)) {
     528           0 :             SubCluster sc(*it);
     529           0 :             return sc.GetId();
     530             :         }
     531             :     }
     532           0 :     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        1901 : void ExtCommunity::RemoveRTarget() {
     556        1901 :     for (ExtCommunityList::iterator it = communities_.begin();
     557        1901 :          it != communities_.end(); ) {
     558           0 :         if (ExtCommunity::is_route_target(*it)) {
     559           0 :             it = communities_.erase(it);
     560             :         } else {
     561           0 :             ++it;
     562             :         }
     563             :     }
     564        1901 : }
     565             : 
     566        1901 : void ExtCommunity::RemoveSGID() {
     567        1901 :     for (ExtCommunityList::iterator it = communities_.begin();
     568        1901 :          it != communities_.end(); ) {
     569           0 :         if (ExtCommunity::is_security_group(*it) ||
     570           0 :                 ExtCommunity::is_security_group4(*it)) {
     571           0 :             it = communities_.erase(it);
     572             :         } else {
     573           0 :             ++it;
     574             :         }
     575             :     }
     576        1901 : }
     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           0 : void ExtCommunity::RemoveSiteOfOrigin() {
     590           0 :     for (ExtCommunityList::iterator it = communities_.begin();
     591           0 :          it != communities_.end(); ) {
     592           0 :         if (ExtCommunity::is_site_of_origin(*it)) {
     593           0 :             it = communities_.erase(it);
     594             :         } else {
     595           0 :             ++it;
     596             :         }
     597             :     }
     598           0 : }
     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           0 : void ExtCommunity::RemoveOriginVn() {
     622           0 :     for (ExtCommunityList::iterator it = communities_.begin();
     623           0 :          it != communities_.end(); ) {
     624           0 :         if (ExtCommunity::is_origin_vn(*it))
     625           0 :             it = communities_.erase(it);
     626             :         else
     627           0 :             ++it;
     628             :     }
     629           0 : }
     630             : 
     631        1901 : void ExtCommunity::RemoveTunnelEncapsulation() {
     632        1901 :     for (ExtCommunityList::iterator it = communities_.begin();
     633        3802 :          it != communities_.end(); ) {
     634        1901 :         if (ExtCommunity::is_tunnel_encap(*it)) {
     635           0 :             it = communities_.erase(it);
     636             :         } else {
     637        1901 :             ++it;
     638             :         }
     639             :     }
     640        1901 : }
     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        1420 : vector<string> ExtCommunity::GetTunnelEncap() const {
     665        1420 :     vector<string> encap_list;
     666        1420 :     for (ExtCommunityList::const_iterator iter = communities_.begin();
     667        4260 :          iter != communities_.end(); ++iter) {
     668        2840 :         if (!ExtCommunity::is_tunnel_encap(*iter))
     669        1420 :             continue;
     670        1420 :         TunnelEncap encap(*iter);
     671        1420 :         if (encap.tunnel_encap() == TunnelEncapType::UNSPEC)
     672           0 :             continue;
     673        1419 :         encap_list.push_back(encap.ToXmppString());
     674             :     }
     675             : 
     676        1420 :     sort(encap_list.begin(), encap_list.end());
     677             :     vector<string>::iterator encap_iter =
     678        1419 :         unique(encap_list.begin(), encap_list.end());
     679        1419 :     encap_list.erase(encap_iter, encap_list.end());
     680        2836 :     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        1418 : int ExtCommunity::GetOriginVnIndex() const {
     737        1418 :     for (ExtCommunityList::const_iterator iter = communities_.begin();
     738        4255 :          iter != communities_.end(); ++iter) {
     739        2836 :         if (ExtCommunity::is_origin_vn(*iter)) {
     740           0 :             OriginVn origin_vn(*iter);
     741           0 :             return origin_vn.vn_index();
     742             :         }
     743             :     }
     744        1419 :     return -1;
     745             : }
     746             : 
     747         160 : ExtCommunity::ExtCommunity(ExtCommunityDB *extcomm_db,
     748         160 :         const ExtCommunitySpec spec) : extcomm_db_(extcomm_db) {
     749         160 :     refcount_ = 0;
     750         160 :     for (vector<uint64_t>::const_iterator it = spec.communities.begin();
     751         480 :          it < spec.communities.end(); ++it) {
     752             :         ExtCommunityValue comm;
     753         320 :         put_value(comm.data(), comm.size(), *it);
     754         320 :         communities_.push_back(comm);
     755             :     }
     756         160 :     sort(communities_.begin(), communities_.end());
     757             :     ExtCommunityList::iterator it =
     758         160 :         unique(communities_.begin(), communities_.end());
     759         160 :     communities_.erase(it, communities_.end());
     760         160 : }
     761             : 
     762          68 : ExtCommunityDB::ExtCommunityDB(BgpServer *server) {
     763          68 : }
     764             : 
     765        1351 : ExtCommunityPtr ExtCommunityDB::AppendAndLocate(const ExtCommunity *src,
     766             :         const ExtCommunity::ExtCommunityList &list) {
     767             :     ExtCommunity *clone;
     768        1351 :     if (src) {
     769        1351 :         clone = new ExtCommunity(*src);
     770             :     } else {
     771           0 :         clone = new ExtCommunity(this);
     772             :     }
     773             : 
     774        1354 :     clone->Append(list);
     775        1354 :     return Locate(clone);
     776             : }
     777             : 
     778           0 : ExtCommunityPtr ExtCommunityDB::AppendAndLocate(const ExtCommunity *src,
     779             :         const ExtCommunity::ExtCommunityValue &value) {
     780           0 :     ExtCommunity::ExtCommunityList list;
     781           0 :     list.push_back(value);
     782           0 :     return AppendAndLocate(src, list);
     783           0 : }
     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        1901 : ExtCommunityPtr ExtCommunityDB::ReplaceRTargetAndLocate(const ExtCommunity *src,
     813             :         const ExtCommunity::ExtCommunityList &export_list) {
     814             :     ExtCommunity *clone;
     815        1901 :     if (src) {
     816           0 :         clone = new ExtCommunity(*src);
     817             :     } else {
     818        1901 :         clone = new ExtCommunity(this);
     819             :     }
     820             : 
     821        1901 :     clone->RemoveRTarget();
     822        1901 :     clone->Append(export_list);
     823        1901 :     return Locate(clone);
     824             : }
     825             : 
     826        1901 : ExtCommunityPtr ExtCommunityDB::ReplaceSGIDListAndLocate(
     827             :     const ExtCommunity *src,
     828             :     const ExtCommunity::ExtCommunityList &sgid_list) {
     829             :     ExtCommunity *clone;
     830        1901 :     if (src) {
     831        1901 :         clone = new ExtCommunity(*src);
     832             :     } else {
     833           0 :         clone = new ExtCommunity(this);
     834             :     }
     835             : 
     836        1901 :     clone->RemoveSGID();
     837        1901 :     clone->Append(sgid_list);
     838        1901 :     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           0 : ExtCommunityPtr ExtCommunityDB::RemoveSiteOfOriginAndLocate(
     857             :         const ExtCommunity *src) {
     858             :     ExtCommunity *clone;
     859           0 :     if (src) {
     860           0 :         clone = new ExtCommunity(*src);
     861             :     } else {
     862           0 :         clone = new ExtCommunity(this);
     863             :     }
     864             : 
     865           0 :     clone->RemoveSiteOfOrigin();
     866           0 :     return Locate(clone);
     867             : }
     868             : 
     869           0 : ExtCommunityPtr ExtCommunityDB::ReplaceSiteOfOriginAndLocate(
     870             :         const ExtCommunity *src,
     871             :         const ExtCommunity::ExtCommunityValue &soo) {
     872             :     ExtCommunity *clone;
     873           0 :     if (src) {
     874           0 :         clone = new ExtCommunity(*src);
     875             :     } else {
     876           0 :         clone = new ExtCommunity(this);
     877             :     }
     878             : 
     879           0 :     clone->RemoveSiteOfOrigin();
     880           0 :     clone->Append(soo);
     881           0 :     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           0 : ExtCommunityPtr ExtCommunityDB::RemoveOriginVnAndLocate(
     941             :         const ExtCommunity *src) {
     942             :     ExtCommunity *clone;
     943           0 :     if (src) {
     944           0 :         clone = new ExtCommunity(*src);
     945             :     } else {
     946           0 :         clone = new ExtCommunity(this);
     947             :     }
     948             : 
     949           0 :     clone->RemoveOriginVn();
     950           0 :     return Locate(clone);
     951             : }
     952             : 
     953           0 : ExtCommunityPtr ExtCommunityDB::ReplaceOriginVnAndLocate(
     954             :         const ExtCommunity *src,
     955             :         const ExtCommunity::ExtCommunityValue &origin_vn) {
     956             :     ExtCommunity *clone;
     957           0 :     if (src) {
     958           0 :         clone = new ExtCommunity(*src);
     959             :     } else {
     960           0 :         clone = new ExtCommunity(this);
     961             :     }
     962             : 
     963           0 :     clone->RemoveOriginVn();
     964           0 :     clone->Append(origin_vn);
     965           0 :     return Locate(clone);
     966             : }
     967             : 
     968        1901 : ExtCommunityPtr ExtCommunityDB::ReplaceTunnelEncapsulationAndLocate(
     969             :         const ExtCommunity *src,
     970             :         const ExtCommunity::ExtCommunityList &tunnel_encaps) {
     971             :     ExtCommunity *clone;
     972        1901 :     if (src) {
     973        1901 :         clone = new ExtCommunity(*src);
     974             :     } else {
     975           0 :         clone = new ExtCommunity(this);
     976             :     }
     977             : 
     978        1901 :     clone->RemoveTunnelEncapsulation();
     979        1901 :     clone->Append(tunnel_encaps);
     980        1901 :     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           0 : void LargeCommunitySpec::ToCanonical(BgpAttr *attr) {
    1046             :     // add LarceComm to attr
    1047           0 :     attr->set_large_community(this);
    1048           0 : }
    1049             : 
    1050         320 : int LargeCommunity::CompareTo(const LargeCommunity &rhs) const {
    1051         320 :     KEY_COMPARE(communities_.size(), rhs.communities_.size());
    1052             : 
    1053         320 :     LargeCommunityList::const_iterator i, j;
    1054         320 :     for (i = communities_.begin(), j = rhs.communities_.begin();
    1055         320 :          i < communities_.end(); ++i, ++j) {
    1056           0 :         if (*i < *j) {
    1057           0 :             return -1;
    1058             :         }
    1059           0 :         if (*i > *j) {
    1060           0 :             return 1;
    1061             :         }
    1062             :     }
    1063         320 :     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          32 : void LargeCommunity::Remove() {
    1074          32 :     largecomm_db_->Delete(this);
    1075          32 : }
    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           0 : void LargeCommunity::Append(const LargeCommunityList &list) {
    1086           0 :     communities_.insert(communities_.end(), list.begin(), list.end());
    1087           0 :     sort(communities_.begin(), communities_.end());
    1088             :     LargeCommunityList::iterator it =
    1089           0 :         unique(communities_.begin(), communities_.end());
    1090           0 :     communities_.erase(it, communities_.end());
    1091           0 : }
    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           0 : void LargeCommunity::RemoveTag() {
    1167           0 :     for (LargeCommunityList::iterator it = communities_.begin();
    1168           0 :          it != communities_.end(); ) {
    1169           0 :         if (LargeCommunity::is_tag(*it)) {
    1170           0 :             it = communities_.erase(it);
    1171             :         } else {
    1172           0 :             ++it;
    1173             :         }
    1174             :     }
    1175           0 : }
    1176             : 
    1177         160 : vector<uint64_t> LargeCommunity::GetTagList(as_t asn) const {
    1178         160 :     vector<uint64_t> tag_list;
    1179         160 :     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         160 :     sort(tag_list.begin(), tag_list.end());
    1189         160 :     vector<uint64_t>::iterator tag_iter = unique(tag_list.begin(),
    1190             :                                                  tag_list.end());
    1191         160 :     tag_list.erase(tag_iter, tag_list.end());
    1192         320 :     return tag_list;
    1193           0 : }
    1194             : 
    1195             : 
    1196         160 : LargeCommunity::LargeCommunity(LargeCommunityDB *largecomm_db,
    1197         160 :         const LargeCommunitySpec spec) : largecomm_db_(largecomm_db) {
    1198         160 :     refcount_ = 0;
    1199         160 :     std::vector<uint32_t>::const_iterator lcit = spec.communities.begin();
    1200         160 :     while (lcit < spec.communities.end()) {
    1201             :         LargeCommunityValue comm;
    1202           0 :         put_value(comm.data(), 4, *lcit);
    1203           0 :         lcit++;
    1204           0 :         put_value(comm.data()+4, 4, *lcit);
    1205           0 :         lcit++;
    1206           0 :         put_value(comm.data()+8, 4, *lcit);
    1207           0 :         lcit++;
    1208           0 :         communities_.push_back(comm);
    1209             :     }
    1210         160 :     sort(communities_.begin(), communities_.end());
    1211             :     LargeCommunityList::iterator it =
    1212         160 :         unique(communities_.begin(), communities_.end());
    1213         160 :     communities_.erase(it, communities_.end());
    1214         160 : }
    1215             : 
    1216          68 : LargeCommunityDB::LargeCommunityDB(BgpServer *server) {
    1217          68 : }
    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           0 : LargeCommunityPtr LargeCommunityDB::ReplaceTagListAndLocate(
    1240             :     const LargeCommunity *src,
    1241             :     const LargeCommunity::LargeCommunityList &tag_list) {
    1242             :     LargeCommunity *clone;
    1243           0 :     if (src) {
    1244           0 :         clone = new LargeCommunity(*src);
    1245             :     } else {
    1246           0 :         clone = new LargeCommunity(this);
    1247             :     }
    1248             : 
    1249           0 :     clone->RemoveTag();
    1250           0 :     clone->Append(tag_list);
    1251           0 :     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