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

Generated by: LCOV version 1.14