diff --git a/src/bgp/bgp_attr_base.cc b/src/bgp/bgp_attr_base.cc index e8fcdd1b1f0..aecadcbd7a6 100644 --- a/src/bgp/bgp_attr_base.cc +++ b/src/bgp/bgp_attr_base.cc @@ -11,16 +11,32 @@ const size_t BgpProtoPrefix::kLabelSize = 3; BgpProtoPrefix::BgpProtoPrefix() : prefixlen(0), type(0) { } -uint32_t BgpProtoPrefix::ReadLabel(size_t label_offset) const { +// +// Extract the label from the BgpProtorefix. +// EVPN extensions for VXLAN use the label to convey a 24-bit VNI. +// +uint32_t BgpProtoPrefix::ReadLabel(size_t label_offset, bool is_vni) const { assert((label_offset + kLabelSize) <= prefix.size()); + if (is_vni) + return get_value(&prefix[label_offset], kLabelSize); uint32_t label = (prefix[label_offset] << 16 | prefix[label_offset + 1] << 8 | prefix[label_offset + 2]) >> 4; return label; } -void BgpProtoPrefix::WriteLabel(size_t label_offset, uint32_t label) { +// +// Write the label to the BgpProtorefix. +// EVPN extensions for VXLAN use the label to convey a 24-bit VNI. +// +void BgpProtoPrefix::WriteLabel(size_t label_offset, uint32_t label, + bool is_vni) { assert((label_offset + kLabelSize) <= prefix.size()); + if (is_vni) { + assert(label <= 0xFFFFFF); + put_value(&prefix[label_offset], kLabelSize, label); + return; + } assert(label <= 0xFFFFF); uint32_t tmp = (label << 4 | 0x1); for (size_t idx = 0; idx < kLabelSize; ++idx) { diff --git a/src/bgp/bgp_attr_base.h b/src/bgp/bgp_attr_base.h index 41ab8298aa2..600c6a45b5e 100644 --- a/src/bgp/bgp_attr_base.h +++ b/src/bgp/bgp_attr_base.h @@ -91,8 +91,8 @@ struct BgpProtoPrefix : public ParseObject { BgpProtoPrefix(); - uint32_t ReadLabel(size_t label_offset) const; - void WriteLabel(size_t label_offset, uint32_t label); + uint32_t ReadLabel(size_t label_offset, bool is_vni = false) const; + void WriteLabel(size_t label_offset, uint32_t label, bool is_vni = false); std::vector prefix; int prefixlen; diff --git a/src/bgp/community.cc b/src/bgp/community.cc index 0f4fc10c276..d8f2fd50721 100644 --- a/src/bgp/community.cc +++ b/src/bgp/community.cc @@ -197,6 +197,20 @@ std::vector ExtCommunity::GetTunnelEncap() const { return encap_list; } +bool ExtCommunity::ContainsTunnelEncapVxlan() const { + for (ExtCommunityList::const_iterator iter = communities_.begin(); + iter != communities_.end(); ++iter) { + if (!ExtCommunity::is_tunnel_encap(*iter)) + continue; + TunnelEncap encap(*iter); + if (encap.tunnel_encap() == TunnelEncapType::VXLAN) + return true; + if (encap.tunnel_encap() == TunnelEncapType::VXLAN_CONTRAIL) + return true; + } + return false; +} + ExtCommunity::ExtCommunity(ExtCommunityDB *extcomm_db, const ExtCommunitySpec spec) : extcomm_db_(extcomm_db) { refcount_ = 0; diff --git a/src/bgp/community.h b/src/bgp/community.h index 2bd8eb2677d..126885ce2d8 100644 --- a/src/bgp/community.h +++ b/src/bgp/community.h @@ -164,6 +164,7 @@ class ExtCommunity { } std::vector GetTunnelEncap() const; + bool ContainsTunnelEncapVxlan() const; static bool is_origin_vn(const ExtCommunityValue &val) { // diff --git a/src/bgp/evpn/evpn_route.cc b/src/bgp/evpn/evpn_route.cc index e6c90ab5106..b1f3710f080 100644 --- a/src/bgp/evpn/evpn_route.cc +++ b/src/bgp/evpn/evpn_route.cc @@ -32,6 +32,33 @@ const size_t EvpnPrefix::kMinInclusiveMulticastRouteSize = const size_t EvpnPrefix::kMinSegmentRouteSize = kRdSize + kEsiSize + 1; +// +// Read label from the BgpProtoPrefix. +// If the encapsulation is VXLAN and ethernet tag is non-zero use that as +// the label for backward compatibility with older JUNOS code and forward +// compatibility with newer JUNOS and Contrail code which encodes/decodes +// the label as a 24-bit value. +// +static uint32_t ReadLabel(const BgpProtoPrefix &proto_prefix, + const BgpAttr *attr, size_t offset, uint32_t tag) { + if (!attr) + return 0; + const ExtCommunity *extcomm = attr->ext_community(); + if (extcomm && extcomm->ContainsTunnelEncapVxlan()) { + return (tag ? tag : proto_prefix.ReadLabel(offset, false)); + } else { + return proto_prefix.ReadLabel(offset, false); + } +} + +// +// Write label to the BgpProtoPrefix. +// +static void WriteLabel(BgpProtoPrefix *proto_prefix, + const BgpAttr *attr, size_t offset, uint32_t label) { + proto_prefix->WriteLabel(offset, label, false); +} + EvpnPrefix::EvpnPrefix() : type_(Unspecified), tag_(EvpnPrefix::kNullTag), family_(Address::UNSPEC) { } @@ -109,10 +136,8 @@ int EvpnPrefix::FromProtoPrefix(BgpServer *server, prefix->esi_ = EthernetSegmentId(&proto_prefix.prefix[esi_offset]); size_t tag_offset = esi_offset + kEsiSize; prefix->tag_ = get_value(&proto_prefix.prefix[tag_offset], kTagSize); - if (attr) { - size_t label_offset = tag_offset + kTagSize; - *label = proto_prefix.ReadLabel(label_offset); - } + size_t label_offset = tag_offset + kTagSize; + *label = ReadLabel(proto_prefix, attr, label_offset, prefix->tag_); break; } case MacAdvertisementRoute: { @@ -144,10 +169,8 @@ int EvpnPrefix::FromProtoPrefix(BgpServer *server, return -1; size_t ip_offset = ip_len_offset + 1; prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size); - if (attr) { - size_t label_offset = ip_offset + ip_size; - *label = proto_prefix.ReadLabel(label_offset); - } + size_t label_offset = ip_offset + ip_size; + *label = ReadLabel(proto_prefix, attr, label_offset, prefix->tag_); break; } case InclusiveMulticastRoute: { @@ -227,7 +250,7 @@ void EvpnPrefix::BuildProtoPrefix(const BgpAttr *attr, uint32_t label, size_t tag_offset = esi_offset + kEsiSize; put_value(&proto_prefix->prefix[tag_offset], kTagSize, tag_); size_t label_offset = tag_offset + kTagSize; - proto_prefix->WriteLabel(label_offset, label); + WriteLabel(proto_prefix, attr, label_offset, label); break; } case MacAdvertisementRoute: { @@ -256,7 +279,7 @@ void EvpnPrefix::BuildProtoPrefix(const BgpAttr *attr, uint32_t label, size_t ip_offset = ip_len_offset + 1; WriteIpAddress(proto_prefix, ip_offset); size_t label_offset = ip_offset + ip_size; - proto_prefix->WriteLabel(label_offset, label); + WriteLabel(proto_prefix, attr, label_offset, label); break; } case InclusiveMulticastRoute: { diff --git a/src/bgp/evpn/test/evpn_prefix_test.cc b/src/bgp/evpn/test/evpn_prefix_test.cc index 44c173b1081..cb4d48caca5 100644 --- a/src/bgp/evpn/test/evpn_prefix_test.cc +++ b/src/bgp/evpn/test/evpn_prefix_test.cc @@ -9,6 +9,7 @@ #include "bgp/evpn/evpn_route.h" #include "bgp/evpn/evpn_table.h" #include "bgp/test/bgp_server_test_util.h" +#include "bgp/tunnel_encap/tunnel_encap.h" #include "control-node/control_node.h" #include "testing/gunit.h" @@ -241,6 +242,85 @@ TEST_F(EvpnAutoDiscoveryPrefixTest, FromProtoPrefix2) { } } +// Build and parse BgpProtoPrefix for reach with VXLAN encap. +// Tag is not 0, so label should be ignored. +TEST_F(EvpnAutoDiscoveryPrefixTest, FromProtoPrefix3) { + string temp("1-10.1.1.1:65535-00:01:02:03:04:05:06:07:08:09-"); + uint32_t tag_list[] = { 32, 10000, 1048575, 16777215 }; + BOOST_FOREACH(uint32_t tag, tag_list) { + string prefix_str = temp + integerToString(tag); + boost::system::error_code ec; + 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::AutoDiscoveryRoute, proto_prefix.type); + size_t expected_size = + EvpnPrefix::kMinAutoDiscoveryRouteSize + EvpnPrefix::kLabelSize; + EXPECT_EQ(expected_size * 8, proto_prefix.prefixlen); + EXPECT_EQ(expected_size, 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(tag, label2); + } +} + +// Build and parse BgpProtoPrefix for reach with VXLAN encap. +// Tag is 0, so label should be honored. +TEST_F(EvpnAutoDiscoveryPrefixTest, FromProtoPrefix4) { + string temp("1-10.1.1.1:65535-00:01:02:03:04:05:06:07:08:09-"); + uint32_t label_list[] = { 32, 10000, 1048575 }; + BOOST_FOREACH(uint32_t label1, label_list) { + string prefix_str = temp + integerToString(0); + boost::system::error_code ec; + 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); + + BgpProtoPrefix proto_prefix; + prefix1.BuildProtoPrefix(attr.get(), label1, &proto_prefix); + EXPECT_EQ(EvpnPrefix::AutoDiscoveryRoute, proto_prefix.type); + size_t expected_size = + EvpnPrefix::kMinAutoDiscoveryRouteSize + EvpnPrefix::kLabelSize; + EXPECT_EQ(expected_size * 8, proto_prefix.prefixlen); + EXPECT_EQ(expected_size, 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(label1, label2); + } +} + // Smaller than minimum size for reach. TEST_F(EvpnAutoDiscoveryPrefixTest, FromProtoPrefix_Error1) { BgpProtoPrefix proto_prefix; @@ -770,6 +850,249 @@ TEST_F(EvpnMacAdvertisementPrefixTest, FromProtoPrefix6) { } } +// Build and parse BgpProtoPrefix for reach with VXLAN encap, w/o ip. +// Tag is not 0, so label should be ignored. +TEST_F(EvpnMacAdvertisementPrefixTest, FromProtoPrefix7) { + string temp1("2-10.1.1.1:65535-"); + string temp2("-11:12:13:14:15:16,0.0.0.0"); + uint32_t tag_list[] = { 32, 10000, 1048575, 16777215 }; + BOOST_FOREACH(uint32_t tag, tag_list) { + string prefix_str = temp1 + integerToString(tag) + temp2; + boost::system::error_code ec; + 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::MacAdvertisementRoute, proto_prefix.type); + size_t expected_size = + EvpnPrefix::kMinMacAdvertisementRouteSize + EvpnPrefix::kLabelSize; + EXPECT_EQ(expected_size * 8, proto_prefix.prefixlen); + EXPECT_EQ(expected_size, 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(prefix2.esi().IsZero()); + EXPECT_EQ(attr.get(), attr_out2.get()); + EXPECT_EQ(tag, label2); + } +} + +// Build and parse BgpProtoPrefix for reach with VXLAN encap, w/o ip. +// Tag is 0, so label should be honored. +TEST_F(EvpnMacAdvertisementPrefixTest, FromProtoPrefix8) { + string temp1("2-10.1.1.1:65535-"); + string temp2("-11:12:13:14:15:16,0.0.0.0"); + uint32_t label_list[] = { 32, 10000, 1048575 }; + BOOST_FOREACH(uint32_t label1, label_list) { + string prefix_str = temp1 + integerToString(0) + temp2; + boost::system::error_code ec; + 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); + + BgpProtoPrefix proto_prefix; + prefix1.BuildProtoPrefix(attr.get(), label1, &proto_prefix); + EXPECT_EQ(EvpnPrefix::MacAdvertisementRoute, proto_prefix.type); + size_t expected_size = + EvpnPrefix::kMinMacAdvertisementRouteSize + EvpnPrefix::kLabelSize; + EXPECT_EQ(expected_size * 8, proto_prefix.prefixlen); + EXPECT_EQ(expected_size, 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(prefix2.esi().IsZero()); + EXPECT_EQ(attr.get(), attr_out2.get()); + EXPECT_EQ(label1, label2); + } +} + +// Build and parse BgpProtoPrefix for reach with VXLAN encap, w/ ipv4. +// Tag is not 0, so label should be ignored. +TEST_F(EvpnMacAdvertisementPrefixTest, FromProtoPrefix9) { + string temp1("2-10.1.1.1:65535-"); + string temp2("-11:12:13:14:15:16,192.1.1.1"); + uint32_t tag_list[] = { 32, 10000, 1048575, 16777215 }; + BOOST_FOREACH(uint32_t tag, tag_list) { + string prefix_str = temp1 + integerToString(tag) + temp2; + boost::system::error_code ec; + 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::MacAdvertisementRoute, proto_prefix.type); + size_t expected_size = + EvpnPrefix::kMinMacAdvertisementRouteSize + EvpnPrefix::kLabelSize + 4; + EXPECT_EQ(expected_size * 8, proto_prefix.prefixlen); + EXPECT_EQ(expected_size, 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(prefix2.esi().IsZero()); + EXPECT_EQ(attr.get(), attr_out2.get()); + EXPECT_EQ(tag, label2); + } +} + +// Build and parse BgpProtoPrefix for reach with VXLAN encap, w/ ipv4. +// Tag is 0, so label should be honored. +TEST_F(EvpnMacAdvertisementPrefixTest, FromProtoPrefix10) { + string temp1("2-10.1.1.1:65535-"); + string temp2("-11:12:13:14:15:16,192.1.1.1"); + uint32_t label_list[] = { 32, 10000, 1048575 }; + BOOST_FOREACH(uint32_t label1, label_list) { + string prefix_str = temp1 + integerToString(0) + temp2; + boost::system::error_code ec; + 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); + + BgpProtoPrefix proto_prefix; + prefix1.BuildProtoPrefix(attr.get(), label1, &proto_prefix); + EXPECT_EQ(EvpnPrefix::MacAdvertisementRoute, proto_prefix.type); + size_t expected_size = + EvpnPrefix::kMinMacAdvertisementRouteSize + EvpnPrefix::kLabelSize + 4; + EXPECT_EQ(expected_size * 8, proto_prefix.prefixlen); + EXPECT_EQ(expected_size, 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(prefix2.esi().IsZero()); + EXPECT_EQ(attr.get(), attr_out2.get()); + EXPECT_EQ(label1, label2); + } +} + +// Build and parse BgpProtoPrefix for reach with VXLAN encap, w/ ipv6. +// Tag is not 0, so label should be ignored. +TEST_F(EvpnMacAdvertisementPrefixTest, FromProtoPrefix11) { + string temp1("2-10.1.1.1:65535-"); + string temp2("-11:12:13:14:15:16,2001:db8:0:9::1"); + uint32_t tag_list[] = { 32, 10000, 1048575, 16777215 }; + BOOST_FOREACH(uint32_t tag, tag_list) { + string prefix_str = temp1 + integerToString(tag) + temp2; + boost::system::error_code ec; + 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::MacAdvertisementRoute, proto_prefix.type); + size_t expected_size = + EvpnPrefix::kMinMacAdvertisementRouteSize + EvpnPrefix::kLabelSize + 16; + EXPECT_EQ(expected_size * 8, proto_prefix.prefixlen); + EXPECT_EQ(expected_size, 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(prefix2.esi().IsZero()); + EXPECT_EQ(attr.get(), attr_out2.get()); + EXPECT_EQ(tag, label2); + } +} + +// Build and parse BgpProtoPrefix for reach with VXLAN encap, w/ ipv6. +// Tag is 0, so label should be honored. +TEST_F(EvpnMacAdvertisementPrefixTest, FromProtoPrefix12) { + string temp1("2-10.1.1.1:65535-"); + string temp2("-11:12:13:14:15:16,2001:db8:0:9::1"); + uint32_t label_list[] = { 32, 10000, 1048575 }; + BOOST_FOREACH(uint32_t label1, label_list) { + string prefix_str = temp1 + integerToString(0) + temp2; + boost::system::error_code ec; + 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); + + BgpProtoPrefix proto_prefix; + prefix1.BuildProtoPrefix(attr.get(), label1, &proto_prefix); + EXPECT_EQ(EvpnPrefix::MacAdvertisementRoute, proto_prefix.type); + size_t expected_size = + EvpnPrefix::kMinMacAdvertisementRouteSize + EvpnPrefix::kLabelSize + 16; + EXPECT_EQ(expected_size * 8, proto_prefix.prefixlen); + EXPECT_EQ(expected_size, 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(prefix2.esi().IsZero()); + EXPECT_EQ(attr.get(), attr_out2.get()); + EXPECT_EQ(label1, label2); + } +} + // Smaller than minimum size for reach. TEST_F(EvpnMacAdvertisementPrefixTest, FromProtoPrefix_Error1) { BgpProtoPrefix proto_prefix;