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: 6 925 0.6 %
Date: 2026-09-21 02:11:39 Functions: 1 37 2.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include "bgp/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           0 : static uint32_t ReadLabel(const BgpProtoPrefix &proto_prefix,
      58             :     const BgpAttr *attr, size_t offset, uint32_t tag = EvpnPrefix::kNullTag) {
      59           0 :     if (!attr)
      60           0 :         return 0;
      61           0 :     const ExtCommunity *extcomm = attr->ext_community();
      62           0 :     if (extcomm && extcomm->ContainsTunnelEncapVxlan()) {
      63           0 :         if (tag) {
      64           0 :             if (tag == EvpnPrefix::kMaxTag) {
      65           0 :                 return 0;
      66           0 :             } else if (tag <= EvpnPrefix::kMaxVni) {
      67           0 :                 return tag;
      68             :             } else {
      69           0 :                 return proto_prefix.ReadLabel(offset, true);
      70             :             }
      71             :         } else {
      72           0 :             return proto_prefix.ReadLabel(offset, true);
      73             :         }
      74             :     } else {
      75           0 :         return proto_prefix.ReadLabel(offset, false);
      76             :     }
      77             : }
      78             : 
      79             : //
      80             : // Write label to the BgpProtoPrefix.
      81             : //
      82           0 : static void WriteLabel(BgpProtoPrefix *proto_prefix,
      83             :     const BgpAttr *attr, size_t offset, uint32_t label) {
      84           0 :     const ExtCommunity *extcomm = attr ? attr->ext_community() : NULL;
      85           0 :     if (extcomm && extcomm->ContainsTunnelEncapVxlan()) {
      86           0 :         proto_prefix->WriteLabel(offset, label, true);
      87             :     } else {
      88           0 :         proto_prefix->WriteLabel(offset, label, false);
      89             :     }
      90           0 : }
      91             : 
      92             : //
      93             : // Read gateway address from the BgpProtoPrefix.
      94             : //
      95           0 : static IpAddress ReadGwAddress(const BgpProtoPrefix &proto_prefix,
      96             :     size_t gw_offset, size_t ip_size) {
      97           0 :     assert(ip_size == EvpnPrefix::kIp4AddrSize ||
      98             :         ip_size == EvpnPrefix::kIp6AddrSize);
      99           0 :     if (ip_size == EvpnPrefix::kIp4AddrSize) {
     100             :         Ip4Address::bytes_type bytes;
     101           0 :         copy(proto_prefix.prefix.begin() + gw_offset,
     102           0 :             proto_prefix.prefix.begin() + gw_offset + ip_size, bytes.begin());
     103           0 :         return Ip4Address(bytes);
     104             :     } else {
     105             :         Ip6Address::bytes_type bytes;
     106           0 :         copy(proto_prefix.prefix.begin() + gw_offset,
     107           0 :             proto_prefix.prefix.begin() + gw_offset + ip_size, bytes.begin());
     108           0 :         return Ip6Address(bytes);
     109             :     }
     110             :     return IpAddress();
     111             : }
     112             : 
     113           1 : EvpnPrefix::EvpnPrefix()
     114           1 :     : type_(Unspecified),
     115           1 :       tag_(EvpnPrefix::kNullTag),
     116           1 :       family_(Address::UNSPEC),
     117           1 :       ip_prefixlen_(0) {
     118           1 : }
     119             : 
     120           0 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd,
     121           0 :     const EthernetSegmentId &esi, uint32_t tag)
     122           0 :     : type_(AutoDiscoveryRoute),
     123           0 :       rd_(rd),
     124           0 :       esi_(esi),
     125           0 :       tag_(tag),
     126           0 :       family_(Address::UNSPEC),
     127           0 :       ip_prefixlen_(0) {
     128           0 : }
     129             : 
     130           0 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd,
     131           0 :     const MacAddress &mac_addr, const IpAddress &ip_address)
     132           0 :     : type_(MacAdvertisementRoute),
     133           0 :       rd_(rd),
     134           0 :       tag_(EvpnPrefix::kNullTag),
     135           0 :       mac_addr_(mac_addr),
     136           0 :       family_(Address::UNSPEC),
     137           0 :       ip_address_(ip_address),
     138           0 :       ip_prefixlen_(0) {
     139           0 :     if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
     140           0 :         family_ = Address::INET;
     141           0 :     } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
     142           0 :         family_ = Address::INET6;
     143             :     }
     144           0 : }
     145             : 
     146           0 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, uint32_t tag,
     147           0 :     const MacAddress &mac_addr, const IpAddress &ip_address)
     148           0 :     : type_(MacAdvertisementRoute), rd_(rd), tag_(tag),
     149           0 :       mac_addr_(mac_addr), family_(Address::UNSPEC),
     150           0 :       ip_address_(ip_address), ip_prefixlen_(0) {
     151           0 :     if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
     152           0 :         family_ = Address::INET;
     153           0 :     } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
     154           0 :         family_ = Address::INET6;
     155             :     }
     156           0 : }
     157             : 
     158           0 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, uint32_t tag,
     159           0 :     const IpAddress &ip_address)
     160           0 :     : type_(InclusiveMulticastRoute),
     161           0 :       rd_(rd),
     162           0 :       tag_(tag),
     163           0 :       family_(Address::UNSPEC),
     164           0 :       ip_address_(ip_address),
     165           0 :       ip_prefixlen_(0) {
     166           0 :     if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
     167           0 :         family_ = Address::INET;
     168           0 :     } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
     169           0 :         family_ = Address::INET6;
     170             :     }
     171           0 : }
     172             : 
     173           0 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd,
     174           0 :     const EthernetSegmentId &esi, const IpAddress &ip_address)
     175           0 :     : type_(SegmentRoute),
     176           0 :       rd_(rd),
     177           0 :       esi_(esi),
     178           0 :       tag_(EvpnPrefix::kNullTag),
     179           0 :       family_(Address::UNSPEC),
     180           0 :       ip_address_(ip_address),
     181           0 :       ip_prefixlen_(0) {
     182           0 :     if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
     183           0 :         family_ = Address::INET;
     184           0 :     } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
     185           0 :         family_ = Address::INET6;
     186             :     }
     187           0 : }
     188             : 
     189           0 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd,
     190           0 :     const IpAddress &ip_address, uint8_t ip_prefixlen)
     191           0 :     : type_(IpPrefixRoute),
     192           0 :       rd_(rd),
     193           0 :       tag_(0),
     194           0 :       family_(Address::UNSPEC),
     195           0 :       ip_address_(ip_address),
     196           0 :       ip_prefixlen_(ip_prefixlen) {
     197           0 :     assert(ip_address_.is_v4() || ip_address_.is_v6());
     198           0 :     if (ip_address_.is_v4()) {
     199           0 :         family_ = Address::INET;
     200           0 :     } else if (ip_address_.is_v6()) {
     201           0 :         family_ = Address::INET6;
     202             :     }
     203           0 : }
     204             : 
     205           0 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, uint32_t tag,
     206             :     const IpAddress &source, const IpAddress &group,
     207           0 :     const IpAddress &ip_address)
     208           0 :     : type_(SelectiveMulticastRoute),
     209           0 :       rd_(rd),
     210           0 :       tag_(tag),
     211           0 :       family_(Address::UNSPEC),
     212           0 :       ip_address_(ip_address),
     213           0 :       source_(source),
     214           0 :       group_(group),
     215           0 :       ip_prefixlen_(0), flags_(0x2) {
     216           0 :     if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
     217           0 :         family_ = Address::INET;
     218           0 :     } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
     219           0 :         family_ = Address::INET6;
     220             :     }
     221           0 :     string ip = group.to_v4().to_string();
     222           0 :     char *str = const_cast<char *>(ip.c_str());
     223           0 :     char * mac_ip = strstr(str, ".");
     224           0 :     std::ostringstream oss;
     225           0 :     oss << "01:00:5e:" << strtok(mac_ip, "."); 
     226           0 :     oss << ":" << strtok(NULL, ".");
     227           0 :     oss << ":" << strtok(NULL, "");
     228           0 :     mac_addr_ = MacAddress::FromString(oss.str(), NULL);
     229           0 : }
     230             : 
     231           0 : 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           0 :     *new_attr = attr;
     236           0 :     *label = 0;
     237           0 :     if (l3_label)
     238           0 :         *l3_label = 0;
     239           0 :     prefix->type_ = proto_prefix.type;
     240           0 :     size_t nlri_size = proto_prefix.prefix.size();
     241             : 
     242           0 :     switch (prefix->type_) {
     243           0 :     case AutoDiscoveryRoute: {
     244           0 :         size_t expected_min_nlri_size =
     245           0 :             kMinAutoDiscoveryRouteSize + (attr ? kLabelSize : 0);
     246           0 :         if (nlri_size < expected_min_nlri_size)
     247           0 :             return -1;
     248           0 :         size_t rd_offset = 0;
     249           0 :         prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
     250           0 :         size_t esi_offset = rd_offset + kRdSize;
     251           0 :         prefix->esi_ = EthernetSegmentId(&proto_prefix.prefix[esi_offset]);
     252           0 :         size_t tag_offset = esi_offset + kEsiSize;
     253           0 :         prefix->tag_ = get_value(&proto_prefix.prefix[tag_offset], kTagSize);
     254           0 :         size_t label_offset = tag_offset + kTagSize;
     255           0 :         *label = ReadLabel(proto_prefix, attr, label_offset, prefix->tag_);
     256           0 :         break;
     257             :     }
     258           0 :     case MacAdvertisementRoute: {
     259           0 :         size_t expected_min_nlri_size =
     260           0 :             kMinMacAdvertisementRouteSize + (attr ? kLabelSize : 0);
     261           0 :         if (nlri_size < expected_min_nlri_size)
     262           0 :             return -1;
     263           0 :         size_t rd_offset = 0;
     264           0 :         prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
     265           0 :         size_t esi_offset = rd_offset + kRdSize;
     266           0 :         if (attr) {
     267           0 :             EthernetSegmentId esi(&proto_prefix.prefix[esi_offset]);
     268           0 :             *new_attr = server->attr_db()->ReplaceEsiAndLocate(attr, esi);
     269             :         }
     270           0 :         size_t tag_offset = esi_offset + kEsiSize;
     271           0 :         prefix->tag_ = get_value(&proto_prefix.prefix[tag_offset], kTagSize);
     272           0 :         size_t mac_len_offset = tag_offset + kTagSize;
     273           0 :         size_t mac_len = proto_prefix.prefix[mac_len_offset];
     274           0 :         if (mac_len != 48)
     275           0 :             return -1;
     276           0 :         size_t mac_offset = mac_len_offset + 1;
     277           0 :         prefix->mac_addr_ = MacAddress(&proto_prefix.prefix[mac_offset]);
     278           0 :         size_t ip_len_offset = mac_offset + kMacSize;
     279           0 :         size_t ip_len = proto_prefix.prefix[ip_len_offset];
     280           0 :         if (ip_len != 0 && ip_len != 32 && ip_len != 128)
     281           0 :             return -1;
     282           0 :         size_t ip_size = ip_len / 8;
     283           0 :         if (nlri_size < expected_min_nlri_size + ip_size)
     284           0 :             return -1;
     285           0 :         size_t ip_offset = ip_len_offset + 1;
     286           0 :         prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_size);
     287           0 :         size_t label_offset = ip_offset + ip_size;
     288           0 :         *label = ReadLabel(proto_prefix, attr, label_offset, prefix->tag_);
     289           0 :         size_t l3_label_offset = label_offset + kLabelSize;
     290           0 :         if (l3_label && nlri_size >= l3_label_offset + kLabelSize) {
     291           0 :             *l3_label = ReadLabel(proto_prefix, attr, l3_label_offset);
     292             :         }
     293           0 :         break;
     294             :     }
     295           0 :     case InclusiveMulticastRoute: {
     296           0 :         if (nlri_size < kMinInclusiveMulticastRouteSize)
     297           0 :             return -1;
     298           0 :         size_t rd_offset = 0;
     299           0 :         prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
     300           0 :         size_t tag_offset = rd_offset + kRdSize;
     301           0 :         prefix->tag_ = get_value(&proto_prefix.prefix[tag_offset], kTagSize);
     302           0 :         size_t ip_len_offset = tag_offset + kTagSize;
     303           0 :         size_t ip_len = proto_prefix.prefix[ip_len_offset];
     304           0 :         if (ip_len != 32 && ip_len != 128)
     305           0 :             return -1;
     306           0 :         size_t ip_size = ip_len / 8;
     307           0 :         if (nlri_size < kMinInclusiveMulticastRouteSize + ip_size)
     308           0 :             return -1;
     309           0 :         size_t ip_offset = ip_len_offset + 1;
     310           0 :         prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_size);
     311           0 :         const PmsiTunnel *pmsi_tunnel = attr ? attr->pmsi_tunnel() : NULL;
     312           0 :         if (pmsi_tunnel &&
     313           0 :             (pmsi_tunnel->tunnel_type() == PmsiTunnelSpec::IngressReplication ||
     314           0 :              pmsi_tunnel->tunnel_type() ==
     315             :              PmsiTunnelSpec::AssistedReplicationContrail)) {
     316           0 :             const ExtCommunity *extcomm = attr ? attr->ext_community() : NULL;
     317           0 :             if (extcomm && extcomm->ContainsTunnelEncapVxlan()) {
     318           0 :                 if (prefix->tag_ && prefix->tag_ <= kMaxVni) {
     319           0 :                     *label = prefix->tag_;
     320             :                 } else {
     321           0 :                     *label = pmsi_tunnel->GetLabel(extcomm);
     322             :                 }
     323             :             } else {
     324           0 :                 *label = pmsi_tunnel->GetLabel(extcomm);
     325             :             }
     326             :         }
     327           0 :         break;
     328             :     }
     329           0 :     case SegmentRoute: {
     330           0 :         if (nlri_size < kMinSegmentRouteSize)
     331           0 :             return -1;
     332           0 :         size_t rd_offset = 0;
     333           0 :         prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
     334           0 :         size_t esi_offset = rd_offset + kRdSize;
     335           0 :         prefix->esi_ = EthernetSegmentId(&proto_prefix.prefix[esi_offset]);
     336           0 :         size_t ip_len_offset = esi_offset + kEsiSize;
     337           0 :         size_t ip_len = proto_prefix.prefix[ip_len_offset];
     338           0 :         if (ip_len != 32 && ip_len != 128)
     339           0 :             return -1;
     340           0 :         size_t ip_size = ip_len / 8;
     341           0 :         if (nlri_size < kMinSegmentRouteSize + ip_size)
     342           0 :             return -1;
     343           0 :         size_t ip_offset = ip_len_offset + 1;
     344           0 :         prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_size);
     345           0 :         break;
     346             :     }
     347           0 :     case IpPrefixRoute: {
     348             :         size_t ip_size;
     349           0 :         if (attr) {
     350           0 :             if (nlri_size == kMinInet6PrefixRouteSize + kLabelSize) {
     351           0 :                 ip_size = kIp6AddrSize;
     352           0 :             } else if (nlri_size == kMinInetPrefixRouteSize + kLabelSize) {
     353           0 :                 ip_size = kIp4AddrSize;
     354             :             } else {
     355           0 :                 return -1;
     356             :             }
     357             :         } else {
     358           0 :             if (nlri_size == kMinInet6PrefixRouteSize ||
     359           0 :                 nlri_size == kMinInet6PrefixRouteSize + kLabelSize) {
     360           0 :                 ip_size = kIp6AddrSize;
     361           0 :             } else if (nlri_size == kMinInetPrefixRouteSize ||
     362           0 :                 nlri_size == kMinInetPrefixRouteSize + kLabelSize) {
     363           0 :                 ip_size = kIp4AddrSize;
     364             :             } else {
     365           0 :                 return -1;
     366             :             }
     367             :         }
     368             : 
     369           0 :         size_t rd_offset = 0;
     370           0 :         prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
     371           0 :         size_t esi_offset = rd_offset + kRdSize;
     372           0 :         EthernetSegmentId esi(&proto_prefix.prefix[esi_offset]);
     373           0 :         if (!esi.IsZero())
     374           0 :             return -1;
     375           0 :         size_t tag_offset = esi_offset + kEsiSize;
     376             :         // Ignore tag for type5 routes.
     377           0 :         prefix->tag_ = 0;
     378           0 :         size_t ip_plen_offset = tag_offset + kTagSize;
     379           0 :         prefix->ip_prefixlen_ = proto_prefix.prefix[ip_plen_offset];
     380           0 :         if (ip_size == kIp4AddrSize && prefix->ip_prefixlen_ > 32)
     381           0 :             return -1;
     382           0 :         if (ip_size == kIp6AddrSize && prefix->ip_prefixlen_ > 128)
     383           0 :             return -1;
     384           0 :         size_t ip_offset = ip_plen_offset + 1;
     385           0 :         size_t ip_psize = (prefix->ip_prefixlen_ + 7) / 8;
     386           0 :         prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_psize);
     387           0 :         size_t gw_offset = ip_offset + ip_size;
     388           0 :         IpAddress gw_address = ReadGwAddress(proto_prefix, gw_offset, ip_size);
     389           0 :         if (!gw_address.is_unspecified())
     390           0 :             return -1;
     391           0 :         size_t label_offset = gw_offset + ip_size;
     392           0 :         *label = ReadLabel(proto_prefix, attr, label_offset);
     393           0 :         break;
     394             :     }
     395           0 :     case SelectiveMulticastRoute: {
     396           0 :         if (nlri_size < kMinSelectiveMulticastRouteSize)
     397           0 :             return -1;
     398           0 :         size_t rd_offset = 0;
     399           0 :         prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
     400           0 :         size_t tag_offset = rd_offset + kRdSize;
     401           0 :         prefix->tag_ = get_value(&proto_prefix.prefix[tag_offset], kTagSize);
     402           0 :         size_t src_len_offset = tag_offset + kTagSize;
     403           0 :         size_t src_len = proto_prefix.prefix[src_len_offset];
     404           0 :         if (src_len != 32 && src_len != 128 && src_len != 0)
     405           0 :             return -1;
     406           0 :         size_t src_size = src_len / 8;
     407           0 :         size_t src_offset = src_len_offset + 1;
     408           0 :         if (src_size > 0) {
     409           0 :             if (nlri_size < src_offset + src_size)
     410           0 :                 return -1;
     411           0 :             prefix->ReadSource(proto_prefix, src_offset, src_size);
     412             :         }
     413           0 :         size_t grp_len_offset = src_offset + src_size;
     414           0 :         size_t grp_len = proto_prefix.prefix[grp_len_offset];
     415           0 :         if (grp_len != 32 && grp_len != 128)
     416           0 :             return -1;
     417           0 :         size_t grp_size = grp_len / 8;
     418           0 :         size_t grp_offset = grp_len_offset + 1;
     419           0 :         if (nlri_size < grp_offset + grp_size)
     420           0 :             return -1;
     421           0 :         prefix->ReadGroup(proto_prefix, grp_offset, grp_size);
     422           0 :         size_t ip_len_offset = grp_offset + grp_size;
     423           0 :         size_t ip_len = proto_prefix.prefix[ip_len_offset];
     424           0 :         if (ip_len != 32 && ip_len != 128)
     425           0 :             return -1;
     426           0 :         size_t ip_size = ip_len / 8;
     427           0 :         size_t ip_offset = ip_len_offset + 1;
     428           0 :         if (nlri_size < ip_offset + ip_size)
     429           0 :             return -1;
     430           0 :         prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_size);
     431           0 :         size_t flag_offset = ip_offset + ip_size;
     432           0 :         if (nlri_size <= flag_offset + 4)
     433           0 :             prefix->flags_ = get_value(&proto_prefix.prefix[flag_offset], 4);
     434           0 :         break;
     435             :     }
     436           0 :     default: {
     437           0 :         return -1;
     438             :         break;
     439             :     }
     440             :     }
     441           0 :     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           0 : void EvpnPrefix::BuildProtoPrefix(BgpProtoPrefix *proto_prefix,
     452             :     const BgpAttr *attr, uint32_t label, uint32_t l3_label) const {
     453           0 :     proto_prefix->type = type_;
     454           0 :     proto_prefix->prefix.clear();
     455             : 
     456           0 :     switch (type_) {
     457           0 :     case AutoDiscoveryRoute: {
     458           0 :         size_t nlri_size = kMinAutoDiscoveryRouteSize + kLabelSize;
     459           0 :         proto_prefix->prefixlen = nlri_size * 8;
     460           0 :         proto_prefix->prefix.resize(nlri_size, 0);
     461             : 
     462           0 :         size_t rd_offset = 0;
     463           0 :         copy(rd_.GetData(), rd_.GetData() + kRdSize,
     464           0 :             proto_prefix->prefix.begin() + rd_offset);
     465           0 :         size_t esi_offset = rd_offset + kRdSize;
     466           0 :         copy(esi_.GetData(), esi_.GetData() + kEsiSize,
     467           0 :             proto_prefix->prefix.begin() + esi_offset);
     468           0 :         size_t tag_offset = esi_offset + kEsiSize;
     469           0 :         put_value(&proto_prefix->prefix[tag_offset], kTagSize, tag_);
     470           0 :         size_t label_offset = tag_offset + kTagSize;
     471           0 :         WriteLabel(proto_prefix, attr, label_offset, label);
     472           0 :         break;
     473             :     }
     474           0 :     case MacAdvertisementRoute: {
     475           0 :         size_t ip_size = GetIpAddressSize();
     476           0 :         size_t nlri_size = kMinMacAdvertisementRouteSize + ip_size + kLabelSize;
     477           0 :         if (l3_label)
     478           0 :             nlri_size += kLabelSize;
     479           0 :         proto_prefix->prefixlen = nlri_size * 8;
     480           0 :         proto_prefix->prefix.resize(nlri_size, 0);
     481             : 
     482           0 :         size_t rd_offset = 0;
     483           0 :         copy(rd_.GetData(), rd_.GetData() + kRdSize,
     484           0 :             proto_prefix->prefix.begin() + rd_offset);
     485           0 :         size_t esi_offset = rd_offset + kRdSize;
     486           0 :         if (attr) {
     487           0 :             copy(attr->esi().GetData(), attr->esi().GetData() + kEsiSize,
     488           0 :                 proto_prefix->prefix.begin() + esi_offset);
     489             :         }
     490           0 :         size_t tag_offset = esi_offset + kEsiSize;
     491           0 :         put_value(&proto_prefix->prefix[tag_offset], kTagSize, tag_);
     492           0 :         size_t mac_len_offset = tag_offset + kTagSize;
     493           0 :         proto_prefix->prefix[mac_len_offset] = 48;
     494           0 :         size_t mac_offset = mac_len_offset + 1;
     495           0 :         copy(mac_addr_.GetData(), mac_addr_.GetData() + kMacSize,
     496           0 :             proto_prefix->prefix.begin() + mac_offset);
     497           0 :         size_t ip_len_offset = mac_offset + kMacSize;
     498           0 :         proto_prefix->prefix[ip_len_offset] = ip_size * 8;
     499           0 :         size_t ip_offset = ip_len_offset + 1;
     500           0 :         WriteIpAddress(proto_prefix, ip_offset);
     501           0 :         size_t label_offset = ip_offset + ip_size;
     502           0 :         WriteLabel(proto_prefix, attr, label_offset, label);
     503           0 :         if (l3_label) {
     504           0 :             size_t l3_label_offset = label_offset + kLabelSize;
     505           0 :             WriteLabel(proto_prefix, attr, l3_label_offset, l3_label);
     506             :         }
     507           0 :         break;
     508             :     }
     509           0 :     case InclusiveMulticastRoute: {
     510           0 :         size_t ip_size = GetIpAddressSize();
     511           0 :         size_t nlri_size = kMinInclusiveMulticastRouteSize + ip_size;
     512           0 :         proto_prefix->prefixlen = nlri_size * 8;
     513           0 :         proto_prefix->prefix.resize(nlri_size, 0);
     514             : 
     515           0 :         size_t rd_offset = 0;
     516           0 :         copy(rd_.GetData(), rd_.GetData() + kRdSize,
     517           0 :             proto_prefix->prefix.begin() + rd_offset);
     518           0 :         size_t tag_offset = rd_offset + kRdSize;
     519           0 :         put_value(&proto_prefix->prefix[tag_offset], kTagSize, tag_);
     520           0 :         size_t ip_len_offset = tag_offset + kTagSize;
     521           0 :         proto_prefix->prefix[ip_len_offset] = ip_size * 8;
     522           0 :         size_t ip_offset = ip_len_offset + 1;
     523           0 :         WriteIpAddress(proto_prefix, ip_offset);
     524           0 :         break;
     525             :     }
     526           0 :     case SegmentRoute: {
     527           0 :         size_t ip_size = GetIpAddressSize();
     528           0 :         size_t nlri_size = kMinSegmentRouteSize + ip_size;
     529           0 :         proto_prefix->prefixlen = nlri_size * 8;
     530           0 :         proto_prefix->prefix.resize(nlri_size, 0);
     531             : 
     532           0 :         size_t rd_offset = 0;
     533           0 :         copy(rd_.GetData(), rd_.GetData() + kRdSize,
     534           0 :             proto_prefix->prefix.begin() + rd_offset);
     535           0 :         size_t esi_offset = rd_offset + kRdSize;
     536           0 :         copy(esi_.GetData(), esi_.GetData() + kEsiSize,
     537           0 :             proto_prefix->prefix.begin() + esi_offset);
     538           0 :         size_t ip_len_offset = esi_offset + kEsiSize;
     539           0 :         proto_prefix->prefix[ip_len_offset] = ip_size * 8;
     540           0 :         size_t ip_offset = ip_len_offset + 1;
     541           0 :         WriteIpAddress(proto_prefix, ip_offset);
     542           0 :         break;
     543             :     }
     544           0 :     case IpPrefixRoute: {
     545             :         size_t ip_size, nlri_size;
     546           0 :         if (family_ == Address::INET) {
     547           0 :             ip_size = kIp4AddrSize;
     548           0 :             nlri_size = kMinInetPrefixRouteSize + kLabelSize;
     549             :         } else {
     550           0 :             ip_size = kIp6AddrSize;
     551           0 :             nlri_size = kMinInet6PrefixRouteSize + kLabelSize;
     552             :         }
     553           0 :         proto_prefix->prefixlen = nlri_size * 8;
     554           0 :         proto_prefix->prefix.resize(nlri_size, 0);
     555             : 
     556           0 :         size_t rd_offset = 0;
     557           0 :         copy(rd_.GetData(), rd_.GetData() + kRdSize,
     558           0 :             proto_prefix->prefix.begin() + rd_offset);
     559           0 :         size_t esi_offset = rd_offset + kRdSize;
     560           0 :         if (attr) {
     561           0 :             copy(attr->esi().GetData(), attr->esi().GetData() + kEsiSize,
     562           0 :                 proto_prefix->prefix.begin() + esi_offset);
     563             :         }
     564           0 :         size_t tag_offset = esi_offset + kEsiSize;
     565             :         // Tag is not applicable for type5 routes.
     566           0 :         put_value(&proto_prefix->prefix[tag_offset], kTagSize, 0);
     567           0 :         size_t ip_plen_offset = tag_offset + kTagSize;
     568           0 :         proto_prefix->prefix[ip_plen_offset] = ip_prefixlen_;
     569           0 :         size_t ip_offset = ip_plen_offset + 1;
     570           0 :         WriteIpAddress(proto_prefix, ip_offset);
     571           0 :         size_t gw_offset = ip_offset + ip_size;
     572           0 :         size_t label_offset = gw_offset + ip_size;
     573           0 :         WriteLabel(proto_prefix, attr, label_offset, label);
     574           0 :         break;
     575             :     }
     576           0 :     case SelectiveMulticastRoute: {
     577           0 :         size_t ip_size = GetIpAddressSize();
     578           0 :         size_t nlri_size = kMinSelectiveMulticastRouteSize + 2 * ip_size + 1;
     579           0 :         if (!source_.is_unspecified())
     580           0 :             nlri_size += ip_size;
     581           0 :         proto_prefix->prefixlen = nlri_size * 8;
     582           0 :         proto_prefix->prefix.resize(nlri_size, 0);
     583             : 
     584           0 :         size_t rd_offset = 0;
     585           0 :         copy(rd_.GetData(), rd_.GetData() + kRdSize,
     586           0 :             proto_prefix->prefix.begin() + rd_offset);
     587           0 :         size_t tag_offset = rd_offset + kRdSize;
     588           0 :         put_value(&proto_prefix->prefix[tag_offset], kTagSize, tag_);
     589           0 :         size_t src_len_offset = tag_offset + kTagSize;
     590           0 :         size_t grp_len_offset = src_len_offset + 1;
     591           0 :         if (source_.is_unspecified()) {
     592           0 :             proto_prefix->prefix[src_len_offset] = 0;
     593             :         } else {
     594           0 :             proto_prefix->prefix[src_len_offset] = ip_size * 8;
     595           0 :             size_t src_offset = src_len_offset + 1;
     596           0 :             WriteSource(proto_prefix, src_offset);
     597           0 :             grp_len_offset += ip_size;
     598             :         }
     599           0 :         proto_prefix->prefix[grp_len_offset] = ip_size * 8;
     600           0 :         size_t grp_offset = grp_len_offset + 1;
     601           0 :         WriteGroup(proto_prefix, grp_offset);
     602           0 :         size_t ip_len_offset = grp_offset + ip_size;
     603           0 :         proto_prefix->prefix[ip_len_offset] = ip_size * 8;
     604           0 :         size_t ip_offset = ip_len_offset + 1;
     605           0 :         WriteIpAddress(proto_prefix, ip_offset);
     606           0 :         size_t flag_offset = ip_offset + ip_size;
     607           0 :         put_value(&proto_prefix->prefix[flag_offset], 1, flags_);
     608           0 :         break;
     609             :     }
     610           0 :     default: {
     611           0 :         assert(false);
     612             :         break;
     613             :     }
     614             :     }
     615           0 : }
     616             : 
     617           0 : int EvpnPrefix::CompareTo(const EvpnPrefix &rhs) const {
     618           0 :     KEY_COMPARE(type_, rhs.type_);
     619             : 
     620           0 :     switch (type_) {
     621           0 :     case AutoDiscoveryRoute:
     622           0 :         KEY_COMPARE(rd_, rhs.rd_);
     623           0 :         KEY_COMPARE(esi_, rhs.esi_);
     624           0 :         KEY_COMPARE(tag_, rhs.tag_);
     625           0 :         break;
     626           0 :     case MacAdvertisementRoute:
     627           0 :         KEY_COMPARE(rd_, rhs.rd_);
     628           0 :         KEY_COMPARE(tag_, rhs.tag_);
     629           0 :         KEY_COMPARE(mac_addr_, rhs.mac_addr_);
     630           0 :         KEY_COMPARE(ip_address_, rhs.ip_address_);
     631           0 :         break;
     632           0 :     case InclusiveMulticastRoute:
     633           0 :         KEY_COMPARE(rd_, rhs.rd_);
     634           0 :         KEY_COMPARE(tag_, rhs.tag_);
     635           0 :         KEY_COMPARE(ip_address_, rhs.ip_address_);
     636           0 :         break;
     637           0 :     case SegmentRoute:
     638           0 :         KEY_COMPARE(rd_, rhs.rd_);
     639           0 :         KEY_COMPARE(esi_, rhs.esi_);
     640           0 :         KEY_COMPARE(ip_address_, rhs.ip_address_);
     641           0 :         break;
     642           0 :     case IpPrefixRoute:
     643           0 :         KEY_COMPARE(rd_, rhs.rd_);
     644           0 :         KEY_COMPARE(tag_, rhs.tag_);
     645           0 :         KEY_COMPARE(ip_address_, rhs.ip_address_);
     646           0 :         KEY_COMPARE(ip_prefixlen_, rhs.ip_prefixlen_);
     647           0 :         break;
     648           0 :     case SelectiveMulticastRoute:
     649           0 :         KEY_COMPARE(rd_, rhs.rd_);
     650           0 :         KEY_COMPARE(tag_, rhs.tag_);
     651           0 :         KEY_COMPARE(source_, rhs.source_);
     652           0 :         KEY_COMPARE(group_, rhs.group_);
     653           0 :         KEY_COMPARE(ip_address_, rhs.ip_address_);
     654             :     default:
     655           0 :         break;
     656             :     }
     657             : 
     658           0 :     return 0;
     659             : }
     660             : 
     661             : // Check whether 'this' is more specific than rhs.
     662           0 : bool EvpnPrefix::IsMoreSpecific(const EvpnPrefix &rhs) const {
     663           0 :     switch (type_) {
     664           0 :     case IpPrefixRoute:
     665           0 :         if (family_ == Address::INET) {
     666           0 :             return inet_prefix().IsMoreSpecific(rhs.inet_prefix());
     667             :         } else {
     668           0 :             return inet6_prefix().IsMoreSpecific(rhs.inet6_prefix());
     669             :         }
     670             :         break;
     671           0 :     default:
     672           0 :         break;
     673             :     }
     674           0 :     return false;
     675             : }
     676             : 
     677           0 : bool EvpnPrefix::GetSourceFromString(EvpnPrefix *prefix, const string &str,
     678             :         size_t pos1, size_t *pos2, boost::system::error_code *errorp) {
     679           0 :     *pos2 = str.find('-', pos1 + 1);
     680           0 :     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           0 :     string temp_str = str.substr(pos1 + 1, *pos2 - pos1 - 1);
     687           0 :     boost::system::error_code source_err;
     688           0 :     prefix->source_ = Ip4Address::from_string(temp_str, source_err);
     689           0 :     if (source_err.failed()) {
     690           0 :         if (errorp != NULL) {
     691           0 :             *errorp = source_err;
     692             :         }
     693           0 :         return false;
     694             :     }
     695           0 :     return true;
     696           0 : }
     697             : 
     698           0 : bool EvpnPrefix::GetGroupFromString(EvpnPrefix *prefix, const string &str,
     699             :         size_t pos1, size_t *pos2, boost::system::error_code *errorp) {
     700           0 :     *pos2 = str.find('-', pos1 + 1);
     701           0 :     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           0 :     string temp_str = str.substr(pos1 + 1, *pos2 - pos1 - 1);
     708           0 :     boost::system::error_code group_err;
     709           0 :     prefix->group_ = Ip4Address::from_string(temp_str, group_err);
     710           0 :     if (group_err.failed()) {
     711           0 :         if (errorp != NULL) {
     712           0 :             *errorp = group_err;
     713             :         }
     714           0 :         return false;
     715             :     }
     716           0 :     return true;
     717           0 : }
     718             : 
     719           0 : EvpnPrefix EvpnPrefix::FromString(const string &str,
     720             :     boost::system::error_code *errorp) {
     721           0 :     EvpnPrefix prefix;
     722             : 
     723             :     // Parse type.
     724           0 :     size_t pos1 = str.find('-');
     725           0 :     if (pos1 == string::npos) {
     726           0 :         if (errorp != NULL) {
     727           0 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     728             :         }
     729           0 :         return EvpnPrefix::kNullPrefix;
     730             :     }
     731             : 
     732           0 :     string type_str = str.substr(0, pos1);
     733           0 :     bool ret = stringToInteger(type_str, prefix.type_);
     734           0 :     if (!ret) {
     735           0 :         if (errorp != NULL) {
     736           0 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     737             :         }
     738           0 :         return EvpnPrefix::kNullPrefix;
     739             :     }
     740             : 
     741           0 :     if (prefix.type_ < EvpnPrefix::AutoDiscoveryRoute ||
     742           0 :         prefix.type_ > EvpnPrefix::SelectiveMulticastRoute) {
     743           0 :         if (errorp != NULL) {
     744           0 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     745             :         }
     746           0 :         return EvpnPrefix::kNullPrefix;
     747             :     }
     748             : 
     749             :     // Parse RD.
     750           0 :     size_t pos2 = str.find('-', pos1 + 1);
     751           0 :     if (pos2 == string::npos) {
     752           0 :         if (errorp != NULL) {
     753           0 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     754             :         }
     755           0 :         return EvpnPrefix::kNullPrefix;
     756             :     }
     757           0 :     string rd_str = str.substr(pos1 + 1, pos2 - pos1 - 1);
     758           0 :     boost::system::error_code rd_err;
     759           0 :     prefix.rd_ = RouteDistinguisher::FromString(rd_str, &rd_err);
     760           0 :     if (rd_err.failed()) {
     761           0 :         if (errorp != NULL) {
     762           0 :             *errorp = rd_err;
     763             :         }
     764           0 :         return EvpnPrefix::kNullPrefix;
     765             :     }
     766             : 
     767           0 :     switch (prefix.type_) {
     768           0 :     case AutoDiscoveryRoute: {
     769             :         // Parse ESI.
     770           0 :         size_t pos3 = str.find('-', pos2 + 1);
     771           0 :         if (pos3 == string::npos) {
     772           0 :             if (errorp != NULL) {
     773             :                 *errorp =
     774           0 :                     make_error_code(boost::system::errc::invalid_argument);
     775             :             }
     776           0 :             return EvpnPrefix::kNullPrefix;
     777             :         }
     778           0 :         string esi_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
     779           0 :         boost::system::error_code esi_err;
     780           0 :         prefix.esi_ = EthernetSegmentId::FromString(esi_str, &esi_err);
     781           0 :         if (esi_err.failed()) {
     782           0 :             if (errorp != NULL) {
     783           0 :                 *errorp = esi_err;
     784             :             }
     785           0 :             return EvpnPrefix::kNullPrefix;
     786             :         }
     787             : 
     788             :         // Parse tag.
     789           0 :         string tag_str = str.substr(pos3 + 1, string::npos);
     790           0 :         bool ret = stringToInteger(tag_str, prefix.tag_);
     791           0 :         if (!ret) {
     792           0 :             if (errorp != NULL) {
     793             :                 *errorp =
     794           0 :                     make_error_code(boost::system::errc::invalid_argument);
     795             :             }
     796           0 :             return EvpnPrefix::kNullPrefix;
     797             :         }
     798             : 
     799           0 :         break;
     800           0 :     }
     801             : 
     802           0 :     case MacAdvertisementRoute: {
     803             :         // Parse tag.
     804           0 :         size_t pos3 = str.find('-', pos2 + 1);
     805           0 :         if (pos3 == string::npos) {
     806           0 :             if (errorp != NULL) {
     807             :                 *errorp =
     808           0 :                     make_error_code(boost::system::errc::invalid_argument);
     809             :             }
     810           0 :             return EvpnPrefix::kNullPrefix;
     811             :         }
     812           0 :         string tag_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
     813           0 :         bool ret = stringToInteger(tag_str, prefix.tag_);
     814           0 :         if (!ret) {
     815           0 :             if (errorp != NULL) {
     816             :                 *errorp =
     817           0 :                     make_error_code(boost::system::errc::invalid_argument);
     818             :             }
     819           0 :             return EvpnPrefix::kNullPrefix;
     820             :         }
     821             : 
     822             :         // Parse MAC.
     823           0 :         size_t pos4 = str.rfind(',');
     824           0 :         string mac_str = str.substr(pos3 + 1, pos4 - pos3 -1);
     825           0 :         boost::system::error_code mac_err;
     826           0 :         prefix.mac_addr_ = MacAddress::FromString(mac_str, &mac_err);
     827           0 :         if (mac_err.failed()) {
     828           0 :             if (errorp != NULL) {
     829           0 :                 *errorp = mac_err;
     830             :             }
     831           0 :             return EvpnPrefix::kNullPrefix;
     832             :         }
     833             : 
     834             :         // Parse IP - treat all 0s as unspecified.
     835           0 :         string ip_str = str.substr(pos4 + 1, string::npos);
     836           0 :         boost::system::error_code ip_err;
     837           0 :         prefix.ip_address_ = IpAddress::from_string(ip_str, ip_err);
     838           0 :         if (ip_err.failed()) {
     839           0 :             if (errorp != NULL) {
     840           0 :                 *errorp = ip_err;
     841             :             }
     842           0 :             return EvpnPrefix::kNullPrefix;
     843             :         }
     844           0 :         if (prefix.ip_address_.is_v4() && !prefix.ip_address_.is_unspecified())
     845           0 :             prefix.family_ = Address::INET;
     846           0 :         if (prefix.ip_address_.is_v6() && !prefix.ip_address_.is_unspecified())
     847           0 :             prefix.family_ = Address::INET6;
     848             : 
     849           0 :         break;
     850           0 :     }
     851             : 
     852           0 :     case InclusiveMulticastRoute: {
     853             :         // Parse tag.
     854           0 :         size_t pos3 = str.find('-', pos2 + 1);
     855           0 :         if (pos3 == string::npos) {
     856           0 :             if (errorp != NULL) {
     857             :                 *errorp =
     858           0 :                     make_error_code(boost::system::errc::invalid_argument);
     859             :             }
     860           0 :             return EvpnPrefix::kNullPrefix;
     861             :         }
     862           0 :         string tag_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
     863           0 :         bool ret = stringToInteger(tag_str, prefix.tag_);
     864           0 :         if (!ret) {
     865           0 :             if (errorp != NULL) {
     866             :                 *errorp =
     867           0 :                     make_error_code(boost::system::errc::invalid_argument);
     868             :             }
     869           0 :             return EvpnPrefix::kNullPrefix;
     870             :         }
     871             : 
     872             :         // Parse IP.
     873           0 :         string ip_str = str.substr(pos3 + 1, string::npos);
     874           0 :         boost::system::error_code ip_err;
     875           0 :         prefix.ip_address_ = IpAddress::from_string(ip_str, ip_err);
     876           0 :         if (ip_err.failed()) {
     877           0 :             if (errorp != NULL) {
     878           0 :                 *errorp = ip_err;
     879             :             }
     880           0 :             return EvpnPrefix::kNullPrefix;
     881             :         }
     882           0 :         prefix.family_ =
     883           0 :             prefix.ip_address_.is_v4() ? Address::INET : Address::INET6;
     884             : 
     885           0 :         break;
     886           0 :     }
     887             : 
     888           0 :     case SegmentRoute: {
     889             :         // Parse ESI.
     890           0 :         size_t pos3 = str.find('-', pos2 + 1);
     891           0 :         if (pos3 == string::npos) {
     892           0 :             if (errorp != NULL) {
     893             :                 *errorp =
     894           0 :                     make_error_code(boost::system::errc::invalid_argument);
     895             :             }
     896           0 :             return EvpnPrefix::kNullPrefix;
     897             :         }
     898           0 :         string esi_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
     899           0 :         boost::system::error_code esi_err;
     900           0 :         prefix.esi_ = EthernetSegmentId::FromString(esi_str, &esi_err);
     901           0 :         if (esi_err.failed()) {
     902           0 :             if (errorp != NULL) {
     903           0 :                 *errorp = esi_err;
     904             :             }
     905           0 :             return EvpnPrefix::kNullPrefix;
     906             :         }
     907             : 
     908             :         // Parse IP.
     909           0 :         string ip_str = str.substr(pos3 + 1, string::npos);
     910           0 :         boost::system::error_code ip_err;
     911           0 :         prefix.ip_address_ = IpAddress::from_string(ip_str, ip_err);
     912           0 :         if (ip_err.failed()) {
     913           0 :             if (errorp != NULL) {
     914           0 :                 *errorp = ip_err;
     915             :             }
     916           0 :             return EvpnPrefix::kNullPrefix;
     917             :         }
     918           0 :         prefix.family_ =
     919           0 :             prefix.ip_address_.is_v4() ? Address::INET : Address::INET6;
     920             : 
     921           0 :         break;
     922           0 :     }
     923             : 
     924           0 :     case IpPrefixRoute: {
     925             :         // Parse tag.
     926           0 :         size_t pos3 = str.find('-', pos2 + 1);
     927           0 :         if (pos3 == string::npos) {
     928           0 :             if (errorp != NULL) {
     929             :                 *errorp =
     930           0 :                     make_error_code(boost::system::errc::invalid_argument);
     931             :             }
     932           0 :             return EvpnPrefix::kNullPrefix;
     933             :         }
     934           0 :         string tag_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
     935           0 :         bool ret = stringToInteger(tag_str, prefix.tag_);
     936           0 :         if (!ret) {
     937           0 :             if (errorp != NULL) {
     938             :                 *errorp =
     939           0 :                     make_error_code(boost::system::errc::invalid_argument);
     940             :             }
     941           0 :             return EvpnPrefix::kNullPrefix;
     942             :         }
     943             : 
     944             :         // Parse IP prefix - first try v4, then v6.
     945           0 :         string ip_str = str.substr(pos3 + 1, string::npos);
     946           0 :         boost::system::error_code ip_err;
     947             : 
     948           0 :         Ip4Prefix inet_prefix = Ip4Prefix::FromString(ip_str, &ip_err);
     949           0 :         if (!ip_err) {
     950           0 :             prefix.family_ = Address::INET;
     951           0 :             prefix.ip_address_ = inet_prefix.addr();
     952           0 :             prefix.ip_prefixlen_ = inet_prefix.prefixlen();
     953           0 :             return prefix;
     954             :         }
     955             : 
     956           0 :         Inet6Prefix inet6_prefix = Inet6Prefix::FromString(ip_str, &ip_err);
     957           0 :         if (!ip_err) {
     958           0 :             prefix.family_ = Address::INET6;
     959           0 :             prefix.ip_address_ = inet6_prefix.addr();
     960           0 :             prefix.ip_prefixlen_ = inet6_prefix.prefixlen();
     961           0 :             return prefix;
     962             :         }
     963             : 
     964           0 :         if (errorp != NULL) {
     965           0 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     966             :         }
     967           0 :         return EvpnPrefix::kNullPrefix;
     968             :         break;
     969           0 :     }
     970             : 
     971           0 :     case SelectiveMulticastRoute: {
     972             :         // Parse tag.
     973           0 :         size_t pos3 = str.find('-', pos2 + 1);
     974           0 :         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           0 :         string tag_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
     982           0 :         bool ret = stringToInteger(tag_str, prefix.tag_);
     983           0 :         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           0 :         if (!GetSourceFromString(&prefix, str, pos3, &pos4, errorp))
     994           0 :             return EvpnPrefix::kNullPrefix;
     995             : 
     996             :         // Look for group.
     997             :         size_t pos5;
     998           0 :         if (!GetGroupFromString(&prefix, str, pos4, &pos5, errorp))
     999           0 :             return EvpnPrefix::kNullPrefix;
    1000             : 
    1001             :         // Parse IP.
    1002           0 :         string ip_str = str.substr(pos5 + 1, string::npos);
    1003           0 :         boost::system::error_code ip_err;
    1004           0 :         prefix.ip_address_ = IpAddress::from_string(ip_str, ip_err);
    1005           0 :         if (ip_err.failed()) {
    1006           0 :             if (errorp != NULL) {
    1007           0 :                 *errorp = ip_err;
    1008             :             }
    1009           0 :             return EvpnPrefix::kNullPrefix;
    1010             :         }
    1011           0 :         prefix.family_ =
    1012           0 :             prefix.ip_address_.is_v4() ? Address::INET : Address::INET6;
    1013             : 
    1014           0 :         break;
    1015           0 :     }
    1016             : 
    1017             :     }
    1018             : 
    1019           0 :     return prefix;
    1020           0 : }
    1021             : 
    1022           0 : string EvpnPrefix::ToString() const {
    1023           0 :     string str = integerToString(type_);
    1024           0 :     str += "-" + rd_.ToString();
    1025           0 :     switch (type_) {
    1026           0 :     case AutoDiscoveryRoute:
    1027           0 :         str += "-" + esi_.ToString();
    1028           0 :         str += "-" + integerToString(tag_);
    1029           0 :         break;
    1030           0 :     case MacAdvertisementRoute:
    1031           0 :         str += "-" + integerToString(tag_);
    1032           0 :         str += "-" + mac_addr_.ToString();
    1033           0 :         str += "," + ip_address_.to_string();
    1034           0 :         break;
    1035           0 :     case InclusiveMulticastRoute:
    1036           0 :         str += "-" + integerToString(tag_);
    1037           0 :         str += "-" + ip_address_.to_string();
    1038           0 :         break;
    1039           0 :     case SegmentRoute:
    1040           0 :         str += "-" + esi_.ToString();
    1041           0 :         str += "-" + ip_address_.to_string();
    1042           0 :         break;
    1043           0 :     case IpPrefixRoute:
    1044           0 :         str += "-" + integerToString(tag_);
    1045           0 :         if (family_ == Address::INET) {
    1046           0 :             str += "-" + inet_prefix().ToString();
    1047             :         } else {
    1048           0 :             str += "-" + inet6_prefix().ToString();
    1049             :         }
    1050           0 :         break;
    1051           0 :     case SelectiveMulticastRoute:
    1052           0 :         str += "-" + integerToString(tag_);
    1053           0 :         if (!source_.is_unspecified())
    1054           0 :             str += "-" + source_.to_string();
    1055           0 :         str += "-" + group_.to_string();
    1056           0 :         str += "-" + ip_address_.to_string();
    1057           0 :         break;
    1058           0 :     default:
    1059           0 :         break;
    1060             :     }
    1061             : 
    1062           0 :     return str;
    1063           0 : }
    1064             : 
    1065           0 : string EvpnPrefix::ToXmppIdString() const {
    1066           0 :     string str;
    1067           0 :     if (tag_ != 0)
    1068           0 :         str += integerToString(tag_) + "-";
    1069           0 :     str += mac_addr_.ToString();
    1070           0 :     str += "," + ip_address_.to_string() + "/" +
    1071           0 :         integerToString(ip_address_length());
    1072           0 :     if (!group_.is_unspecified()) {
    1073           0 :         str += "," + group_.to_string() + "," +
    1074           0 :             source_.to_string();
    1075             :     }
    1076           0 :     return str;
    1077           0 : }
    1078             : 
    1079           0 : uint8_t EvpnPrefix::ip_address_length() const {
    1080           0 :     if (type_ == IpPrefixRoute)
    1081           0 :         return ip_prefixlen_;
    1082           0 :     if (family_ == Address::INET)
    1083           0 :         return 32;
    1084           0 :     if (family_ == Address::INET6)
    1085           0 :         return 128;
    1086           0 :     return 32;
    1087             : }
    1088             : 
    1089           0 : size_t EvpnPrefix::GetIpAddressSize() const {
    1090           0 :     if (family_ == Address::INET)
    1091           0 :         return kIp4AddrSize;
    1092           0 :     if (family_ == Address::INET6)
    1093           0 :         return kIp6AddrSize;
    1094           0 :     return 0;
    1095             : }
    1096             : 
    1097           0 : void EvpnPrefix::ReadSource(const BgpProtoPrefix &proto_prefix,
    1098             :     size_t ip_offset, size_t ip_size) {
    1099           0 :     if (ip_size == 0) {
    1100           0 :         family_ = Address::UNSPEC;
    1101           0 :     } else if (ip_size == kIp4AddrSize) {
    1102           0 :         family_ = Address::INET;
    1103           0 :         Ip4Address::bytes_type bytes = { { 0 } };
    1104           0 :         copy(proto_prefix.prefix.begin() + ip_offset,
    1105           0 :             proto_prefix.prefix.begin() + ip_offset + ip_size, bytes.begin());
    1106           0 :         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           0 : }
    1115             : 
    1116           0 : void EvpnPrefix::ReadGroup(const BgpProtoPrefix &proto_prefix,
    1117             :     size_t ip_offset, size_t ip_size) {
    1118           0 :     if (ip_size == 0) {
    1119           0 :         family_ = Address::UNSPEC;
    1120           0 :     } else if (ip_size == kIp4AddrSize) {
    1121           0 :         family_ = Address::INET;
    1122           0 :         Ip4Address::bytes_type bytes = { { 0 } };
    1123           0 :         copy(proto_prefix.prefix.begin() + ip_offset,
    1124           0 :             proto_prefix.prefix.begin() + ip_offset + ip_size, bytes.begin());
    1125           0 :         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           0 : }
    1134             : 
    1135           0 : void EvpnPrefix::ReadIpAddress(const BgpProtoPrefix &proto_prefix,
    1136             :     size_t ip_offset, size_t ip_size, size_t ip_psize) {
    1137           0 :     assert(ip_psize <= ip_size);
    1138           0 :     if (ip_size == 0) {
    1139           0 :         family_ = Address::UNSPEC;
    1140           0 :     } else if (ip_size == kIp4AddrSize) {
    1141           0 :         family_ = Address::INET;
    1142           0 :         Ip4Address::bytes_type bytes = { { 0 } };
    1143           0 :         copy(proto_prefix.prefix.begin() + ip_offset,
    1144           0 :             proto_prefix.prefix.begin() + ip_offset + ip_psize, bytes.begin());
    1145           0 :         ip_address_ = Ip4Address(bytes);
    1146           0 :     } else if (ip_size == kIp6AddrSize) {
    1147           0 :         family_ = Address::INET6;
    1148           0 :         Ip6Address::bytes_type bytes = { { 0 } };
    1149           0 :         copy(proto_prefix.prefix.begin() + ip_offset,
    1150           0 :             proto_prefix.prefix.begin() + ip_offset + ip_psize, bytes.begin());
    1151           0 :         ip_address_ = Ip6Address(bytes);
    1152             :     }
    1153           0 : }
    1154             : 
    1155           0 : void EvpnPrefix::WriteIpAddress(BgpProtoPrefix *proto_prefix,
    1156             :                                 size_t ip_offset) const {
    1157           0 :     if (family_ == Address::INET) {
    1158           0 :         const Ip4Address::bytes_type &bytes = ip_address_.to_v4().to_bytes();
    1159           0 :         copy(bytes.begin(), bytes.begin() + kIp4AddrSize,
    1160           0 :             proto_prefix->prefix.begin() + ip_offset);
    1161           0 :     } else if (family_ == Address::INET6) {
    1162           0 :         const Ip6Address::bytes_type &bytes = ip_address_.to_v6().to_bytes();
    1163           0 :         copy(bytes.begin(), bytes.begin() + kIp6AddrSize,
    1164           0 :             proto_prefix->prefix.begin() + ip_offset);
    1165             :     }
    1166           0 : }
    1167             : 
    1168           0 : void EvpnPrefix::WriteSource(BgpProtoPrefix *proto_prefix,
    1169             :                              size_t ip_offset) const {
    1170           0 :     if (family_ == Address::INET) {
    1171           0 :         const Ip4Address::bytes_type &bytes = source_.to_v4().to_bytes();
    1172           0 :         copy(bytes.begin(), bytes.begin() + kIp4AddrSize,
    1173           0 :             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           0 : }
    1180             : 
    1181           0 : void EvpnPrefix::WriteGroup(BgpProtoPrefix *proto_prefix,
    1182             :                             size_t ip_offset) const {
    1183           0 :     if (family_ == Address::INET) {
    1184           0 :         const Ip4Address::bytes_type &bytes = group_.to_v4().to_bytes();
    1185           0 :         copy(bytes.begin(), bytes.begin() + kIp4AddrSize,
    1186           0 :             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           0 : }
    1193             : 
    1194           0 : EvpnRoute::EvpnRoute(const EvpnPrefix &prefix)
    1195           0 :     : prefix_(prefix) {
    1196           0 : }
    1197             : 
    1198           0 : int EvpnRoute::CompareTo(const Route &rhs) const {
    1199           0 :     const EvpnRoute &evpn_rhs = static_cast<const EvpnRoute &>(rhs);
    1200           0 :     return prefix_.CompareTo(evpn_rhs.prefix_);
    1201             : }
    1202             : 
    1203           0 : string EvpnRoute::ToString() const {
    1204           0 :     return prefix_.ToString();
    1205             : }
    1206             : 
    1207           0 : string EvpnRoute::ToXmppIdString() const {
    1208           0 :     if (xmpp_id_str_.empty())
    1209           0 :         xmpp_id_str_ = prefix_.ToXmppIdString();
    1210           0 :     return xmpp_id_str_;
    1211             : }
    1212             : 
    1213           0 : bool EvpnRoute::IsValid() const {
    1214           0 :     if (!BgpRoute::IsValid())
    1215           0 :         return false;
    1216             : 
    1217           0 :     const BgpAttr *attr = BestPath()->GetAttr();
    1218           0 :     switch (prefix_.type()) {
    1219           0 :     case EvpnPrefix::AutoDiscoveryRoute: {
    1220           0 :         if (prefix_.tag() == EvpnPrefix::kMaxTag)
    1221           0 :             return true;
    1222           0 :         break;
    1223             :     }
    1224           0 :     case EvpnPrefix::MacAdvertisementRoute: {
    1225           0 :         return true;
    1226             :     }
    1227           0 :     case EvpnPrefix::InclusiveMulticastRoute: {
    1228           0 :         const PmsiTunnel *pmsi_tunnel = attr->pmsi_tunnel();
    1229           0 :         if (!pmsi_tunnel)
    1230           0 :             return false;
    1231           0 :         uint8_t tunnel_type = pmsi_tunnel->tunnel_type();
    1232           0 :         uint8_t tunnel_flags = pmsi_tunnel->tunnel_flags();
    1233           0 :         uint8_t ar_type =
    1234             :             tunnel_flags & PmsiTunnelSpec::AssistedReplicationType;
    1235           0 :         if (tunnel_type == PmsiTunnelSpec::IngressReplication) {
    1236           0 :             if (ar_type == PmsiTunnelSpec::RegularNVE)
    1237           0 :                 return true;
    1238           0 :             if (ar_type == PmsiTunnelSpec::ARReplicator &&
    1239           0 :                 (tunnel_flags & PmsiTunnelSpec::LeafInfoRequired)) {
    1240           0 :                 return true;
    1241             :             }
    1242           0 :             return false;
    1243             :         }
    1244           0 :         if (tunnel_type == PmsiTunnelSpec::AssistedReplicationContrail &&
    1245             :             ar_type == PmsiTunnelSpec::ARLeaf) {
    1246           0 :             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           0 : void EvpnRoute::SetKey(const DBRequestKey *reqkey) {
    1268           0 :     const EvpnTable::RequestKey *key =
    1269             :         static_cast<const EvpnTable::RequestKey *>(reqkey);
    1270           0 :     prefix_ = key->prefix;
    1271           0 : }
    1272             : 
    1273           0 : void EvpnRoute::BuildProtoPrefix(BgpProtoPrefix *proto_prefix,
    1274             :     const BgpAttr *attr, uint32_t label, uint32_t l3_label) const {
    1275           0 :     prefix_.BuildProtoPrefix(proto_prefix, attr, label, l3_label);
    1276           0 : }
    1277             : 
    1278           0 : void EvpnRoute::BuildBgpProtoNextHop(vector<uint8_t> &nh,
    1279             :         IpAddress nexthop) const {
    1280           0 :     nh.resize(4);
    1281           0 :     const Ip4Address::bytes_type &addr_bytes = nexthop.to_v4().to_bytes();
    1282           0 :     copy(addr_bytes.begin(), addr_bytes.end(), nh.begin());
    1283           0 : }
    1284             : 
    1285           0 : DBEntryBase::KeyPtr EvpnRoute::GetDBRequestKey() const {
    1286           0 :     EvpnTable::RequestKey *key = new EvpnTable::RequestKey(GetPrefix(), NULL);
    1287           0 :     return KeyPtr(key);
    1288             : }

Generated by: LCOV version 1.14