LCOV - code coverage report
Current view: top level - bgp/evpn - evpn_route.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 848 925 91.7 %
Date: 2026-11-09 02:10:49 Functions: 37 37 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #include "bgp/evpn/evpn_route.h"
       7             : 
       8             : #include <algorithm>
       9             : #include <sstream>
      10             : 
      11             : #include "base/string_util.h"
      12             : #include "bgp/bgp_server.h"
      13             : #include "bgp/evpn/evpn_table.h"
      14             : 
      15             : using std::copy;
      16             : using std::string;
      17             : using std::vector;
      18             : 
      19             : const EvpnPrefix EvpnPrefix::kNullPrefix;
      20             : const uint32_t EvpnPrefix::kInvalidLabel = 0x01000000;
      21             : const uint32_t EvpnPrefix::kNullTag = 0;
      22             : const uint32_t EvpnPrefix::kMaxTag = 0xFFFFFFFF;
      23             : const uint32_t EvpnPrefix::kMaxVni = 0x00FFFFFF;
      24             : const int32_t EvpnPrefix::kMaxVniSigned =
      25             :     static_cast<uint32_t>(EvpnPrefix::kMaxVni);
      26             : 
      27             : const size_t EvpnPrefix::kRdSize = RouteDistinguisher::kSize;
      28             : const size_t EvpnPrefix::kEsiSize = EthernetSegmentId::kSize;
      29             : const size_t EvpnPrefix::kTagSize = 4;
      30             : const size_t EvpnPrefix::kIp4AddrSize = 4;
      31             : const size_t EvpnPrefix::kIp6AddrSize = 16;
      32             : const size_t EvpnPrefix::kMacSize = MacAddress::size();
      33             : const size_t EvpnPrefix::kLabelSize = BgpProtoPrefix::kLabelSize;
      34             : 
      35             : const size_t EvpnPrefix::kMinAutoDiscoveryRouteSize =
      36             :     kRdSize + kEsiSize + kTagSize;
      37             : const size_t EvpnPrefix::kMinMacAdvertisementRouteSize =
      38             :     kRdSize + kEsiSize + kTagSize + 1 + kMacSize + 1;
      39             : const size_t EvpnPrefix::kMinInclusiveMulticastRouteSize =
      40             :     kRdSize + kTagSize + 1;
      41             : const size_t EvpnPrefix::kMinSelectiveMulticastRouteSize =
      42             :     kRdSize + kTagSize + 3;
      43             : const size_t EvpnPrefix::kMinSegmentRouteSize =
      44             :     kRdSize + kEsiSize + 1;
      45             : const size_t EvpnPrefix::kMinInetPrefixRouteSize =
      46             :     kRdSize + kEsiSize + kTagSize + 1 + 2 * kIp4AddrSize;
      47             : const size_t EvpnPrefix::kMinInet6PrefixRouteSize =
      48             :     kRdSize + kEsiSize + kTagSize + 1 + 2 * kIp6AddrSize;
      49             : 
      50             : //
      51             : // Read label from the BgpProtoPrefix.
      52             : // If the encapsulation is VXLAN and ethernet tag is non-zero use that as
      53             : // the label for backward compatibility with older JUNOS code.
      54             : //
      55             : // Note that Ethernet AD Routes per ESI always set ethernet tag to kMaxTag
      56             : // and their label is supposed to be set to 0 on write and ignored on read.
      57             : //
      58       25546 : static uint32_t ReadLabel(const BgpProtoPrefix &proto_prefix,
      59             :     const BgpAttr *attr, size_t offset, uint32_t tag = EvpnPrefix::kNullTag) {
      60       25546 :     if (!attr)
      61        6883 :         return 0;
      62       18663 :     const ExtCommunity *extcomm = attr->ext_community();
      63       18663 :     if (extcomm && extcomm->ContainsTunnelEncapVxlan()) {
      64         146 :         if (tag) {
      65          60 :             if (tag == EvpnPrefix::kMaxTag) {
      66           4 :                 return 0;
      67          56 :             } else if (tag <= EvpnPrefix::kMaxVni) {
      68          28 :                 return tag;
      69             :             } else {
      70          28 :                 return proto_prefix.ReadLabel(offset, true);
      71             :             }
      72             :         } else {
      73          86 :             return proto_prefix.ReadLabel(offset, true);
      74             :         }
      75             :     } else {
      76       18517 :         return proto_prefix.ReadLabel(offset, false);
      77             :     }
      78             : }
      79             : 
      80             : //
      81             : // Write label to the BgpProtoPrefix.
      82             : //
      83       29329 : static void WriteLabel(BgpProtoPrefix *proto_prefix,
      84             :     const BgpAttr *attr, size_t offset, uint32_t label) {
      85       29329 :     const ExtCommunity *extcomm = attr ? attr->ext_community() : NULL;
      86       29329 :     if (extcomm && extcomm->ContainsTunnelEncapVxlan()) {
      87         146 :         proto_prefix->WriteLabel(offset, label, true);
      88             :     } else {
      89       29182 :         proto_prefix->WriteLabel(offset, label, false);
      90             :     }
      91       29328 : }
      92             : 
      93             : //
      94             : // Read gateway address from the BgpProtoPrefix.
      95             : //
      96        1779 : static IpAddress ReadGwAddress(const BgpProtoPrefix &proto_prefix,
      97             :     size_t gw_offset, size_t ip_size) {
      98        1779 :     assert(ip_size == EvpnPrefix::kIp4AddrSize ||
      99             :         ip_size == EvpnPrefix::kIp6AddrSize);
     100        1779 :     if (ip_size == EvpnPrefix::kIp4AddrSize) {
     101             :         Ip4Address::bytes_type bytes;
     102        2252 :         copy(proto_prefix.prefix.begin() + gw_offset,
     103        1126 :             proto_prefix.prefix.begin() + gw_offset + ip_size, bytes.begin());
     104        1126 :         return Ip4Address(bytes);
     105             :     } else {
     106             :         Ip6Address::bytes_type bytes;
     107        1306 :         copy(proto_prefix.prefix.begin() + gw_offset,
     108         653 :             proto_prefix.prefix.begin() + gw_offset + ip_size, bytes.begin());
     109         653 :         return Ip6Address(bytes);
     110             :     }
     111             :     return IpAddress();
     112             : }
     113             : 
     114      128684 : EvpnPrefix::EvpnPrefix()
     115      128684 :     : type_(Unspecified),
     116      128680 :       tag_(EvpnPrefix::kNullTag),
     117      128680 :       family_(Address::UNSPEC),
     118      128684 :       ip_prefixlen_(0) {
     119      128667 : }
     120             : 
     121          92 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd,
     122          92 :     const EthernetSegmentId &esi, uint32_t tag)
     123          92 :     : type_(AutoDiscoveryRoute),
     124          92 :       rd_(rd),
     125          92 :       esi_(esi),
     126          92 :       tag_(tag),
     127          92 :       family_(Address::UNSPEC),
     128          92 :       ip_prefixlen_(0) {
     129          92 : }
     130             : 
     131           3 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd,
     132           3 :     const MacAddress &mac_addr, const IpAddress &ip_address)
     133           3 :     : type_(MacAdvertisementRoute),
     134           3 :       rd_(rd),
     135           3 :       tag_(EvpnPrefix::kNullTag),
     136           3 :       mac_addr_(mac_addr),
     137           3 :       family_(Address::UNSPEC),
     138           3 :       ip_address_(ip_address),
     139           6 :       ip_prefixlen_(0) {
     140           3 :     if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
     141           1 :         family_ = Address::INET;
     142           2 :     } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
     143           1 :         family_ = Address::INET6;
     144             :     }
     145           3 : }
     146             : 
     147       15637 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, uint32_t tag,
     148       15637 :     const MacAddress &mac_addr, const IpAddress &ip_address)
     149       15637 :     : type_(MacAdvertisementRoute), rd_(rd), tag_(tag),
     150       15636 :       mac_addr_(mac_addr), family_(Address::UNSPEC),
     151       31272 :       ip_address_(ip_address), ip_prefixlen_(0) {
     152       15636 :     if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
     153         220 :         family_ = Address::INET;
     154       15415 :     } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
     155          28 :         family_ = Address::INET6;
     156             :     }
     157       15635 : }
     158             : 
     159       24876 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, uint32_t tag,
     160       24876 :     const IpAddress &ip_address)
     161       24876 :     : type_(InclusiveMulticastRoute),
     162       24876 :       rd_(rd),
     163       24876 :       tag_(tag),
     164       24876 :       family_(Address::UNSPEC),
     165       24876 :       ip_address_(ip_address),
     166       49752 :       ip_prefixlen_(0) {
     167       24876 :     if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
     168       24871 :         family_ = Address::INET;
     169           5 :     } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
     170           5 :         family_ = Address::INET6;
     171             :     }
     172       24876 : }
     173             : 
     174           2 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd,
     175           2 :     const EthernetSegmentId &esi, const IpAddress &ip_address)
     176           2 :     : type_(SegmentRoute),
     177           2 :       rd_(rd),
     178           2 :       esi_(esi),
     179           2 :       tag_(EvpnPrefix::kNullTag),
     180           2 :       family_(Address::UNSPEC),
     181           2 :       ip_address_(ip_address),
     182           4 :       ip_prefixlen_(0) {
     183           2 :     if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
     184           1 :         family_ = Address::INET;
     185           1 :     } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
     186           1 :         family_ = Address::INET6;
     187             :     }
     188           2 : }
     189             : 
     190        1039 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd,
     191        1039 :     const IpAddress &ip_address, uint8_t ip_prefixlen)
     192        1039 :     : type_(IpPrefixRoute),
     193        1039 :       rd_(rd),
     194        1039 :       tag_(0),
     195        1039 :       family_(Address::UNSPEC),
     196        1039 :       ip_address_(ip_address),
     197        2078 :       ip_prefixlen_(ip_prefixlen) {
     198        1039 :     assert(ip_address_.is_v4() || ip_address_.is_v6());
     199        1039 :     if (ip_address_.is_v4()) {
     200         653 :         family_ = Address::INET;
     201         386 :     } else if (ip_address_.is_v6()) {
     202         386 :         family_ = Address::INET6;
     203             :     }
     204        1039 : }
     205             : 
     206          46 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, uint32_t tag,
     207             :     const IpAddress &source, const IpAddress &group,
     208          46 :     const IpAddress &ip_address)
     209          46 :     : type_(SelectiveMulticastRoute),
     210          46 :       rd_(rd),
     211          46 :       tag_(tag),
     212          46 :       family_(Address::UNSPEC),
     213          46 :       ip_address_(ip_address),
     214          46 :       source_(source),
     215          46 :       group_(group),
     216          46 :       ip_prefixlen_(0), flags_(0x2) {
     217          46 :     if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
     218          46 :         family_ = Address::INET;
     219           0 :     } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
     220           0 :         family_ = Address::INET6;
     221             :     }
     222          46 :     string ip = group.to_v4().to_string();
     223          46 :     char *str = const_cast<char *>(ip.c_str());
     224          46 :     char * mac_ip = strstr(str, ".");
     225          46 :     std::ostringstream oss;
     226          46 :     oss << "01:00:5e:" << strtok(mac_ip, "."); 
     227          46 :     oss << ":" << strtok(NULL, ".");
     228          46 :     oss << ":" << strtok(NULL, "");
     229          46 :     mac_addr_ = MacAddress::FromString(oss.str(), NULL);
     230          46 : }
     231             : 
     232       28826 : int EvpnPrefix::FromProtoPrefix(BgpServer *server,
     233             :     const BgpProtoPrefix &proto_prefix, const BgpAttr *attr,
     234             :     const Address::Family family, EvpnPrefix *prefix, BgpAttrPtr *new_attr,
     235             :     uint32_t *label, uint32_t *l3_label) {
     236       28826 :     *new_attr = attr;
     237       28826 :     *label = 0;
     238       28826 :     if (l3_label)
     239       26135 :         *l3_label = 0;
     240       28826 :     prefix->type_ = proto_prefix.type;
     241       28826 :     size_t nlri_size = proto_prefix.prefix.size();
     242             : 
     243       28826 :     switch (prefix->type_) {
     244          81 :     case AutoDiscoveryRoute: {
     245          81 :         size_t expected_min_nlri_size =
     246          81 :             kMinAutoDiscoveryRouteSize + (attr ? kLabelSize : 0);
     247          81 :         if (nlri_size < expected_min_nlri_size)
     248          47 :             return -1;
     249          34 :         size_t rd_offset = 0;
     250          34 :         prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
     251          34 :         size_t esi_offset = rd_offset + kRdSize;
     252          34 :         prefix->esi_ = EthernetSegmentId(&proto_prefix.prefix[esi_offset]);
     253          34 :         size_t tag_offset = esi_offset + kEsiSize;
     254          34 :         prefix->tag_ = get_value(&proto_prefix.prefix[tag_offset], kTagSize);
     255          34 :         size_t label_offset = tag_offset + kTagSize;
     256          34 :         *label = ReadLabel(proto_prefix, attr, label_offset, prefix->tag_);
     257          34 :         break;
     258             :     }
     259       24796 :     case MacAdvertisementRoute: {
     260       24796 :         size_t expected_min_nlri_size =
     261       24796 :             kMinMacAdvertisementRouteSize + (attr ? kLabelSize : 0);
     262       24796 :         if (nlri_size < expected_min_nlri_size)
     263          63 :             return -1;
     264       24733 :         size_t rd_offset = 0;
     265       24733 :         prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
     266       24733 :         size_t esi_offset = rd_offset + kRdSize;
     267       24733 :         if (attr) {
     268       17816 :             EthernetSegmentId esi(&proto_prefix.prefix[esi_offset]);
     269       17816 :             *new_attr = server->attr_db()->ReplaceEsiAndLocate(attr, esi);
     270             :         }
     271       24733 :         size_t tag_offset = esi_offset + kEsiSize;
     272       24733 :         prefix->tag_ = get_value(&proto_prefix.prefix[tag_offset], kTagSize);
     273       24733 :         size_t mac_len_offset = tag_offset + kTagSize;
     274       24733 :         size_t mac_len = proto_prefix.prefix[mac_len_offset];
     275       24733 :         if (mac_len != 48)
     276         510 :             return -1;
     277       24223 :         size_t mac_offset = mac_len_offset + 1;
     278       24223 :         prefix->mac_addr_ = MacAddress(&proto_prefix.prefix[mac_offset]);
     279       24223 :         size_t ip_len_offset = mac_offset + kMacSize;
     280       24223 :         size_t ip_len = proto_prefix.prefix[ip_len_offset];
     281       24223 :         if (ip_len != 0 && ip_len != 32 && ip_len != 128)
     282         506 :             return -1;
     283       23717 :         size_t ip_size = ip_len / 8;
     284       23717 :         if (nlri_size < expected_min_nlri_size + ip_size)
     285          40 :             return -1;
     286       23677 :         size_t ip_offset = ip_len_offset + 1;
     287       23677 :         prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_size);
     288       23677 :         size_t label_offset = ip_offset + ip_size;
     289       23677 :         *label = ReadLabel(proto_prefix, attr, label_offset, prefix->tag_);
     290       23677 :         size_t l3_label_offset = label_offset + kLabelSize;
     291       23677 :         if (l3_label && nlri_size >= l3_label_offset + kLabelSize) {
     292          76 :             *l3_label = ReadLabel(proto_prefix, attr, l3_label_offset);
     293             :         }
     294       23677 :         break;
     295             :     }
     296        1027 :     case InclusiveMulticastRoute: {
     297        1027 :         if (nlri_size < kMinInclusiveMulticastRouteSize)
     298          13 :             return -1;
     299        1014 :         size_t rd_offset = 0;
     300        1014 :         prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
     301        1014 :         size_t tag_offset = rd_offset + kRdSize;
     302        1014 :         prefix->tag_ = get_value(&proto_prefix.prefix[tag_offset], kTagSize);
     303        1014 :         size_t ip_len_offset = tag_offset + kTagSize;
     304        1014 :         size_t ip_len = proto_prefix.prefix[ip_len_offset];
     305        1014 :         if (ip_len != 32 && ip_len != 128)
     306         254 :             return -1;
     307         760 :         size_t ip_size = ip_len / 8;
     308         760 :         if (nlri_size < kMinInclusiveMulticastRouteSize + ip_size)
     309          20 :             return -1;
     310         740 :         size_t ip_offset = ip_len_offset + 1;
     311         740 :         prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_size);
     312         740 :         const PmsiTunnel *pmsi_tunnel = attr ? attr->pmsi_tunnel() : NULL;
     313        1128 :         if (pmsi_tunnel &&
     314         388 :             (pmsi_tunnel->tunnel_type() == PmsiTunnelSpec::IngressReplication ||
     315           0 :              pmsi_tunnel->tunnel_type() ==
     316             :              PmsiTunnelSpec::AssistedReplicationContrail)) {
     317         388 :             const ExtCommunity *extcomm = attr ? attr->ext_community() : NULL;
     318         388 :             if (extcomm && extcomm->ContainsTunnelEncapVxlan()) {
     319          24 :                 if (prefix->tag_ && prefix->tag_ <= kMaxVni) {
     320           8 :                     *label = prefix->tag_;
     321             :                 } else {
     322          16 :                     *label = pmsi_tunnel->GetLabel(extcomm);
     323             :                 }
     324             :             } else {
     325         364 :                 *label = pmsi_tunnel->GetLabel(extcomm);
     326             :             }
     327             :         }
     328         740 :         break;
     329             :     }
     330         295 :     case SegmentRoute: {
     331         295 :         if (nlri_size < kMinSegmentRouteSize)
     332          19 :             return -1;
     333         276 :         size_t rd_offset = 0;
     334         276 :         prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
     335         276 :         size_t esi_offset = rd_offset + kRdSize;
     336         276 :         prefix->esi_ = EthernetSegmentId(&proto_prefix.prefix[esi_offset]);
     337         276 :         size_t ip_len_offset = esi_offset + kEsiSize;
     338         276 :         size_t ip_len = proto_prefix.prefix[ip_len_offset];
     339         276 :         if (ip_len != 32 && ip_len != 128)
     340         254 :             return -1;
     341          22 :         size_t ip_size = ip_len / 8;
     342          22 :         if (nlri_size < kMinSegmentRouteSize + ip_size)
     343          20 :             return -1;
     344           2 :         size_t ip_offset = ip_len_offset + 1;
     345           2 :         prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_size);
     346           2 :         break;
     347             :     }
     348        2329 :     case IpPrefixRoute: {
     349             :         size_t ip_size;
     350        2329 :         if (attr) {
     351        1774 :             if (nlri_size == kMinInet6PrefixRouteSize + kLabelSize) {
     352         643 :                 ip_size = kIp6AddrSize;
     353        1131 :             } else if (nlri_size == kMinInetPrefixRouteSize + kLabelSize) {
     354        1039 :                 ip_size = kIp4AddrSize;
     355             :             } else {
     356         570 :                 return -1;
     357             :             }
     358             :         } else {
     359         555 :             if (nlri_size == kMinInet6PrefixRouteSize ||
     360         555 :                 nlri_size == kMinInet6PrefixRouteSize + kLabelSize) {
     361         147 :                 ip_size = kIp6AddrSize;
     362         408 :             } else if (nlri_size == kMinInetPrefixRouteSize ||
     363         408 :                 nlri_size == kMinInetPrefixRouteSize + kLabelSize) {
     364         320 :                 ip_size = kIp4AddrSize;
     365             :             } else {
     366          88 :                 return -1;
     367             :             }
     368             :         }
     369             : 
     370        2149 :         size_t rd_offset = 0;
     371        2149 :         prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
     372        2149 :         size_t esi_offset = rd_offset + kRdSize;
     373        2149 :         EthernetSegmentId esi(&proto_prefix.prefix[esi_offset]);
     374        2149 :         if (!esi.IsZero())
     375          20 :             return -1;
     376        2129 :         size_t tag_offset = esi_offset + kEsiSize;
     377             :         // Ignore tag for type5 routes.
     378        2129 :         prefix->tag_ = 0;
     379        2129 :         size_t ip_plen_offset = tag_offset + kTagSize;
     380        2129 :         prefix->ip_prefixlen_ = proto_prefix.prefix[ip_plen_offset];
     381        2129 :         if (ip_size == kIp4AddrSize && prefix->ip_prefixlen_ > 32)
     382         223 :             return -1;
     383        1906 :         if (ip_size == kIp6AddrSize && prefix->ip_prefixlen_ > 128)
     384         127 :             return -1;
     385        1779 :         size_t ip_offset = ip_plen_offset + 1;
     386        1779 :         size_t ip_psize = (prefix->ip_prefixlen_ + 7) / 8;
     387        1779 :         prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_psize);
     388        1779 :         size_t gw_offset = ip_offset + ip_size;
     389        1779 :         IpAddress gw_address = ReadGwAddress(proto_prefix, gw_offset, ip_size);
     390        1779 :         if (!gw_address.is_unspecified())
     391          20 :             return -1;
     392        1759 :         size_t label_offset = gw_offset + ip_size;
     393        1759 :         *label = ReadLabel(proto_prefix, attr, label_offset);
     394        1759 :         break;
     395             :     }
     396          49 :     case SelectiveMulticastRoute: {
     397          49 :         if (nlri_size < kMinSelectiveMulticastRouteSize)
     398           1 :             return -1;
     399          48 :         size_t rd_offset = 0;
     400          48 :         prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
     401          48 :         size_t tag_offset = rd_offset + kRdSize;
     402          48 :         prefix->tag_ = get_value(&proto_prefix.prefix[tag_offset], kTagSize);
     403          48 :         size_t src_len_offset = tag_offset + kTagSize;
     404          48 :         size_t src_len = proto_prefix.prefix[src_len_offset];
     405          48 :         if (src_len != 32 && src_len != 128 && src_len != 0)
     406           0 :             return -1;
     407          48 :         size_t src_size = src_len / 8;
     408          48 :         size_t src_offset = src_len_offset + 1;
     409          48 :         if (src_size > 0) {
     410          48 :             if (nlri_size < src_offset + src_size)
     411           0 :                 return -1;
     412          48 :             prefix->ReadSource(proto_prefix, src_offset, src_size);
     413             :         }
     414          48 :         size_t grp_len_offset = src_offset + src_size;
     415          48 :         size_t grp_len = proto_prefix.prefix[grp_len_offset];
     416          48 :         if (grp_len != 32 && grp_len != 128)
     417           0 :             return -1;
     418          48 :         size_t grp_size = grp_len / 8;
     419          48 :         size_t grp_offset = grp_len_offset + 1;
     420          48 :         if (nlri_size < grp_offset + grp_size)
     421           0 :             return -1;
     422          48 :         prefix->ReadGroup(proto_prefix, grp_offset, grp_size);
     423          48 :         size_t ip_len_offset = grp_offset + grp_size;
     424          48 :         size_t ip_len = proto_prefix.prefix[ip_len_offset];
     425          48 :         if (ip_len != 32 && ip_len != 128)
     426           0 :             return -1;
     427          48 :         size_t ip_size = ip_len / 8;
     428          48 :         size_t ip_offset = ip_len_offset + 1;
     429          48 :         if (nlri_size < ip_offset + ip_size)
     430           0 :             return -1;
     431          48 :         prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_size);
     432          48 :         size_t flag_offset = ip_offset + ip_size;
     433          48 :         if (nlri_size <= flag_offset + 4)
     434          48 :             prefix->flags_ = get_value(&proto_prefix.prefix[flag_offset], 4);
     435          48 :         break;
     436             :     }
     437         249 :     default: {
     438         249 :         return -1;
     439             :         break;
     440             :     }
     441             :     }
     442       26260 :     return 0;
     443             : }
     444             : 
     445             : //
     446             : // Build the BgpProtoPrefix for this EvpnPrefix.
     447             : //
     448             : // The ESI for MacAdvertisementRoute is not part of the key and hence
     449             : // must be obtained from the BgpAttr. The BgpAttr is NULL and label is
     450             : // 0 when withdrawing the route.
     451             : //
     452       30044 : void EvpnPrefix::BuildProtoPrefix(BgpProtoPrefix *proto_prefix,
     453             :     const BgpAttr *attr, uint32_t label, uint32_t l3_label) const {
     454       30044 :     proto_prefix->type = type_;
     455       30044 :     proto_prefix->prefix.clear();
     456             : 
     457       30044 :     switch (type_) {
     458          28 :     case AutoDiscoveryRoute: {
     459          28 :         size_t nlri_size = kMinAutoDiscoveryRouteSize + kLabelSize;
     460          28 :         proto_prefix->prefixlen = nlri_size * 8;
     461          28 :         proto_prefix->prefix.resize(nlri_size, 0);
     462             : 
     463          28 :         size_t rd_offset = 0;
     464          28 :         copy(rd_.GetData(), rd_.GetData() + kRdSize,
     465          28 :             proto_prefix->prefix.begin() + rd_offset);
     466          28 :         size_t esi_offset = rd_offset + kRdSize;
     467          28 :         copy(esi_.GetData(), esi_.GetData() + kEsiSize,
     468          28 :             proto_prefix->prefix.begin() + esi_offset);
     469          28 :         size_t tag_offset = esi_offset + kEsiSize;
     470          28 :         put_value(&proto_prefix->prefix[tag_offset], kTagSize, tag_);
     471          28 :         size_t label_offset = tag_offset + kTagSize;
     472          28 :         WriteLabel(proto_prefix, attr, label_offset, label);
     473          28 :         break;
     474             :     }
     475       27467 :     case MacAdvertisementRoute: {
     476       27467 :         size_t ip_size = GetIpAddressSize();
     477       27467 :         size_t nlri_size = kMinMacAdvertisementRouteSize + ip_size + kLabelSize;
     478       27467 :         if (l3_label)
     479          76 :             nlri_size += kLabelSize;
     480       27467 :         proto_prefix->prefixlen = nlri_size * 8;
     481       27467 :         proto_prefix->prefix.resize(nlri_size, 0);
     482             : 
     483       27467 :         size_t rd_offset = 0;
     484       27467 :         copy(rd_.GetData(), rd_.GetData() + kRdSize,
     485       27467 :             proto_prefix->prefix.begin() + rd_offset);
     486       27467 :         size_t esi_offset = rd_offset + kRdSize;
     487       27467 :         if (attr) {
     488       17352 :             copy(attr->esi().GetData(), attr->esi().GetData() + kEsiSize,
     489       34704 :                 proto_prefix->prefix.begin() + esi_offset);
     490             :         }
     491       27467 :         size_t tag_offset = esi_offset + kEsiSize;
     492       27467 :         put_value(&proto_prefix->prefix[tag_offset], kTagSize, tag_);
     493       27467 :         size_t mac_len_offset = tag_offset + kTagSize;
     494       27467 :         proto_prefix->prefix[mac_len_offset] = 48;
     495       27467 :         size_t mac_offset = mac_len_offset + 1;
     496       27467 :         copy(mac_addr_.GetData(), mac_addr_.GetData() + kMacSize,
     497       27467 :             proto_prefix->prefix.begin() + mac_offset);
     498       27467 :         size_t ip_len_offset = mac_offset + kMacSize;
     499       27467 :         proto_prefix->prefix[ip_len_offset] = ip_size * 8;
     500       27467 :         size_t ip_offset = ip_len_offset + 1;
     501       27467 :         WriteIpAddress(proto_prefix, ip_offset);
     502       27467 :         size_t label_offset = ip_offset + ip_size;
     503       27467 :         WriteLabel(proto_prefix, attr, label_offset, label);
     504       27467 :         if (l3_label) {
     505          76 :             size_t l3_label_offset = label_offset + kLabelSize;
     506          76 :             WriteLabel(proto_prefix, attr, l3_label_offset, l3_label);
     507             :         }
     508       27467 :         break;
     509             :     }
     510         740 :     case InclusiveMulticastRoute: {
     511         740 :         size_t ip_size = GetIpAddressSize();
     512         740 :         size_t nlri_size = kMinInclusiveMulticastRouteSize + ip_size;
     513         740 :         proto_prefix->prefixlen = nlri_size * 8;
     514         740 :         proto_prefix->prefix.resize(nlri_size, 0);
     515             : 
     516         740 :         size_t rd_offset = 0;
     517         740 :         copy(rd_.GetData(), rd_.GetData() + kRdSize,
     518         740 :             proto_prefix->prefix.begin() + rd_offset);
     519         740 :         size_t tag_offset = rd_offset + kRdSize;
     520         740 :         put_value(&proto_prefix->prefix[tag_offset], kTagSize, tag_);
     521         740 :         size_t ip_len_offset = tag_offset + kTagSize;
     522         740 :         proto_prefix->prefix[ip_len_offset] = ip_size * 8;
     523         740 :         size_t ip_offset = ip_len_offset + 1;
     524         740 :         WriteIpAddress(proto_prefix, ip_offset);
     525         740 :         break;
     526             :     }
     527           2 :     case SegmentRoute: {
     528           2 :         size_t ip_size = GetIpAddressSize();
     529           2 :         size_t nlri_size = kMinSegmentRouteSize + ip_size;
     530           2 :         proto_prefix->prefixlen = nlri_size * 8;
     531           2 :         proto_prefix->prefix.resize(nlri_size, 0);
     532             : 
     533           2 :         size_t rd_offset = 0;
     534           2 :         copy(rd_.GetData(), rd_.GetData() + kRdSize,
     535           2 :             proto_prefix->prefix.begin() + rd_offset);
     536           2 :         size_t esi_offset = rd_offset + kRdSize;
     537           2 :         copy(esi_.GetData(), esi_.GetData() + kEsiSize,
     538           2 :             proto_prefix->prefix.begin() + esi_offset);
     539           2 :         size_t ip_len_offset = esi_offset + kEsiSize;
     540           2 :         proto_prefix->prefix[ip_len_offset] = ip_size * 8;
     541           2 :         size_t ip_offset = ip_len_offset + 1;
     542           2 :         WriteIpAddress(proto_prefix, ip_offset);
     543           2 :         break;
     544             :     }
     545        1759 :     case IpPrefixRoute: {
     546             :         size_t ip_size, nlri_size;
     547        1759 :         if (family_ == Address::INET) {
     548        1122 :             ip_size = kIp4AddrSize;
     549        1122 :             nlri_size = kMinInetPrefixRouteSize + kLabelSize;
     550             :         } else {
     551         637 :             ip_size = kIp6AddrSize;
     552         637 :             nlri_size = kMinInet6PrefixRouteSize + kLabelSize;
     553             :         }
     554        1759 :         proto_prefix->prefixlen = nlri_size * 8;
     555        1759 :         proto_prefix->prefix.resize(nlri_size, 0);
     556             : 
     557        1759 :         size_t rd_offset = 0;
     558        1759 :         copy(rd_.GetData(), rd_.GetData() + kRdSize,
     559        1759 :             proto_prefix->prefix.begin() + rd_offset);
     560        1759 :         size_t esi_offset = rd_offset + kRdSize;
     561        1759 :         if (attr) {
     562        1292 :             copy(attr->esi().GetData(), attr->esi().GetData() + kEsiSize,
     563        2584 :                 proto_prefix->prefix.begin() + esi_offset);
     564             :         }
     565        1759 :         size_t tag_offset = esi_offset + kEsiSize;
     566             :         // Tag is not applicable for type5 routes.
     567        1759 :         put_value(&proto_prefix->prefix[tag_offset], kTagSize, 0);
     568        1759 :         size_t ip_plen_offset = tag_offset + kTagSize;
     569        1759 :         proto_prefix->prefix[ip_plen_offset] = ip_prefixlen_;
     570        1759 :         size_t ip_offset = ip_plen_offset + 1;
     571        1759 :         WriteIpAddress(proto_prefix, ip_offset);
     572        1758 :         size_t gw_offset = ip_offset + ip_size;
     573        1758 :         size_t label_offset = gw_offset + ip_size;
     574        1758 :         WriteLabel(proto_prefix, attr, label_offset, label);
     575        1757 :         break;
     576             :     }
     577          48 :     case SelectiveMulticastRoute: {
     578          48 :         size_t ip_size = GetIpAddressSize();
     579          48 :         size_t nlri_size = kMinSelectiveMulticastRouteSize + 2 * ip_size + 1;
     580          48 :         if (!source_.is_unspecified())
     581          48 :             nlri_size += ip_size;
     582          48 :         proto_prefix->prefixlen = nlri_size * 8;
     583          48 :         proto_prefix->prefix.resize(nlri_size, 0);
     584             : 
     585          48 :         size_t rd_offset = 0;
     586          48 :         copy(rd_.GetData(), rd_.GetData() + kRdSize,
     587          48 :             proto_prefix->prefix.begin() + rd_offset);
     588          48 :         size_t tag_offset = rd_offset + kRdSize;
     589          48 :         put_value(&proto_prefix->prefix[tag_offset], kTagSize, tag_);
     590          48 :         size_t src_len_offset = tag_offset + kTagSize;
     591          48 :         size_t grp_len_offset = src_len_offset + 1;
     592          48 :         if (source_.is_unspecified()) {
     593           0 :             proto_prefix->prefix[src_len_offset] = 0;
     594             :         } else {
     595          48 :             proto_prefix->prefix[src_len_offset] = ip_size * 8;
     596          48 :             size_t src_offset = src_len_offset + 1;
     597          48 :             WriteSource(proto_prefix, src_offset);
     598          48 :             grp_len_offset += ip_size;
     599             :         }
     600          48 :         proto_prefix->prefix[grp_len_offset] = ip_size * 8;
     601          48 :         size_t grp_offset = grp_len_offset + 1;
     602          48 :         WriteGroup(proto_prefix, grp_offset);
     603          48 :         size_t ip_len_offset = grp_offset + ip_size;
     604          48 :         proto_prefix->prefix[ip_len_offset] = ip_size * 8;
     605          48 :         size_t ip_offset = ip_len_offset + 1;
     606          48 :         WriteIpAddress(proto_prefix, ip_offset);
     607          48 :         size_t flag_offset = ip_offset + ip_size;
     608          48 :         put_value(&proto_prefix->prefix[flag_offset], 1, flags_);
     609          48 :         break;
     610             :     }
     611           0 :     default: {
     612           0 :         assert(false);
     613             :         break;
     614             :     }
     615             :     }
     616       30042 : }
     617             : 
     618     2739867 : int EvpnPrefix::CompareTo(const EvpnPrefix &rhs) const {
     619     2739867 :     KEY_COMPARE(type_, rhs.type_);
     620             : 
     621     2703547 :     switch (type_) {
     622       41839 :     case AutoDiscoveryRoute:
     623       41839 :         KEY_COMPARE(rd_, rhs.rd_);
     624       29520 :         KEY_COMPARE(esi_, rhs.esi_);
     625       17201 :         KEY_COMPARE(tag_, rhs.tag_);
     626        4882 :         break;
     627     1046697 :     case MacAdvertisementRoute:
     628     1046697 :         KEY_COMPARE(rd_, rhs.rd_);
     629      545306 :         KEY_COMPARE(tag_, rhs.tag_);
     630      544740 :         KEY_COMPARE(mac_addr_, rhs.mac_addr_);
     631      225552 :         KEY_COMPARE(ip_address_, rhs.ip_address_);
     632      158782 :         break;
     633      471093 :     case InclusiveMulticastRoute:
     634      471093 :         KEY_COMPARE(rd_, rhs.rd_);
     635      190561 :         KEY_COMPARE(tag_, rhs.tag_);
     636      176140 :         KEY_COMPARE(ip_address_, rhs.ip_address_);
     637      109846 :         break;
     638       41571 :     case SegmentRoute:
     639       41571 :         KEY_COMPARE(rd_, rhs.rd_);
     640       29252 :         KEY_COMPARE(esi_, rhs.esi_);
     641       16933 :         KEY_COMPARE(ip_address_, rhs.ip_address_);
     642        4614 :         break;
     643     1081879 :     case IpPrefixRoute:
     644     1081879 :         KEY_COMPARE(rd_, rhs.rd_);
     645     1001735 :         KEY_COMPARE(tag_, rhs.tag_);
     646     1001735 :         KEY_COMPARE(ip_address_, rhs.ip_address_);
     647      170525 :         KEY_COMPARE(ip_prefixlen_, rhs.ip_prefixlen_);
     648      170525 :         break;
     649       20489 :     case SelectiveMulticastRoute:
     650       20489 :         KEY_COMPARE(rd_, rhs.rd_);
     651       20148 :         KEY_COMPARE(tag_, rhs.tag_);
     652       17358 :         KEY_COMPARE(source_, rhs.source_);
     653       17358 :         KEY_COMPARE(group_, rhs.group_);
     654       10538 :         KEY_COMPARE(ip_address_, rhs.ip_address_);
     655             :     default:
     656       10517 :         break;
     657             :     }
     658             : 
     659      459166 :     return 0;
     660             : }
     661             : 
     662             : // Check whether 'this' is more specific than rhs.
     663       19866 : bool EvpnPrefix::IsMoreSpecific(const EvpnPrefix &rhs) const {
     664       19866 :     switch (type_) {
     665       19868 :     case IpPrefixRoute:
     666       19868 :         if (family_ == Address::INET) {
     667        9942 :             return inet_prefix().IsMoreSpecific(rhs.inet_prefix());
     668             :         } else {
     669        9926 :             return inet6_prefix().IsMoreSpecific(rhs.inet6_prefix());
     670             :         }
     671             :         break;
     672           0 :     default:
     673           0 :         break;
     674             :     }
     675           0 :     return false;
     676             : }
     677             : 
     678        3336 : bool EvpnPrefix::GetSourceFromString(EvpnPrefix *prefix, const string &str,
     679             :         size_t pos1, size_t *pos2, boost::system::error_code *errorp) {
     680        3336 :     *pos2 = str.find('-', pos1 + 1);
     681        3336 :     if (*pos2 == string::npos) {
     682           0 :         if (errorp != NULL) {
     683           0 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     684             :         }
     685           0 :         return false;
     686             :     }
     687        3336 :     string temp_str = str.substr(pos1 + 1, *pos2 - pos1 - 1);
     688        3336 :     boost::system::error_code source_err;
     689        3336 :     prefix->source_ = Ip4Address::from_string(temp_str, source_err);
     690        3336 :     if (source_err.failed()) {
     691           0 :         if (errorp != NULL) {
     692           0 :             *errorp = source_err;
     693             :         }
     694           0 :         return false;
     695             :     }
     696        3336 :     return true;
     697        3336 : }
     698             : 
     699        3336 : bool EvpnPrefix::GetGroupFromString(EvpnPrefix *prefix, const string &str,
     700             :         size_t pos1, size_t *pos2, boost::system::error_code *errorp) {
     701        3336 :     *pos2 = str.find('-', pos1 + 1);
     702        3336 :     if (*pos2 == string::npos) {
     703           0 :         if (errorp != NULL) {
     704           0 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     705             :         }
     706           0 :         return false;
     707             :     }
     708        3336 :     string temp_str = str.substr(pos1 + 1, *pos2 - pos1 - 1);
     709        3336 :     boost::system::error_code group_err;
     710        3336 :     prefix->group_ = Ip4Address::from_string(temp_str, group_err);
     711        3336 :     if (group_err.failed()) {
     712           0 :         if (errorp != NULL) {
     713           0 :             *errorp = group_err;
     714             :         }
     715           0 :         return false;
     716             :     }
     717        3336 :     return true;
     718        3336 : }
     719             : 
     720       75686 : EvpnPrefix EvpnPrefix::FromString(const string &str,
     721             :     boost::system::error_code *errorp) {
     722       75686 :     EvpnPrefix prefix;
     723             : 
     724             :     // Parse type.
     725       75686 :     size_t pos1 = str.find('-');
     726       75686 :     if (pos1 == string::npos) {
     727         214 :         if (errorp != NULL) {
     728         214 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     729             :         }
     730         214 :         return EvpnPrefix::kNullPrefix;
     731             :     }
     732             : 
     733       75472 :     string type_str = str.substr(0, pos1);
     734       75472 :     bool ret = stringToInteger(type_str, prefix.type_);
     735       75472 :     if (!ret) {
     736           1 :         if (errorp != NULL) {
     737           1 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     738             :         }
     739           1 :         return EvpnPrefix::kNullPrefix;
     740             :     }
     741             : 
     742       75471 :     if (prefix.type_ < EvpnPrefix::AutoDiscoveryRoute ||
     743       75470 :         prefix.type_ > EvpnPrefix::SelectiveMulticastRoute) {
     744           1 :         if (errorp != NULL) {
     745           1 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     746             :         }
     747           1 :         return EvpnPrefix::kNullPrefix;
     748             :     }
     749             : 
     750             :     // Parse RD.
     751       75470 :     size_t pos2 = str.find('-', pos1 + 1);
     752       75470 :     if (pos2 == string::npos) {
     753           6 :         if (errorp != NULL) {
     754           6 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     755             :         }
     756           6 :         return EvpnPrefix::kNullPrefix;
     757             :     }
     758       75464 :     string rd_str = str.substr(pos1 + 1, pos2 - pos1 - 1);
     759       75464 :     boost::system::error_code rd_err;
     760       75464 :     prefix.rd_ = RouteDistinguisher::FromString(rd_str, &rd_err);
     761       75464 :     if (rd_err.failed()) {
     762           5 :         if (errorp != NULL) {
     763           5 :             *errorp = rd_err;
     764             :         }
     765           5 :         return EvpnPrefix::kNullPrefix;
     766             :     }
     767             : 
     768       75459 :     switch (prefix.type_) {
     769        3162 :     case AutoDiscoveryRoute: {
     770             :         // Parse ESI.
     771        3162 :         size_t pos3 = str.find('-', pos2 + 1);
     772        3162 :         if (pos3 == string::npos) {
     773           1 :             if (errorp != NULL) {
     774             :                 *errorp =
     775           1 :                     make_error_code(boost::system::errc::invalid_argument);
     776             :             }
     777           3 :             return EvpnPrefix::kNullPrefix;
     778             :         }
     779        3161 :         string esi_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
     780        3161 :         boost::system::error_code esi_err;
     781        3161 :         prefix.esi_ = EthernetSegmentId::FromString(esi_str, &esi_err);
     782        3161 :         if (esi_err.failed()) {
     783           1 :             if (errorp != NULL) {
     784           1 :                 *errorp = esi_err;
     785             :             }
     786           1 :             return EvpnPrefix::kNullPrefix;
     787             :         }
     788             : 
     789             :         // Parse tag.
     790        3160 :         string tag_str = str.substr(pos3 + 1, string::npos);
     791        3160 :         bool ret = stringToInteger(tag_str, prefix.tag_);
     792        3160 :         if (!ret) {
     793           1 :             if (errorp != NULL) {
     794             :                 *errorp =
     795           1 :                     make_error_code(boost::system::errc::invalid_argument);
     796             :             }
     797           1 :             return EvpnPrefix::kNullPrefix;
     798             :         }
     799             : 
     800        3159 :         break;
     801        6321 :     }
     802             : 
     803       11455 :     case MacAdvertisementRoute: {
     804             :         // Parse tag.
     805       11455 :         size_t pos3 = str.find('-', pos2 + 1);
     806       11455 :         if (pos3 == string::npos) {
     807           1 :             if (errorp != NULL) {
     808             :                 *errorp =
     809           1 :                     make_error_code(boost::system::errc::invalid_argument);
     810             :             }
     811           5 :             return EvpnPrefix::kNullPrefix;
     812             :         }
     813       11454 :         string tag_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
     814       11454 :         bool ret = stringToInteger(tag_str, prefix.tag_);
     815       11454 :         if (!ret) {
     816           1 :             if (errorp != NULL) {
     817             :                 *errorp =
     818           1 :                     make_error_code(boost::system::errc::invalid_argument);
     819             :             }
     820           1 :             return EvpnPrefix::kNullPrefix;
     821             :         }
     822             : 
     823             :         // Parse MAC.
     824       11453 :         size_t pos4 = str.rfind(',');
     825       11453 :         string mac_str = str.substr(pos3 + 1, pos4 - pos3 -1);
     826       11453 :         boost::system::error_code mac_err;
     827       11453 :         prefix.mac_addr_ = MacAddress::FromString(mac_str, &mac_err);
     828       11453 :         if (mac_err.failed()) {
     829           2 :             if (errorp != NULL) {
     830           2 :                 *errorp = mac_err;
     831             :             }
     832           2 :             return EvpnPrefix::kNullPrefix;
     833             :         }
     834             : 
     835             :         // Parse IP - treat all 0s as unspecified.
     836       11451 :         string ip_str = str.substr(pos4 + 1, string::npos);
     837       11451 :         boost::system::error_code ip_err;
     838       11451 :         prefix.ip_address_ = IpAddress::from_string(ip_str, ip_err);
     839       11451 :         if (ip_err.failed()) {
     840           1 :             if (errorp != NULL) {
     841           1 :                 *errorp = ip_err;
     842             :             }
     843           1 :             return EvpnPrefix::kNullPrefix;
     844             :         }
     845       11450 :         if (prefix.ip_address_.is_v4() && !prefix.ip_address_.is_unspecified())
     846       11326 :             prefix.family_ = Address::INET;
     847       11450 :         if (prefix.ip_address_.is_v6() && !prefix.ip_address_.is_unspecified())
     848          55 :             prefix.family_ = Address::INET6;
     849             : 
     850       11450 :         break;
     851       34358 :     }
     852             : 
     853        9269 :     case InclusiveMulticastRoute: {
     854             :         // Parse tag.
     855        9269 :         size_t pos3 = str.find('-', pos2 + 1);
     856        9269 :         if (pos3 == string::npos) {
     857           1 :             if (errorp != NULL) {
     858             :                 *errorp =
     859           1 :                     make_error_code(boost::system::errc::invalid_argument);
     860             :             }
     861           3 :             return EvpnPrefix::kNullPrefix;
     862             :         }
     863        9268 :         string tag_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
     864        9268 :         bool ret = stringToInteger(tag_str, prefix.tag_);
     865        9268 :         if (!ret) {
     866           1 :             if (errorp != NULL) {
     867             :                 *errorp =
     868           1 :                     make_error_code(boost::system::errc::invalid_argument);
     869             :             }
     870           1 :             return EvpnPrefix::kNullPrefix;
     871             :         }
     872             : 
     873             :         // Parse IP.
     874        9267 :         string ip_str = str.substr(pos3 + 1, string::npos);
     875        9267 :         boost::system::error_code ip_err;
     876        9267 :         prefix.ip_address_ = IpAddress::from_string(ip_str, ip_err);
     877        9267 :         if (ip_err.failed()) {
     878           1 :             if (errorp != NULL) {
     879           1 :                 *errorp = ip_err;
     880             :             }
     881           1 :             return EvpnPrefix::kNullPrefix;
     882             :         }
     883        9266 :         prefix.family_ =
     884        9266 :             prefix.ip_address_.is_v4() ? Address::INET : Address::INET6;
     885             : 
     886        9266 :         break;
     887       18535 :     }
     888             : 
     889        3088 :     case SegmentRoute: {
     890             :         // Parse ESI.
     891        3088 :         size_t pos3 = str.find('-', pos2 + 1);
     892        3088 :         if (pos3 == string::npos) {
     893           1 :             if (errorp != NULL) {
     894             :                 *errorp =
     895           1 :                     make_error_code(boost::system::errc::invalid_argument);
     896             :             }
     897           3 :             return EvpnPrefix::kNullPrefix;
     898             :         }
     899        3087 :         string esi_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
     900        3087 :         boost::system::error_code esi_err;
     901        3087 :         prefix.esi_ = EthernetSegmentId::FromString(esi_str, &esi_err);
     902        3087 :         if (esi_err.failed()) {
     903           1 :             if (errorp != NULL) {
     904           1 :                 *errorp = esi_err;
     905             :             }
     906           1 :             return EvpnPrefix::kNullPrefix;
     907             :         }
     908             : 
     909             :         // Parse IP.
     910        3086 :         string ip_str = str.substr(pos3 + 1, string::npos);
     911        3086 :         boost::system::error_code ip_err;
     912        3086 :         prefix.ip_address_ = IpAddress::from_string(ip_str, ip_err);
     913        3086 :         if (ip_err.failed()) {
     914           1 :             if (errorp != NULL) {
     915           1 :                 *errorp = ip_err;
     916             :             }
     917           1 :             return EvpnPrefix::kNullPrefix;
     918             :         }
     919        3085 :         prefix.family_ =
     920        3085 :             prefix.ip_address_.is_v4() ? Address::INET : Address::INET6;
     921             : 
     922        3085 :         break;
     923        6173 :     }
     924             : 
     925       45149 :     case IpPrefixRoute: {
     926             :         // Parse tag.
     927       45149 :         size_t pos3 = str.find('-', pos2 + 1);
     928       45149 :         if (pos3 == string::npos) {
     929           1 :             if (errorp != NULL) {
     930             :                 *errorp =
     931           1 :                     make_error_code(boost::system::errc::invalid_argument);
     932             :             }
     933           1 :             return EvpnPrefix::kNullPrefix;
     934             :         }
     935       45148 :         string tag_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
     936       45148 :         bool ret = stringToInteger(tag_str, prefix.tag_);
     937       45148 :         if (!ret) {
     938           2 :             if (errorp != NULL) {
     939             :                 *errorp =
     940           2 :                     make_error_code(boost::system::errc::invalid_argument);
     941             :             }
     942           2 :             return EvpnPrefix::kNullPrefix;
     943             :         }
     944             : 
     945             :         // Parse IP prefix - first try v4, then v6.
     946       45146 :         string ip_str = str.substr(pos3 + 1, string::npos);
     947       45146 :         boost::system::error_code ip_err;
     948             : 
     949       45146 :         Ip4Prefix inet_prefix = Ip4Prefix::FromString(ip_str, &ip_err);
     950       45146 :         if (!ip_err) {
     951       23102 :             prefix.family_ = Address::INET;
     952       23102 :             prefix.ip_address_ = inet_prefix.addr();
     953       23102 :             prefix.ip_prefixlen_ = inet_prefix.prefixlen();
     954       23102 :             return prefix;
     955             :         }
     956             : 
     957       22044 :         Inet6Prefix inet6_prefix = Inet6Prefix::FromString(ip_str, &ip_err);
     958       22044 :         if (!ip_err) {
     959       22030 :             prefix.family_ = Address::INET6;
     960       22030 :             prefix.ip_address_ = inet6_prefix.addr();
     961       22030 :             prefix.ip_prefixlen_ = inet6_prefix.prefixlen();
     962       22030 :             return prefix;
     963             :         }
     964             : 
     965          14 :         if (errorp != NULL) {
     966          14 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     967             :         }
     968          14 :         return EvpnPrefix::kNullPrefix;
     969             :         break;
     970       45148 :     }
     971             : 
     972        3336 :     case SelectiveMulticastRoute: {
     973             :         // Parse tag.
     974        3336 :         size_t pos3 = str.find('-', pos2 + 1);
     975        3336 :         if (pos3 == string::npos) {
     976           0 :             if (errorp != NULL) {
     977             :                 *errorp =
     978           0 :                     make_error_code(boost::system::errc::invalid_argument);
     979             :             }
     980           0 :             return EvpnPrefix::kNullPrefix;
     981             :         }
     982        3336 :         string tag_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
     983        3336 :         bool ret = stringToInteger(tag_str, prefix.tag_);
     984        3336 :         if (!ret) {
     985           0 :             if (errorp != NULL) {
     986             :                 *errorp =
     987           0 :                     make_error_code(boost::system::errc::invalid_argument);
     988             :             }
     989           0 :             return EvpnPrefix::kNullPrefix;
     990             :         }
     991             : 
     992             :         // Look for source.
     993             :         size_t pos4;
     994        3336 :         if (!GetSourceFromString(&prefix, str, pos3, &pos4, errorp))
     995           0 :             return EvpnPrefix::kNullPrefix;
     996             : 
     997             :         // Look for group.
     998             :         size_t pos5;
     999        3336 :         if (!GetGroupFromString(&prefix, str, pos4, &pos5, errorp))
    1000           0 :             return EvpnPrefix::kNullPrefix;
    1001             : 
    1002             :         // Parse IP.
    1003        3336 :         string ip_str = str.substr(pos5 + 1, string::npos);
    1004        3336 :         boost::system::error_code ip_err;
    1005        3336 :         prefix.ip_address_ = IpAddress::from_string(ip_str, ip_err);
    1006        3336 :         if (ip_err.failed()) {
    1007           0 :             if (errorp != NULL) {
    1008           0 :                 *errorp = ip_err;
    1009             :             }
    1010           0 :             return EvpnPrefix::kNullPrefix;
    1011             :         }
    1012        3336 :         prefix.family_ =
    1013        3336 :             prefix.ip_address_.is_v4() ? Address::INET : Address::INET6;
    1014             : 
    1015        3336 :         break;
    1016        6672 :     }
    1017             : 
    1018             :     }
    1019             : 
    1020       30296 :     return prefix;
    1021       75472 : }
    1022             : 
    1023       89436 : string EvpnPrefix::ToString() const {
    1024       89436 :     string str = integerToString(type_);
    1025       89439 :     str += "-" + rd_.ToString();
    1026       89436 :     switch (type_) {
    1027        1643 :     case AutoDiscoveryRoute:
    1028        1643 :         str += "-" + esi_.ToString();
    1029        1643 :         str += "-" + integerToString(tag_);
    1030        1643 :         break;
    1031       42079 :     case MacAdvertisementRoute:
    1032       42079 :         str += "-" + integerToString(tag_);
    1033       42078 :         str += "-" + mac_addr_.ToString();
    1034       42078 :         str += "," + ip_address_.to_string();
    1035       42078 :         break;
    1036        9751 :     case InclusiveMulticastRoute:
    1037        9751 :         str += "-" + integerToString(tag_);
    1038        9751 :         str += "-" + ip_address_.to_string();
    1039        9751 :         break;
    1040        1543 :     case SegmentRoute:
    1041        1543 :         str += "-" + esi_.ToString();
    1042        1543 :         str += "-" + ip_address_.to_string();
    1043        1543 :         break;
    1044       25360 :     case IpPrefixRoute:
    1045       25360 :         str += "-" + integerToString(tag_);
    1046       25362 :         if (family_ == Address::INET) {
    1047       13515 :             str += "-" + inet_prefix().ToString();
    1048             :         } else {
    1049       11847 :             str += "-" + inet6_prefix().ToString();
    1050             :         }
    1051       25362 :         break;
    1052        9060 :     case SelectiveMulticastRoute:
    1053        9060 :         str += "-" + integerToString(tag_);
    1054        9060 :         if (!source_.is_unspecified())
    1055        9055 :             str += "-" + source_.to_string();
    1056        9060 :         str += "-" + group_.to_string();
    1057        9060 :         str += "-" + ip_address_.to_string();
    1058        9058 :         break;
    1059           0 :     default:
    1060           0 :         break;
    1061             :     }
    1062             : 
    1063       89435 :     return str;
    1064           0 : }
    1065             : 
    1066        8762 : string EvpnPrefix::ToXmppIdString() const {
    1067        8762 :     string str;
    1068        8762 :     if (tag_ != 0)
    1069         200 :         str += integerToString(tag_) + "-";
    1070        8762 :     str += mac_addr_.ToString();
    1071       17526 :     str += "," + ip_address_.to_string() + "/" +
    1072       26287 :         integerToString(ip_address_length());
    1073        8762 :     if (!group_.is_unspecified()) {
    1074          72 :         str += "," + group_.to_string() + "," +
    1075         108 :             source_.to_string();
    1076             :     }
    1077        8762 :     return str;
    1078           0 : }
    1079             : 
    1080       19921 : uint8_t EvpnPrefix::ip_address_length() const {
    1081       19921 :     if (type_ == IpPrefixRoute)
    1082        2716 :         return ip_prefixlen_;
    1083       17205 :     if (family_ == Address::INET)
    1084         541 :         return 32;
    1085       16664 :     if (family_ == Address::INET6)
    1086          71 :         return 128;
    1087       16593 :     return 32;
    1088             : }
    1089             : 
    1090       28257 : size_t EvpnPrefix::GetIpAddressSize() const {
    1091       28257 :     if (family_ == Address::INET)
    1092         958 :         return kIp4AddrSize;
    1093       27299 :     if (family_ == Address::INET6)
    1094          92 :         return kIp6AddrSize;
    1095       27207 :     return 0;
    1096             : }
    1097             : 
    1098          48 : void EvpnPrefix::ReadSource(const BgpProtoPrefix &proto_prefix,
    1099             :     size_t ip_offset, size_t ip_size) {
    1100          48 :     if (ip_size == 0) {
    1101           0 :         family_ = Address::UNSPEC;
    1102          48 :     } else if (ip_size == kIp4AddrSize) {
    1103          48 :         family_ = Address::INET;
    1104          48 :         Ip4Address::bytes_type bytes = { { 0 } };
    1105          96 :         copy(proto_prefix.prefix.begin() + ip_offset,
    1106          48 :             proto_prefix.prefix.begin() + ip_offset + ip_size, bytes.begin());
    1107          48 :         source_ = Ip4Address(bytes);
    1108           0 :     } else if (ip_size == kIp6AddrSize) {
    1109           0 :         family_ = Address::INET6;
    1110           0 :         Ip6Address::bytes_type bytes = { { 0 } };
    1111           0 :         copy(proto_prefix.prefix.begin() + ip_offset,
    1112           0 :             proto_prefix.prefix.begin() + ip_offset + ip_size, bytes.begin());
    1113           0 :         source_ = Ip6Address(bytes);
    1114             :     }
    1115          48 : }
    1116             : 
    1117          48 : void EvpnPrefix::ReadGroup(const BgpProtoPrefix &proto_prefix,
    1118             :     size_t ip_offset, size_t ip_size) {
    1119          48 :     if (ip_size == 0) {
    1120           0 :         family_ = Address::UNSPEC;
    1121          48 :     } else if (ip_size == kIp4AddrSize) {
    1122          48 :         family_ = Address::INET;
    1123          48 :         Ip4Address::bytes_type bytes = { { 0 } };
    1124          96 :         copy(proto_prefix.prefix.begin() + ip_offset,
    1125          48 :             proto_prefix.prefix.begin() + ip_offset + ip_size, bytes.begin());
    1126          48 :         group_ = Ip4Address(bytes);
    1127           0 :     } else if (ip_size == kIp6AddrSize) {
    1128           0 :         family_ = Address::INET6;
    1129           0 :         Ip6Address::bytes_type bytes = { { 0 } };
    1130           0 :         copy(proto_prefix.prefix.begin() + ip_offset,
    1131           0 :             proto_prefix.prefix.begin() + ip_offset + ip_size, bytes.begin());
    1132           0 :         group_ = Ip6Address(bytes);
    1133             :     }
    1134          48 : }
    1135             : 
    1136       26246 : void EvpnPrefix::ReadIpAddress(const BgpProtoPrefix &proto_prefix,
    1137             :     size_t ip_offset, size_t ip_size, size_t ip_psize) {
    1138       26246 :     assert(ip_psize <= ip_size);
    1139       26246 :     if (ip_size == 0) {
    1140       23417 :         family_ = Address::UNSPEC;
    1141        2829 :     } else if (ip_size == kIp4AddrSize) {
    1142        2084 :         family_ = Address::INET;
    1143        2084 :         Ip4Address::bytes_type bytes = { { 0 } };
    1144        4168 :         copy(proto_prefix.prefix.begin() + ip_offset,
    1145        2084 :             proto_prefix.prefix.begin() + ip_offset + ip_psize, bytes.begin());
    1146        2084 :         ip_address_ = Ip4Address(bytes);
    1147         745 :     } else if (ip_size == kIp6AddrSize) {
    1148         745 :         family_ = Address::INET6;
    1149         745 :         Ip6Address::bytes_type bytes = { { 0 } };
    1150        1490 :         copy(proto_prefix.prefix.begin() + ip_offset,
    1151         745 :             proto_prefix.prefix.begin() + ip_offset + ip_psize, bytes.begin());
    1152         745 :         ip_address_ = Ip6Address(bytes);
    1153             :     }
    1154       26246 : }
    1155             : 
    1156       30016 : void EvpnPrefix::WriteIpAddress(BgpProtoPrefix *proto_prefix,
    1157             :                                 size_t ip_offset) const {
    1158       30016 :     if (family_ == Address::INET) {
    1159        2080 :         const Ip4Address::bytes_type &bytes = ip_address_.to_v4().to_bytes();
    1160        2080 :         copy(bytes.begin(), bytes.begin() + kIp4AddrSize,
    1161        4160 :             proto_prefix->prefix.begin() + ip_offset);
    1162       27936 :     } else if (family_ == Address::INET6) {
    1163         729 :         const Ip6Address::bytes_type &bytes = ip_address_.to_v6().to_bytes();
    1164         729 :         copy(bytes.begin(), bytes.begin() + kIp6AddrSize,
    1165        1458 :             proto_prefix->prefix.begin() + ip_offset);
    1166             :     }
    1167       30016 : }
    1168             : 
    1169          48 : void EvpnPrefix::WriteSource(BgpProtoPrefix *proto_prefix,
    1170             :                              size_t ip_offset) const {
    1171          48 :     if (family_ == Address::INET) {
    1172          48 :         const Ip4Address::bytes_type &bytes = source_.to_v4().to_bytes();
    1173          48 :         copy(bytes.begin(), bytes.begin() + kIp4AddrSize,
    1174          96 :             proto_prefix->prefix.begin() + ip_offset);
    1175           0 :     } else if (family_ == Address::INET6) {
    1176           0 :         const Ip6Address::bytes_type &bytes = source_.to_v6().to_bytes();
    1177           0 :         copy(bytes.begin(), bytes.begin() + kIp6AddrSize,
    1178           0 :             proto_prefix->prefix.begin() + ip_offset);
    1179             :     }
    1180          48 : }
    1181             : 
    1182          48 : void EvpnPrefix::WriteGroup(BgpProtoPrefix *proto_prefix,
    1183             :                             size_t ip_offset) const {
    1184          48 :     if (family_ == Address::INET) {
    1185          48 :         const Ip4Address::bytes_type &bytes = group_.to_v4().to_bytes();
    1186          48 :         copy(bytes.begin(), bytes.begin() + kIp4AddrSize,
    1187          96 :             proto_prefix->prefix.begin() + ip_offset);
    1188           0 :     } else if (family_ == Address::INET6) {
    1189           0 :         const Ip6Address::bytes_type &bytes = group_.to_v6().to_bytes();
    1190           0 :         copy(bytes.begin(), bytes.begin() + kIp6AddrSize,
    1191           0 :             proto_prefix->prefix.begin() + ip_offset);
    1192             :     }
    1193          48 : }
    1194             : 
    1195      352046 : EvpnRoute::EvpnRoute(const EvpnPrefix &prefix)
    1196      352046 :     : prefix_(prefix) {
    1197      351968 : }
    1198             : 
    1199     2713556 : int EvpnRoute::CompareTo(const Route &rhs) const {
    1200     2713556 :     const EvpnRoute &evpn_rhs = static_cast<const EvpnRoute &>(rhs);
    1201     2713556 :     return prefix_.CompareTo(evpn_rhs.prefix_);
    1202             : }
    1203             : 
    1204       88032 : string EvpnRoute::ToString() const {
    1205       88032 :     return prefix_.ToString();
    1206             : }
    1207             : 
    1208       12511 : string EvpnRoute::ToXmppIdString() const {
    1209       12511 :     if (xmpp_id_str_.empty())
    1210        4302 :         xmpp_id_str_ = prefix_.ToXmppIdString();
    1211       12511 :     return xmpp_id_str_;
    1212             : }
    1213             : 
    1214       55319 : bool EvpnRoute::IsValid() const {
    1215       55319 :     if (!BgpRoute::IsValid())
    1216        8368 :         return false;
    1217             : 
    1218       46951 :     const BgpAttr *attr = BestPath()->GetAttr();
    1219       46951 :     switch (prefix_.type()) {
    1220          56 :     case EvpnPrefix::AutoDiscoveryRoute: {
    1221          56 :         if (prefix_.tag() == EvpnPrefix::kMaxTag)
    1222          56 :             return true;
    1223           0 :         break;
    1224             :     }
    1225       25961 :     case EvpnPrefix::MacAdvertisementRoute: {
    1226       25961 :         return true;
    1227             :     }
    1228       20934 :     case EvpnPrefix::InclusiveMulticastRoute: {
    1229       20934 :         const PmsiTunnel *pmsi_tunnel = attr->pmsi_tunnel();
    1230       20934 :         if (!pmsi_tunnel)
    1231           0 :             return false;
    1232       20934 :         uint8_t tunnel_type = pmsi_tunnel->tunnel_type();
    1233       20934 :         uint8_t tunnel_flags = pmsi_tunnel->tunnel_flags();
    1234       20934 :         uint8_t ar_type =
    1235             :             tunnel_flags & PmsiTunnelSpec::AssistedReplicationType;
    1236       20934 :         if (tunnel_type == PmsiTunnelSpec::IngressReplication) {
    1237       20276 :             if (ar_type == PmsiTunnelSpec::RegularNVE)
    1238       18544 :                 return true;
    1239        1732 :             if (ar_type == PmsiTunnelSpec::ARReplicator &&
    1240        1732 :                 (tunnel_flags & PmsiTunnelSpec::LeafInfoRequired)) {
    1241        1732 :                 return true;
    1242             :             }
    1243           0 :             return false;
    1244             :         }
    1245         658 :         if (tunnel_type == PmsiTunnelSpec::AssistedReplicationContrail &&
    1246             :             ar_type == PmsiTunnelSpec::ARLeaf) {
    1247         658 :             return true;
    1248             :         }
    1249           0 :         return false;
    1250             :     }
    1251           0 :     case EvpnPrefix::SegmentRoute: {
    1252           0 :         return false;
    1253             :     }
    1254           0 :     case EvpnPrefix::IpPrefixRoute: {
    1255           0 :         return false;
    1256             :     }
    1257           0 :     case EvpnPrefix::SelectiveMulticastRoute: {
    1258           0 :         return false;
    1259             :     }
    1260           0 :     default: {
    1261           0 :         break;
    1262             :     }
    1263             :     }
    1264             : 
    1265           0 :     return false;
    1266             : }
    1267             : 
    1268          25 : void EvpnRoute::SetKey(const DBRequestKey *reqkey) {
    1269          25 :     const EvpnTable::RequestKey *key =
    1270             :         static_cast<const EvpnTable::RequestKey *>(reqkey);
    1271          25 :     prefix_ = key->prefix;
    1272          25 : }
    1273             : 
    1274       29829 : void EvpnRoute::BuildProtoPrefix(BgpProtoPrefix *proto_prefix,
    1275             :     const BgpAttr *attr, uint32_t label, uint32_t l3_label) const {
    1276       29829 :     prefix_.BuildProtoPrefix(proto_prefix, attr, label, l3_label);
    1277       29827 : }
    1278             : 
    1279       13016 : void EvpnRoute::BuildBgpProtoNextHop(vector<uint8_t> &nh,
    1280             :         IpAddress nexthop) const {
    1281       13016 :     nh.resize(4);
    1282       13015 :     const Ip4Address::bytes_type &addr_bytes = nexthop.to_v4().to_bytes();
    1283       13015 :     copy(addr_bytes.begin(), addr_bytes.end(), nh.begin());
    1284       13015 : }
    1285             : 
    1286       51289 : DBEntryBase::KeyPtr EvpnRoute::GetDBRequestKey() const {
    1287       51289 :     EvpnTable::RequestKey *key = new EvpnTable::RequestKey(GetPrefix(), NULL);
    1288       51285 :     return KeyPtr(key);
    1289             : }

Generated by: LCOV version 1.14