diff --git a/src/bgp/evpn/evpn_route.cc b/src/bgp/evpn/evpn_route.cc index 04214d07ad7..a2b386a4fb9 100644 --- a/src/bgp/evpn/evpn_route.cc +++ b/src/bgp/evpn/evpn_route.cc @@ -24,6 +24,8 @@ const uint32_t EvpnPrefix::kMaxVni = 0x00FFFFFF; const size_t EvpnPrefix::kRdSize = RouteDistinguisher::kSize; const size_t EvpnPrefix::kEsiSize = EthernetSegmentId::kSize; const size_t EvpnPrefix::kTagSize = 4; +const size_t EvpnPrefix::kIp4AddrSize = 4; +const size_t EvpnPrefix::kIp6AddrSize = 16; const size_t EvpnPrefix::kMacSize = MacAddress::size(); const size_t EvpnPrefix::kLabelSize = BgpProtoPrefix::kLabelSize; @@ -35,6 +37,10 @@ const size_t EvpnPrefix::kMinInclusiveMulticastRouteSize = kRdSize + kTagSize + 1; const size_t EvpnPrefix::kMinSegmentRouteSize = kRdSize + kEsiSize + 1; +const size_t EvpnPrefix::kMinInetPrefixRouteSize = + kRdSize + kEsiSize + kTagSize + 1 + 2 * kIp4AddrSize; +const size_t EvpnPrefix::kMinInet6PrefixRouteSize = + kRdSize + kEsiSize + kTagSize + 1 + 2 * kIp6AddrSize; // // Read label from the BgpProtoPrefix. @@ -45,7 +51,7 @@ const size_t EvpnPrefix::kMinSegmentRouteSize = // and their label is supposed to be set to 0 on write and ignored on read. // static uint32_t ReadLabel(const BgpProtoPrefix &proto_prefix, - const BgpAttr *attr, size_t offset, uint32_t tag) { + const BgpAttr *attr, size_t offset, uint32_t tag = EvpnPrefix::kNullTag) { if (!attr) return 0; const ExtCommunity *extcomm = attr->ext_community(); @@ -79,21 +85,53 @@ static void WriteLabel(BgpProtoPrefix *proto_prefix, } } +// +// Read gateway address from the BgpProtoPrefix. +// +static IpAddress ReadGwAddress(const BgpProtoPrefix &proto_prefix, + size_t gw_offset, size_t ip_size) { + assert(ip_size == EvpnPrefix::kIp4AddrSize || + ip_size == EvpnPrefix::kIp6AddrSize); + if (ip_size == EvpnPrefix::kIp4AddrSize) { + Ip4Address::bytes_type bytes; + copy(proto_prefix.prefix.begin() + gw_offset, + proto_prefix.prefix.begin() + gw_offset + ip_size, bytes.begin()); + return Ip4Address(bytes); + } else { + Ip6Address::bytes_type bytes; + copy(proto_prefix.prefix.begin() + gw_offset, + proto_prefix.prefix.begin() + gw_offset + ip_size, bytes.begin()); + return Ip6Address(bytes); + } + return IpAddress(); +} + EvpnPrefix::EvpnPrefix() - : type_(Unspecified), tag_(EvpnPrefix::kNullTag), family_(Address::UNSPEC) { + : type_(Unspecified), + tag_(EvpnPrefix::kNullTag), + family_(Address::UNSPEC), + ip_prefixlen_(0) { } EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, const EthernetSegmentId &esi, uint32_t tag) : type_(AutoDiscoveryRoute), - rd_(rd), esi_(esi), tag_(tag), family_(Address::UNSPEC) { + rd_(rd), + esi_(esi), + tag_(tag), + family_(Address::UNSPEC), + ip_prefixlen_(0) { } EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, const MacAddress &mac_addr, const IpAddress &ip_address) : type_(MacAdvertisementRoute), - rd_(rd), tag_(EvpnPrefix::kNullTag), - mac_addr_(mac_addr), family_(Address::UNSPEC), ip_address_(ip_address) { + rd_(rd), + tag_(EvpnPrefix::kNullTag), + mac_addr_(mac_addr), + family_(Address::UNSPEC), + ip_address_(ip_address), + ip_prefixlen_(0) { if (ip_address_.is_v4() && !ip_address_.is_unspecified()) { family_ = Address::INET; } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) { @@ -103,9 +141,9 @@ EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, uint32_t tag, const MacAddress &mac_addr, const IpAddress &ip_address) - : type_(MacAdvertisementRoute), - rd_(rd), tag_(tag), - mac_addr_(mac_addr), family_(Address::UNSPEC), ip_address_(ip_address) { + : type_(MacAdvertisementRoute), rd_(rd), tag_(tag), + mac_addr_(mac_addr), family_(Address::UNSPEC), + ip_address_(ip_address), ip_prefixlen_(0) { if (ip_address_.is_v4() && !ip_address_.is_unspecified()) { family_ = Address::INET; } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) { @@ -115,8 +153,12 @@ EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, uint32_t tag, EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, uint32_t tag, const IpAddress &ip_address) - : type_(InclusiveMulticastRoute), rd_(rd), tag_(tag), - family_(Address::UNSPEC), ip_address_(ip_address) { + : type_(InclusiveMulticastRoute), + rd_(rd), + tag_(tag), + family_(Address::UNSPEC), + ip_address_(ip_address), + ip_prefixlen_(0) { if (ip_address_.is_v4() && !ip_address_.is_unspecified()) { family_ = Address::INET; } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) { @@ -127,8 +169,12 @@ EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, uint32_t tag, EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, const EthernetSegmentId &esi, const IpAddress &ip_address) : type_(SegmentRoute), - rd_(rd), esi_(esi), tag_(EvpnPrefix::kNullTag), - family_(Address::UNSPEC), ip_address_(ip_address) { + rd_(rd), + esi_(esi), + tag_(EvpnPrefix::kNullTag), + family_(Address::UNSPEC), + ip_address_(ip_address), + ip_prefixlen_(0) { if (ip_address_.is_v4() && !ip_address_.is_unspecified()) { family_ = Address::INET; } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) { @@ -136,6 +182,22 @@ EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, } } +EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, uint32_t tag, + const IpAddress &ip_address, uint8_t ip_prefixlen) + : type_(IpPrefixRoute), + rd_(rd), + tag_(tag), + family_(Address::UNSPEC), + ip_address_(ip_address), + ip_prefixlen_(ip_prefixlen) { + assert(ip_address_.is_v4() || ip_address_.is_v6()); + if (ip_address_.is_v4()) { + family_ = Address::INET; + } else if (ip_address_.is_v6()) { + family_ = Address::INET6; + } +} + int EvpnPrefix::FromProtoPrefix(BgpServer *server, const BgpProtoPrefix &proto_prefix, const BgpAttr *attr, EvpnPrefix *prefix, BgpAttrPtr *new_attr, uint32_t *label) { @@ -188,7 +250,7 @@ int EvpnPrefix::FromProtoPrefix(BgpServer *server, if (nlri_size < expected_min_nlri_size + ip_size) return -1; size_t ip_offset = ip_len_offset + 1; - prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size); + prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_size); size_t label_offset = ip_offset + ip_size; *label = ReadLabel(proto_prefix, attr, label_offset, prefix->tag_); break; @@ -208,7 +270,7 @@ int EvpnPrefix::FromProtoPrefix(BgpServer *server, if (nlri_size < kMinInclusiveMulticastRouteSize + ip_size) return -1; size_t ip_offset = ip_len_offset + 1; - prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size); + prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_size); const PmsiTunnel *pmsi_tunnel = attr ? attr->pmsi_tunnel() : NULL; if (pmsi_tunnel && (pmsi_tunnel->tunnel_type() == PmsiTunnelSpec::IngressReplication || @@ -242,7 +304,54 @@ int EvpnPrefix::FromProtoPrefix(BgpServer *server, if (nlri_size < kMinSegmentRouteSize + ip_size) return -1; size_t ip_offset = ip_len_offset + 1; - prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size); + prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_size); + break; + } + case IpPrefixRoute: { + size_t ip_size; + if (attr) { + if (nlri_size == kMinInet6PrefixRouteSize + kLabelSize) { + ip_size = kIp6AddrSize; + } else if (nlri_size == kMinInetPrefixRouteSize + kLabelSize) { + ip_size = kIp4AddrSize; + } else { + return -1; + } + } else { + if (nlri_size == kMinInet6PrefixRouteSize || + nlri_size == kMinInet6PrefixRouteSize + kLabelSize) { + ip_size = kIp6AddrSize; + } else if (nlri_size == kMinInetPrefixRouteSize || + nlri_size == kMinInetPrefixRouteSize + kLabelSize) { + ip_size = kIp4AddrSize; + } else { + return -1; + } + } + + size_t rd_offset = 0; + prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]); + size_t esi_offset = rd_offset + kRdSize; + EthernetSegmentId esi(&proto_prefix.prefix[esi_offset]); + if (!esi.IsZero()) + return -1; + size_t tag_offset = esi_offset + kEsiSize; + prefix->tag_ = get_value(&proto_prefix.prefix[tag_offset], kTagSize); + size_t ip_plen_offset = tag_offset + kTagSize; + prefix->ip_prefixlen_ = proto_prefix.prefix[ip_plen_offset]; + if (ip_size == kIp4AddrSize && prefix->ip_prefixlen_ > 32) + return -1; + if (ip_size == kIp6AddrSize && prefix->ip_prefixlen_ > 128) + return -1; + size_t ip_offset = ip_plen_offset + 1; + size_t ip_psize = (prefix->ip_prefixlen_ + 7) / 8; + prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_psize); + size_t gw_offset = ip_offset + ip_size; + IpAddress gw_address = ReadGwAddress(proto_prefix, gw_offset, ip_size); + if (!gw_address.is_unspecified()) + return -1; + size_t label_offset = gw_offset + ip_size; + *label = ReadLabel(proto_prefix, attr, label_offset); break; } default: { @@ -257,7 +366,7 @@ int EvpnPrefix::FromProtoPrefix(BgpServer *server, // Build the BgpProtoPrefix for this EvpnPrefix. // // The ESI for MacAdvertisementRoute is not part of the key and hence -// must be obtained from the BgpAttr.The BgpAttr is NULL and label is +// must be obtained from the BgpAttr. The BgpAttr is NULL and label is // 0 when withdrawing the route. // void EvpnPrefix::BuildProtoPrefix(const BgpAttr *attr, uint32_t label, @@ -348,6 +457,37 @@ void EvpnPrefix::BuildProtoPrefix(const BgpAttr *attr, uint32_t label, WriteIpAddress(proto_prefix, ip_offset); break; } + case IpPrefixRoute: { + size_t ip_size, nlri_size; + if (family_ == Address::INET) { + ip_size = kIp4AddrSize; + nlri_size = kMinInetPrefixRouteSize + kLabelSize; + } else { + ip_size = kIp6AddrSize; + nlri_size = kMinInet6PrefixRouteSize + kLabelSize; + } + proto_prefix->prefixlen = nlri_size * 8; + proto_prefix->prefix.resize(nlri_size, 0); + + size_t rd_offset = 0; + copy(rd_.GetData(), rd_.GetData() + kRdSize, + proto_prefix->prefix.begin() + rd_offset); + size_t esi_offset = rd_offset + kRdSize; + if (attr) { + copy(attr->esi().GetData(), attr->esi().GetData() + kEsiSize, + proto_prefix->prefix.begin() + esi_offset); + } + size_t tag_offset = esi_offset + kEsiSize; + put_value(&proto_prefix->prefix[tag_offset], kTagSize, tag_); + size_t ip_plen_offset = tag_offset + kTagSize; + proto_prefix->prefix[ip_plen_offset] = ip_prefixlen_; + size_t ip_offset = ip_plen_offset + 1; + WriteIpAddress(proto_prefix, ip_offset); + size_t gw_offset = ip_offset + ip_size; + size_t label_offset = gw_offset + ip_size; + WriteLabel(proto_prefix, attr, label_offset, label); + break; + } default: { assert(false); break; @@ -380,6 +520,12 @@ int EvpnPrefix::CompareTo(const EvpnPrefix &rhs) const { KEY_COMPARE(esi_, rhs.esi_); KEY_COMPARE(ip_address_, rhs.ip_address_); break; + case IpPrefixRoute: + KEY_COMPARE(rd_, rhs.rd_); + KEY_COMPARE(tag_, rhs.tag_); + KEY_COMPARE(ip_address_, rhs.ip_address_); + KEY_COMPARE(ip_prefixlen_, rhs.ip_prefixlen_); + break; default: break; } @@ -410,7 +556,7 @@ EvpnPrefix EvpnPrefix::FromString(const string &str, } if (prefix.type_ < EvpnPrefix::AutoDiscoveryRoute || - prefix.type_ > EvpnPrefix::SegmentRoute) { + prefix.type_ > EvpnPrefix::IpPrefixRoute) { if (errorp != NULL) { *errorp = make_error_code(boost::system::errc::invalid_argument); } @@ -591,6 +737,53 @@ EvpnPrefix EvpnPrefix::FromString(const string &str, break; } + + case IpPrefixRoute: { + // Parse tag. + size_t pos3 = str.find('-', pos2 + 1); + if (pos3 == string::npos) { + if (errorp != NULL) { + *errorp = + make_error_code(boost::system::errc::invalid_argument); + } + return EvpnPrefix::kNullPrefix; + } + string tag_str = str.substr(pos2 + 1, pos3 - pos2 - 1); + bool ret = stringToInteger(tag_str, prefix.tag_); + if (!ret) { + if (errorp != NULL) { + *errorp = + make_error_code(boost::system::errc::invalid_argument); + } + return EvpnPrefix::kNullPrefix; + } + + // Parse IP prefix - first try v4, then v6. + string ip_str = str.substr(pos3 + 1, string::npos); + boost::system::error_code ip_err; + + Ip4Prefix inet_prefix = Ip4Prefix::FromString(ip_str, &ip_err); + if (ip_err == 0) { + prefix.family_ = Address::INET; + prefix.ip_address_ = inet_prefix.addr(); + prefix.ip_prefixlen_ = inet_prefix.prefixlen(); + return prefix; + } + + Inet6Prefix inet6_prefix = Inet6Prefix::FromString(ip_str, &ip_err); + if (ip_err == 0) { + prefix.family_ = Address::INET6; + prefix.ip_address_ = inet6_prefix.addr(); + prefix.ip_prefixlen_ = inet6_prefix.prefixlen(); + return prefix; + } + + if (errorp != NULL) { + *errorp = make_error_code(boost::system::errc::invalid_argument); + } + return EvpnPrefix::kNullPrefix; + break; + } } return prefix; @@ -617,6 +810,14 @@ string EvpnPrefix::ToString() const { str += "-" + esi_.ToString(); str += "-" + ip_address_.to_string(); break; + case IpPrefixRoute: + str += "-" + integerToString(tag_); + if (family_ == Address::INET) { + str += "-" + inet_prefix().ToString(); + } else { + str += "-" + inet6_prefix().ToString(); + } + break; default: break; } @@ -644,27 +845,28 @@ uint8_t EvpnPrefix::ip_address_length() const { size_t EvpnPrefix::GetIpAddressSize() const { if (family_ == Address::INET) - return 4; + return kIp4AddrSize; if (family_ == Address::INET6) - return 16; + return kIp6AddrSize; return 0; } void EvpnPrefix::ReadIpAddress(const BgpProtoPrefix &proto_prefix, - size_t ip_offset, size_t ip_size) { + size_t ip_offset, size_t ip_size, size_t ip_psize) { + assert(ip_psize <= ip_size); if (ip_size == 0) { family_ = Address::UNSPEC; - } else if (ip_size == 4) { + } else if (ip_size == kIp4AddrSize) { family_ = Address::INET; - Ip4Address::bytes_type bytes; + Ip4Address::bytes_type bytes = { { 0 } }; copy(proto_prefix.prefix.begin() + ip_offset, - proto_prefix.prefix.begin() + ip_offset + ip_size, bytes.begin()); + proto_prefix.prefix.begin() + ip_offset + ip_psize, bytes.begin()); ip_address_ = Ip4Address(bytes); - } else if (ip_size == 16) { + } else if (ip_size == kIp6AddrSize) { family_ = Address::INET6; - Ip6Address::bytes_type bytes; + Ip6Address::bytes_type bytes = { { 0 } }; copy(proto_prefix.prefix.begin() + ip_offset, - proto_prefix.prefix.begin() + ip_offset + ip_size, bytes.begin()); + proto_prefix.prefix.begin() + ip_offset + ip_psize, bytes.begin()); ip_address_ = Ip6Address(bytes); } } @@ -673,11 +875,11 @@ void EvpnPrefix::WriteIpAddress(BgpProtoPrefix *proto_prefix, size_t ip_offset) const { if (family_ == Address::INET) { const Ip4Address::bytes_type &bytes = ip_address_.to_v4().to_bytes(); - copy(bytes.begin(), bytes.begin() + 4, + copy(bytes.begin(), bytes.begin() + kIp4AddrSize, proto_prefix->prefix.begin() + ip_offset); } else if (family_ == Address::INET6) { const Ip6Address::bytes_type &bytes = ip_address_.to_v6().to_bytes(); - copy(bytes.begin(), bytes.begin() + 16, + copy(bytes.begin(), bytes.begin() + kIp6AddrSize, proto_prefix->prefix.begin() + ip_offset); } } @@ -739,6 +941,9 @@ bool EvpnRoute::IsValid() const { case EvpnPrefix::SegmentRoute: { return false; } + case EvpnPrefix::IpPrefixRoute: { + return false; + } default: { break; } diff --git a/src/bgp/evpn/evpn_route.h b/src/bgp/evpn/evpn_route.h index 6103c4ef315..2cae00729e5 100644 --- a/src/bgp/evpn/evpn_route.h +++ b/src/bgp/evpn/evpn_route.h @@ -12,6 +12,7 @@ #include "bgp/bgp_route.h" #include "bgp/inet/inet_route.h" +#include "bgp/inet6/inet6_route.h" #include "net/address.h" #include "net/bgp_af.h" #include "net/esi.h" @@ -31,19 +32,24 @@ class EvpnPrefix { static const size_t kRdSize; static const size_t kEsiSize; static const size_t kTagSize; + static const size_t kIp4AddrSize; + static const size_t kIp6AddrSize; static const size_t kMacSize; static const size_t kLabelSize; static const size_t kMinAutoDiscoveryRouteSize; static const size_t kMinMacAdvertisementRouteSize; static const size_t kMinInclusiveMulticastRouteSize; static const size_t kMinSegmentRouteSize; + static const size_t kMinInetPrefixRouteSize; + static const size_t kMinInet6PrefixRouteSize; enum RouteType { Unspecified = 0, AutoDiscoveryRoute = 1, MacAdvertisementRoute = 2, InclusiveMulticastRoute = 3, - SegmentRoute = 4 + SegmentRoute = 4, + IpPrefixRoute = 5 }; EvpnPrefix(); @@ -57,6 +63,8 @@ class EvpnPrefix { const IpAddress &ip_address); EvpnPrefix(const RouteDistinguisher &rd, const EthernetSegmentId &esi, const IpAddress &ip_address); + EvpnPrefix(const RouteDistinguisher &rd, uint32_t tag, + const IpAddress &ip_address, uint8_t ip_prefixlen); void BuildProtoPrefix(const BgpAttr *attr, uint32_t label, BgpProtoPrefix *proto_prefix) const; @@ -80,6 +88,13 @@ class EvpnPrefix { Address::Family family() const { return family_; } IpAddress ip_address() const { return ip_address_; } uint8_t ip_address_length() const; + uint8_t ip_prefix_length() const { return ip_prefixlen_; } + Ip4Prefix inet_prefix() const { + return Ip4Prefix(ip_address_.to_v4(), ip_prefixlen_); + } + Inet6Prefix inet6_prefix() const { + return Inet6Prefix(ip_address_.to_v6(), ip_prefixlen_); + } void set_route_distinguisher(const RouteDistinguisher &rd) { rd_ = rd; } private: @@ -90,10 +105,11 @@ class EvpnPrefix { MacAddress mac_addr_; Address::Family family_; IpAddress ip_address_; + uint8_t ip_prefixlen_; size_t GetIpAddressSize() const; void ReadIpAddress(const BgpProtoPrefix &proto_prefix, - size_t ip_size, size_t ip_offset); + size_t ip_offset, size_t ip_size, size_t ip_psize); void WriteIpAddress(BgpProtoPrefix *proto_prefix, size_t ip_offset) const; }; diff --git a/src/bgp/evpn/evpn_table.cc b/src/bgp/evpn/evpn_table.cc index 1c5d724eb2e..e79b6ede8e5 100644 --- a/src/bgp/evpn/evpn_table.cc +++ b/src/bgp/evpn/evpn_table.cc @@ -136,6 +136,8 @@ BgpRoute *EvpnTable::RouteReplicate(BgpServer *server, return NULL; if (evpn_prefix.type() == EvpnPrefix::SegmentRoute) return NULL; + if (evpn_prefix.type() == EvpnPrefix::IpPrefixRoute) + return NULL; if (evpn_prefix.type() == EvpnPrefix::MacAdvertisementRoute && evpn_prefix.mac_addr().IsBroadcast()) return NULL; diff --git a/src/bgp/evpn/test/evpn_prefix_test.cc b/src/bgp/evpn/test/evpn_prefix_test.cc index bb63550939e..4ea71a19b6f 100644 --- a/src/bgp/evpn/test/evpn_prefix_test.cc +++ b/src/bgp/evpn/test/evpn_prefix_test.cc @@ -2350,6 +2350,560 @@ TEST_F(EvpnSegmentPrefixTest, FromProtoPrefix_Error4) { } } +class EvpnIpPrefixTest : public EvpnPrefixTest { +}; + +TEST_F(EvpnIpPrefixTest, BuildPrefix1) { + boost::system::error_code ec; + RouteDistinguisher rd(RouteDistinguisher::FromString("10.1.1.1:65535")); + Ip4Address ip4_addr = Ip4Address::from_string("192.1.1.1", ec); + uint8_t plen = 32; + + string temp1("5-10.1.1.1:65535-"); + string temp2("-192.1.1.1/32"); + uint32_t tag_list[] = { 0, 100, 128, 4094, 65536 }; + BOOST_FOREACH(uint32_t tag, tag_list) { + EvpnPrefix prefix(rd, tag, ip4_addr, plen); + string prefix_str = temp1 + integerToString(tag) + temp2; + EXPECT_EQ(prefix_str, prefix.ToString()); + EXPECT_EQ(EvpnPrefix::IpPrefixRoute, prefix.type()); + EXPECT_EQ("10.1.1.1:65535", prefix.route_distinguisher().ToString()); + EXPECT_EQ(tag, prefix.tag()); + EXPECT_EQ(Address::INET, prefix.family()); + EXPECT_EQ("192.1.1.1", prefix.ip_address().to_string()); + EXPECT_EQ(plen, prefix.ip_prefix_length()); + } +} + +TEST_F(EvpnIpPrefixTest, BuildPrefix2) { + boost::system::error_code ec; + RouteDistinguisher rd(RouteDistinguisher::FromString("10.1.1.1:65535")); + Ip4Address ip4_addr = Ip4Address::from_string("192.1.1.0", ec); + uint8_t plen = 24; + + string temp1("5-10.1.1.1:65535-"); + string temp2("-192.1.1.0/24"); + uint32_t tag_list[] = { 0, 100, 128, 4094, 65536 }; + BOOST_FOREACH(uint32_t tag, tag_list) { + EvpnPrefix prefix(rd, tag, ip4_addr, plen); + string prefix_str = temp1 + integerToString(tag) + temp2; + EXPECT_EQ(prefix_str, prefix.ToString()); + EXPECT_EQ(EvpnPrefix::IpPrefixRoute, prefix.type()); + EXPECT_EQ("10.1.1.1:65535", prefix.route_distinguisher().ToString()); + EXPECT_EQ(tag, prefix.tag()); + EXPECT_EQ(Address::INET, prefix.family()); + EXPECT_EQ("192.1.1.0", prefix.ip_address().to_string()); + EXPECT_EQ(plen, prefix.ip_prefix_length()); + } +} + +TEST_F(EvpnIpPrefixTest, BuildPrefix3) { + boost::system::error_code ec; + RouteDistinguisher rd(RouteDistinguisher::FromString("10.1.1.1:65535")); + Ip6Address ip6_addr = Ip6Address::from_string("2001:db8:0:9::1", ec); + uint8_t plen = 128; + + string temp1("5-10.1.1.1:65535-"); + string temp2("-2001:db8:0:9::1/128"); + uint32_t tag_list[] = { 0, 100, 128, 4094, 65536 }; + BOOST_FOREACH(uint32_t tag, tag_list) { + EvpnPrefix prefix(rd, tag, ip6_addr, plen); + string prefix_str = temp1 + integerToString(tag) + temp2; + EXPECT_EQ(prefix_str, prefix.ToString()); + EXPECT_EQ(EvpnPrefix::IpPrefixRoute, prefix.type()); + EXPECT_EQ("10.1.1.1:65535", prefix.route_distinguisher().ToString()); + EXPECT_EQ(tag, prefix.tag()); + EXPECT_EQ(Address::INET6, prefix.family()); + EXPECT_EQ("2001:db8:0:9::1", prefix.ip_address().to_string()); + EXPECT_EQ(plen, prefix.ip_prefix_length()); + } +} + +TEST_F(EvpnIpPrefixTest, BuildPrefix4) { + boost::system::error_code ec; + RouteDistinguisher rd(RouteDistinguisher::FromString("10.1.1.1:65535")); + Ip6Address ip6_addr = Ip6Address::from_string("2001:db8:0:9::0", ec); + uint8_t plen = 120; + + string temp1("5-10.1.1.1:65535-"); + string temp2("-2001:db8:0:9::/120"); + uint32_t tag_list[] = { 0, 100, 128, 4094, 65536 }; + BOOST_FOREACH(uint32_t tag, tag_list) { + EvpnPrefix prefix(rd, tag, ip6_addr, plen); + string prefix_str = temp1 + integerToString(tag) + temp2; + EXPECT_EQ(prefix_str, prefix.ToString()); + EXPECT_EQ(EvpnPrefix::IpPrefixRoute, prefix.type()); + EXPECT_EQ("10.1.1.1:65535", prefix.route_distinguisher().ToString()); + EXPECT_EQ(tag, prefix.tag()); + EXPECT_EQ(Address::INET6, prefix.family()); + EXPECT_EQ("2001:db8:0:9::", prefix.ip_address().to_string()); + EXPECT_EQ(plen, prefix.ip_prefix_length()); + } +} + +TEST_F(EvpnIpPrefixTest, ParsePrefix1) { + uint8_t plen = 32; + string temp1("5-10.1.1.1:65535-"); + string temp2("-192.1.1.1/32"); + uint32_t tag_list[] = { 0, 100, 128, 4094, 65536 }; + BOOST_FOREACH(uint32_t tag, tag_list) { + boost::system::error_code ec; + string prefix_str = temp1 + integerToString(tag) + temp2; + EvpnPrefix prefix(EvpnPrefix::FromString(prefix_str, &ec)); + EXPECT_EQ(0, ec.value()); + EXPECT_EQ(prefix_str, prefix.ToString()); + EXPECT_EQ(EvpnPrefix::IpPrefixRoute, prefix.type()); + EXPECT_EQ("10.1.1.1:65535", prefix.route_distinguisher().ToString()); + EXPECT_EQ(tag, prefix.tag()); + EXPECT_EQ(Address::INET, prefix.family()); + EXPECT_EQ("192.1.1.1", prefix.ip_address().to_string()); + EXPECT_EQ(plen, prefix.ip_prefix_length()); + } +} + +TEST_F(EvpnIpPrefixTest, ParsePrefix2) { + uint8_t plen = 24; + string temp1("5-10.1.1.1:65535-"); + string temp2("-192.1.1.1/24"); + string temp2_alt("-192.1.1.0/24"); + uint32_t tag_list[] = { 0, 100, 128, 4094, 65536 }; + BOOST_FOREACH(uint32_t tag, tag_list) { + boost::system::error_code ec; + string prefix_str = temp1 + integerToString(tag) + temp2; + string prefix_str_alt = temp1 + integerToString(tag) + temp2_alt; + EvpnPrefix prefix(EvpnPrefix::FromString(prefix_str, &ec)); + EXPECT_EQ(0, ec.value()); + EXPECT_EQ(prefix_str_alt, prefix.ToString()); + EXPECT_EQ(EvpnPrefix::IpPrefixRoute, prefix.type()); + EXPECT_EQ("10.1.1.1:65535", prefix.route_distinguisher().ToString()); + EXPECT_EQ(tag, prefix.tag()); + EXPECT_EQ(Address::INET, prefix.family()); + EXPECT_EQ("192.1.1.0", prefix.ip_address().to_string()); + EXPECT_EQ(plen, prefix.ip_prefix_length()); + } +} + +TEST_F(EvpnIpPrefixTest, ParsePrefix3) { + uint8_t plen = 128; + string temp1("5-10.1.1.1:65535-"); + string temp2("-2001:db8:0:9::1/128"); + uint32_t tag_list[] = { 0, 100, 128, 4094, 65536 }; + BOOST_FOREACH(uint32_t tag, tag_list) { + boost::system::error_code ec; + string prefix_str = temp1 + integerToString(tag) + temp2; + EvpnPrefix prefix(EvpnPrefix::FromString(prefix_str, &ec)); + EXPECT_EQ(0, ec.value()); + EXPECT_EQ(prefix_str, prefix.ToString()); + EXPECT_EQ(EvpnPrefix::IpPrefixRoute, prefix.type()); + EXPECT_EQ("10.1.1.1:65535", prefix.route_distinguisher().ToString()); + EXPECT_EQ(tag, prefix.tag()); + EXPECT_EQ(Address::INET6, prefix.family()); + EXPECT_EQ("2001:db8:0:9::1", prefix.ip_address().to_string()); + EXPECT_EQ(plen, prefix.ip_prefix_length()); + } +} + +TEST_F(EvpnIpPrefixTest, ParsePrefix4) { + uint8_t plen = 120; + string temp1("5-10.1.1.1:65535-"); + string temp2("-2001:db8:0:9::1/120"); + string temp2_alt("-2001:db8:0:9::/120"); + uint32_t tag_list[] = { 0, 100, 128, 4094, 65536 }; + BOOST_FOREACH(uint32_t tag, tag_list) { + boost::system::error_code ec; + string prefix_str = temp1 + integerToString(tag) + temp2; + string prefix_str_alt = temp1 + integerToString(tag) + temp2_alt; + EvpnPrefix prefix(EvpnPrefix::FromString(prefix_str, &ec)); + EXPECT_EQ(0, ec.value()); + EXPECT_EQ(prefix_str_alt, prefix.ToString()); + EXPECT_EQ(EvpnPrefix::IpPrefixRoute, prefix.type()); + EXPECT_EQ("10.1.1.1:65535", prefix.route_distinguisher().ToString()); + EXPECT_EQ(tag, prefix.tag()); + EXPECT_EQ(Address::INET6, prefix.family()); + EXPECT_EQ("2001:db8:0:9::", prefix.ip_address().to_string()); + EXPECT_EQ(plen, prefix.ip_prefix_length()); + } +} + +// No dashes. +TEST_F(EvpnIpPrefixTest, ParsePrefix_Error1) { + boost::system::error_code ec; + string prefix_str("5+10.1.1.1:65535+100+192.1.1.1/24"); + EvpnPrefix prefix(EvpnPrefix::FromString(prefix_str, &ec)); + EXPECT_NE(0, ec.value()); +} + +// No dashes after type delimiter. +TEST_F(EvpnIpPrefixTest, ParsePrefix_Error2) { + boost::system::error_code ec; + string prefix_str("5-10.1.1.1:65535+100+192.1.1.1/24"); + EvpnPrefix prefix(EvpnPrefix::FromString(prefix_str, &ec)); + EXPECT_NE(0, ec.value()); +} + +// Bad RD. +TEST_F(EvpnIpPrefixTest, ParsePrefix_Error3) { + boost::system::error_code ec; + string prefix_str("5-10.1.1.1:65536-100-192.1.1.1/24"); + EvpnPrefix prefix(EvpnPrefix::FromString(prefix_str, &ec)); + EXPECT_NE(0, ec.value()); +} + +// No dashes after RD delimiter. +TEST_F(EvpnIpPrefixTest, ParsePrefix_Error4) { + boost::system::error_code ec; + string prefix_str("5-10.1.1.1:65535+100+192.1.1.1/24"); + EvpnPrefix prefix(EvpnPrefix::FromString(prefix_str, &ec)); + EXPECT_NE(0, ec.value()); +} + +// No dashes after tag delimiter. +TEST_F(EvpnIpPrefixTest, ParsePrefix_Error5) { + boost::system::error_code ec; + string prefix_str("5-10.1.1.1:65535-100+192.1.1.1/24"); + EvpnPrefix prefix(EvpnPrefix::FromString(prefix_str, &ec)); + EXPECT_NE(0, ec.value()); +} + +// Bad tag. +TEST_F(EvpnIpPrefixTest, ParsePrefix_Error6) { + boost::system::error_code ec; + string prefix_str("5-10.1.1.1:65535-100x-192.1.1.1/24"); + EvpnPrefix prefix(EvpnPrefix::FromString(prefix_str, &ec)); + EXPECT_NE(0, ec.value()); +} + +// Bad IPv4 prefix. +TEST_F(EvpnIpPrefixTest, ParsePrefix_Error7) { + boost::system::error_code ec; + string prefix_str("5-10.1.1.1:65535-100-192.1.1.x/24"); + EvpnPrefix prefix(EvpnPrefix::FromString(prefix_str, &ec)); + EXPECT_NE(0, ec.value()); +} + +// Bad IPv6 prefix. +TEST_F(EvpnIpPrefixTest, ParsePrefix_Error8) { + boost::system::error_code ec; + string prefix_str("5-10.1.1.1:65535-100-2001:db8:0:9::x/120"); + EvpnPrefix prefix(EvpnPrefix::FromString(prefix_str, &ec)); + EXPECT_NE(0, ec.value()); +} + +TEST_F(EvpnIpPrefixTest, FromProtoPrefix1) { + string temp1("5-10.1.1.1:65535-"); + string temp2("-192.1.1.1/32"); + uint32_t tag_list[] = { 0, 100, 128, 4094, 65536 }; + BOOST_FOREACH(uint32_t tag, tag_list) { + boost::system::error_code ec; + string prefix_str = temp1 + integerToString(tag) + temp2; + EvpnPrefix prefix1(EvpnPrefix::FromString(prefix_str, &ec)); + EXPECT_EQ(0, ec.value()); + + TunnelEncap tunnel_encap(TunnelEncapType::VXLAN); + ExtCommunitySpec comm_spec; + comm_spec.communities.push_back(tunnel_encap.GetExtCommunityValue()); + BgpAttrSpec attr_spec; + attr_spec.push_back(&comm_spec); + BgpAttrPtr attr = bs_->attr_db()->Locate(attr_spec); + + uint32_t label1 = 10000; + BgpProtoPrefix proto_prefix; + prefix1.BuildProtoPrefix(attr.get(), label1, &proto_prefix); + EXPECT_EQ(EvpnPrefix::IpPrefixRoute, proto_prefix.type); + EXPECT_EQ((EvpnPrefix::kMinInetPrefixRouteSize + 3) * 8, + proto_prefix.prefixlen); + EXPECT_EQ(EvpnPrefix::kMinInetPrefixRouteSize + 3, + proto_prefix.prefix.size()); + + EvpnPrefix prefix2; + BgpAttrPtr attr_out2; + uint32_t label2; + int result = EvpnPrefix::FromProtoPrefix(bs_.get(), + proto_prefix, attr.get(), &prefix2, &attr_out2, &label2); + EXPECT_EQ(0, result); + EXPECT_EQ(prefix1, prefix2); + EXPECT_TRUE(attr_out2->esi().IsZero()); + EXPECT_EQ(attr.get(), attr_out2.get()); + EXPECT_EQ(10000, label2); + } +} + +TEST_F(EvpnIpPrefixTest, FromProtoPrefix2) { + string temp1("5-10.1.1.1:65535-"); + string temp2("-192.1.1.1/24"); + uint32_t tag_list[] = { 0, 100, 128, 4094, 65536 }; + BOOST_FOREACH(uint32_t tag, tag_list) { + boost::system::error_code ec; + string prefix_str = temp1 + integerToString(tag) + temp2; + EvpnPrefix prefix1(EvpnPrefix::FromString(prefix_str, &ec)); + EXPECT_EQ(0, ec.value()); + + TunnelEncap tunnel_encap(TunnelEncapType::VXLAN); + ExtCommunitySpec comm_spec; + comm_spec.communities.push_back(tunnel_encap.GetExtCommunityValue()); + BgpAttrSpec attr_spec; + attr_spec.push_back(&comm_spec); + BgpAttrPtr attr = bs_->attr_db()->Locate(attr_spec); + + uint32_t label1 = 10000; + BgpProtoPrefix proto_prefix; + prefix1.BuildProtoPrefix(attr.get(), label1, &proto_prefix); + EXPECT_EQ(EvpnPrefix::IpPrefixRoute, proto_prefix.type); + EXPECT_EQ((EvpnPrefix::kMinInetPrefixRouteSize + 3) * 8, + proto_prefix.prefixlen); + EXPECT_EQ(EvpnPrefix::kMinInetPrefixRouteSize + 3, + proto_prefix.prefix.size()); + + EvpnPrefix prefix2; + BgpAttrPtr attr_out2; + uint32_t label2; + int result = EvpnPrefix::FromProtoPrefix(bs_.get(), + proto_prefix, attr.get(), &prefix2, &attr_out2, &label2); + EXPECT_EQ(0, result); + EXPECT_EQ(prefix1, prefix2); + EXPECT_TRUE(attr_out2->esi().IsZero()); + EXPECT_EQ(attr.get(), attr_out2.get()); + EXPECT_EQ(10000, label2); + } +} + +// Incorrect size for Ipv4 prefix update. +TEST_F(EvpnIpPrefixTest, FromProtoPrefix_Error1) { + BgpProtoPrefix proto_prefix; + proto_prefix.type = EvpnPrefix::IpPrefixRoute; + + size_t max_nlri_size = EvpnPrefix::kMinInetPrefixRouteSize + + EvpnPrefix::kLabelSize; + for (size_t nlri_size = 0; nlri_size < max_nlri_size; ++nlri_size) { + proto_prefix.prefix.clear(); + proto_prefix.prefix.resize(nlri_size, 0); + EvpnPrefix prefix; + BgpAttrPtr attr_in(new BgpAttr(bs_->attr_db())); + BgpAttrPtr attr_out; + uint32_t label; + int result = EvpnPrefix::FromProtoPrefix(bs_.get(), + proto_prefix, attr_in.get(), &prefix, &attr_out, &label); + EXPECT_NE(0, result); + } +} + +// Incorrect size for Ipv4 prefix withdraw. +TEST_F(EvpnIpPrefixTest, FromProtoPrefix_Error2) { + BgpProtoPrefix proto_prefix; + proto_prefix.type = EvpnPrefix::IpPrefixRoute; + + size_t max_nlri_size = EvpnPrefix::kMinInetPrefixRouteSize + + EvpnPrefix::kLabelSize; + for (size_t nlri_size = 0; nlri_size <= max_nlri_size; ++nlri_size) { + if (nlri_size == EvpnPrefix::kMinInetPrefixRouteSize) { + continue; + } + if (nlri_size == + EvpnPrefix::kMinInetPrefixRouteSize + EvpnPrefix::kLabelSize) { + continue; + } + proto_prefix.prefix.clear(); + proto_prefix.prefix.resize(nlri_size, 0); + EvpnPrefix prefix; + BgpAttrPtr attr_out; + uint32_t label; + int result = EvpnPrefix::FromProtoPrefix(bs_.get(), + proto_prefix, NULL, &prefix, &attr_out, &label); + EXPECT_NE(0, result); + } +} + +// Incorrect size for Ipv6 prefix update. +TEST_F(EvpnIpPrefixTest, FromProtoPrefix_Error3) { + BgpProtoPrefix proto_prefix; + proto_prefix.type = EvpnPrefix::IpPrefixRoute; + + size_t max_nlri_size = EvpnPrefix::kMinInet6PrefixRouteSize + + EvpnPrefix::kLabelSize; + for (size_t nlri_size = 0; nlri_size < max_nlri_size; ++nlri_size) { + if (nlri_size == + EvpnPrefix::kMinInetPrefixRouteSize + EvpnPrefix::kLabelSize) { + continue; + } + proto_prefix.prefix.clear(); + proto_prefix.prefix.resize(nlri_size, 0); + EvpnPrefix prefix; + BgpAttrPtr attr_in(new BgpAttr(bs_->attr_db())); + BgpAttrPtr attr_out; + uint32_t label; + int result = EvpnPrefix::FromProtoPrefix(bs_.get(), + proto_prefix, attr_in.get(), &prefix, &attr_out, &label); + EXPECT_NE(0, result); + } +} + +// Incorrect size for Ipv6 prefix withdraw. +TEST_F(EvpnIpPrefixTest, FromProtoPrefix_Error4) { + BgpProtoPrefix proto_prefix; + proto_prefix.type = EvpnPrefix::IpPrefixRoute; + + size_t max_nlri_size = EvpnPrefix::kMinInet6PrefixRouteSize + + EvpnPrefix::kLabelSize; + for (size_t nlri_size = 0; nlri_size <= max_nlri_size; ++nlri_size) { + if (nlri_size == EvpnPrefix::kMinInetPrefixRouteSize) { + continue; + } + if (nlri_size == + EvpnPrefix::kMinInetPrefixRouteSize + EvpnPrefix::kLabelSize) { + continue; + } + if (nlri_size == EvpnPrefix::kMinInet6PrefixRouteSize) { + continue; + } + if (nlri_size == + EvpnPrefix::kMinInet6PrefixRouteSize + EvpnPrefix::kLabelSize) { + continue; + } + proto_prefix.prefix.clear(); + proto_prefix.prefix.resize(nlri_size, 0); + EvpnPrefix prefix; + BgpAttrPtr attr_out; + uint32_t label; + int result = EvpnPrefix::FromProtoPrefix(bs_.get(), + proto_prefix, NULL, &prefix, &attr_out, &label); + EXPECT_NE(0, result); + } +} + +// Bad IPv4 prefix length. +TEST_F(EvpnIpPrefixTest, FromProtoPrefix_Error5) { + BgpProtoPrefix proto_prefix; + proto_prefix.type = EvpnPrefix::IpPrefixRoute; + size_t nlri_size = EvpnPrefix::kMinInetPrefixRouteSize + + EvpnPrefix::kLabelSize; + proto_prefix.prefix.resize(nlri_size, 0); + size_t ip_plen_offset = + EvpnPrefix::kRdSize + EvpnPrefix::kEsiSize + EvpnPrefix::kTagSize; + + for (uint16_t ip_len = 33; ip_len <= 255; ++ip_len) { + EvpnPrefix prefix; + BgpAttrPtr attr_in(new BgpAttr(bs_->attr_db())); + BgpAttrPtr attr_out; + uint32_t label; + proto_prefix.prefix[ip_plen_offset] = ip_len; + int result = EvpnPrefix::FromProtoPrefix(bs_.get(), + proto_prefix, attr_in.get(), &prefix, &attr_out, &label); + EXPECT_NE(0, result); + } +} + +// Bad IPv6 prefix length. +TEST_F(EvpnIpPrefixTest, FromProtoPrefix_Error6) { + BgpProtoPrefix proto_prefix; + proto_prefix.type = EvpnPrefix::IpPrefixRoute; + size_t nlri_size = EvpnPrefix::kMinInet6PrefixRouteSize + + EvpnPrefix::kLabelSize; + proto_prefix.prefix.resize(nlri_size, 0); + size_t ip_plen_offset = + EvpnPrefix::kRdSize + EvpnPrefix::kEsiSize + EvpnPrefix::kTagSize; + + for (uint16_t ip_len = 129; ip_len <= 255; ++ip_len) { + EvpnPrefix prefix; + BgpAttrPtr attr_in(new BgpAttr(bs_->attr_db())); + BgpAttrPtr attr_out; + uint32_t label; + proto_prefix.prefix[ip_plen_offset] = ip_len; + int result = EvpnPrefix::FromProtoPrefix(bs_.get(), + proto_prefix, attr_in.get(), &prefix, &attr_out, &label); + EXPECT_NE(0, result); + } +} + +// Non-zero ESI with Ipv4 prefix. +TEST_F(EvpnIpPrefixTest, FromProtoPrefix_Error7) { + BgpProtoPrefix proto_prefix; + proto_prefix.type = EvpnPrefix::IpPrefixRoute; + size_t nlri_size = EvpnPrefix::kMinInetPrefixRouteSize + + EvpnPrefix::kLabelSize; + proto_prefix.prefix.resize(nlri_size, 0); + size_t esi_offset = EvpnPrefix::kRdSize; + + for (size_t idx = 0; idx < EvpnPrefix::kEsiSize; ++idx) { + EvpnPrefix prefix; + BgpAttrPtr attr_in(new BgpAttr(bs_->attr_db())); + BgpAttrPtr attr_out; + uint32_t label; + proto_prefix.prefix[esi_offset + idx] = 0x01; + int result = EvpnPrefix::FromProtoPrefix(bs_.get(), + proto_prefix, attr_in.get(), &prefix, &attr_out, &label); + EXPECT_NE(0, result); + proto_prefix.prefix[esi_offset + idx] = 0x00; + } +} + +// Non-zero ESI with Ipv6 prefix. +TEST_F(EvpnIpPrefixTest, FromProtoPrefix_Error8) { + BgpProtoPrefix proto_prefix; + proto_prefix.type = EvpnPrefix::IpPrefixRoute; + size_t nlri_size = EvpnPrefix::kMinInet6PrefixRouteSize + + EvpnPrefix::kLabelSize; + proto_prefix.prefix.resize(nlri_size, 0); + size_t esi_offset = EvpnPrefix::kRdSize; + + for (size_t idx = 0; idx < EvpnPrefix::kEsiSize; ++idx) { + EvpnPrefix prefix; + BgpAttrPtr attr_in(new BgpAttr(bs_->attr_db())); + BgpAttrPtr attr_out; + uint32_t label; + proto_prefix.prefix[esi_offset + idx] = 0x01; + int result = EvpnPrefix::FromProtoPrefix(bs_.get(), + proto_prefix, attr_in.get(), &prefix, &attr_out, &label); + EXPECT_NE(0, result); + proto_prefix.prefix[esi_offset + idx] = 0x00; + } +} + +// Non-zero IPv4 gateway. +TEST_F(EvpnIpPrefixTest, FromProtoPrefix_Error9) { + BgpProtoPrefix proto_prefix; + proto_prefix.type = EvpnPrefix::IpPrefixRoute; + size_t nlri_size = EvpnPrefix::kMinInetPrefixRouteSize + + EvpnPrefix::kLabelSize; + proto_prefix.prefix.resize(nlri_size, 0); + size_t gw_offset = EvpnPrefix::kRdSize + EvpnPrefix::kEsiSize + + EvpnPrefix::kTagSize + 1 + EvpnPrefix::kIp4AddrSize; + + for (size_t idx = 0; idx < EvpnPrefix::kIp4AddrSize; ++idx) { + EvpnPrefix prefix; + BgpAttrPtr attr_in(new BgpAttr(bs_->attr_db())); + BgpAttrPtr attr_out; + uint32_t label; + proto_prefix.prefix[gw_offset + idx] = 0x01; + int result = EvpnPrefix::FromProtoPrefix(bs_.get(), + proto_prefix, attr_in.get(), &prefix, &attr_out, &label); + EXPECT_NE(0, result); + proto_prefix.prefix[gw_offset + idx] = 0x00; + } +} + +// Non-zero IPv6 gateway. +TEST_F(EvpnIpPrefixTest, FromProtoPrefix_Error10) { + BgpProtoPrefix proto_prefix; + proto_prefix.type = EvpnPrefix::IpPrefixRoute; + size_t nlri_size = EvpnPrefix::kMinInet6PrefixRouteSize + + EvpnPrefix::kLabelSize; + proto_prefix.prefix.resize(nlri_size, 0); + size_t gw_offset = EvpnPrefix::kRdSize + EvpnPrefix::kEsiSize + + EvpnPrefix::kTagSize + 1 + EvpnPrefix::kIp6AddrSize; + + for (size_t idx = 0; idx < EvpnPrefix::kIp6AddrSize; ++idx) { + EvpnPrefix prefix; + BgpAttrPtr attr_in(new BgpAttr(bs_->attr_db())); + BgpAttrPtr attr_out; + uint32_t label; + proto_prefix.prefix[gw_offset + idx] = 0x01; + int result = EvpnPrefix::FromProtoPrefix(bs_.get(), + proto_prefix, attr_in.get(), &prefix, &attr_out, &label); + EXPECT_NE(0, result); + proto_prefix.prefix[gw_offset + idx] = 0x00; + } +} + int main(int argc, char **argv) { bgp_log_test::init(); ::testing::InitGoogleTest(&argc, argv); diff --git a/src/bgp/evpn/test/evpn_route_test.cc b/src/bgp/evpn/test/evpn_route_test.cc index 3d54b8bf8af..6506c60fb9f 100644 --- a/src/bgp/evpn/test/evpn_route_test.cc +++ b/src/bgp/evpn/test/evpn_route_test.cc @@ -197,6 +197,54 @@ TEST_F(EvpnSegmentRouteTest, GetDBRequestKey) { EXPECT_EQ(prefix, key->prefix); } +class EvpnIpPrefixRouteTest : public EvpnRouteTest { +}; + +TEST_F(EvpnIpPrefixRouteTest, ToString) { + string temp1("5-10.1.1.1:65535-"); + string temp2("-192.1.1.1/32"); + uint32_t tag_list[] = { 0, 100, 128, 4094, 65536, 4294967295 }; + BOOST_FOREACH(uint32_t tag, tag_list) { + string prefix_str = temp1 + integerToString(tag) + temp2; + EvpnPrefix prefix(EvpnPrefix::FromString(prefix_str)); + EvpnRoute route(prefix); + EXPECT_EQ(prefix, route.GetPrefix()); + EXPECT_EQ(prefix_str, route.ToString()); + } +} + +TEST_F(EvpnIpPrefixRouteTest, SetKey) { + EvpnPrefix null_prefix; + string temp1("5-10.1.1.1:65535-"); + string temp2("-192.1.1.1/32"); + uint32_t tag_list[] = { 0, 100, 128, 4094, 65536, 4294967295 }; + BOOST_FOREACH(uint32_t tag, tag_list) { + EvpnRoute route(null_prefix); + string prefix_str = temp1 + integerToString(tag) + temp2; + EvpnPrefix prefix(EvpnPrefix::FromString(prefix_str)); + boost::scoped_ptr key( + new EvpnTable::RequestKey(prefix, NULL)); + route.SetKey(key.get()); + EXPECT_EQ(prefix, key->prefix); + EXPECT_EQ(prefix, route.GetPrefix()); + } +} + +TEST_F(EvpnIpPrefixRouteTest, GetDBRequestKey) { + string temp1("5-10.1.1.1:65535-"); + string temp2("-192.1.1.1/32"); + uint32_t tag_list[] = { 0, 100, 128, 4094, 65536, 4294967295 }; + BOOST_FOREACH(uint32_t tag, tag_list) { + string prefix_str = temp1 + integerToString(tag) + temp2; + EvpnPrefix prefix(EvpnPrefix::FromString(prefix_str)); + EvpnRoute route(prefix); + DBEntryBase::KeyPtr keyptr = route.GetDBRequestKey(); + const EvpnTable::RequestKey *key = + static_cast(keyptr.get()); + EXPECT_EQ(prefix, key->prefix); + } +} + int main(int argc, char **argv) { bgp_log_test::init(); ::testing::InitGoogleTest(&argc, argv);