Skip to content

Commit

Permalink
Do not use tag greater than kMaxVni as label with VXLAN encap
Browse files Browse the repository at this point in the history
Change-Id: Icffda48af9b64c3afe0ab610b38f66693fc5a3ff
Closes-Bug: 1466415
  • Loading branch information
Nischal Sheth committed Jun 21, 2015
1 parent 54a798d commit 35c2a97
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 4 deletions.
2 changes: 0 additions & 2 deletions src/bgp/bgp_attr_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,9 @@ 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) {
int offset = (kLabelSize - (idx + 1)) * 8;
Expand Down
18 changes: 16 additions & 2 deletions src/bgp/evpn/evpn_route.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ using std::vector;

const EvpnPrefix EvpnPrefix::kNullPrefix;

const uint32_t EvpnPrefix::kInvalidLabel = 0x100000;
const uint32_t EvpnPrefix::kInvalidLabel = 0x00100000;
const uint32_t EvpnPrefix::kNullTag = 0;
const uint32_t EvpnPrefix::kMaxTag = 0xFFFFFFFF;
const uint32_t EvpnPrefix::kMaxVni = 0x00FFFFFF;

const size_t EvpnPrefix::kRdSize = RouteDistinguisher::kSize;
const size_t EvpnPrefix::kEsiSize = EthernetSegmentId::kSize;
Expand All @@ -41,13 +42,26 @@ const size_t EvpnPrefix::kMinSegmentRouteSize =
// compatibility with newer JUNOS and Contrail code which encodes/decodes
// the label as a 24-bit value.
//
// Note that Ethernet AD Routes per ESI always set ethernet tag to kMaxTag
// 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) {
if (!attr)
return 0;
const ExtCommunity *extcomm = attr->ext_community();
if (extcomm && extcomm->ContainsTunnelEncapVxlan()) {
return (tag ? tag : proto_prefix.ReadLabel(offset, false));
if (tag) {
if (tag == EvpnPrefix::kMaxTag) {
return 0;
} else if (tag <= EvpnPrefix::kMaxVni) {
return tag;
} else {
return proto_prefix.ReadLabel(offset, false);
}
} else {
return proto_prefix.ReadLabel(offset, false);
}
} else {
return proto_prefix.ReadLabel(offset, false);
}
Expand Down
1 change: 1 addition & 0 deletions src/bgp/evpn/evpn_route.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class EvpnPrefix {
static const uint32_t kInvalidLabel;
static const uint32_t kNullTag;
static const uint32_t kMaxTag;
static const uint32_t kMaxVni;

static const size_t kRdSize;
static const size_t kEsiSize;
Expand Down
201 changes: 201 additions & 0 deletions src/bgp/evpn/test/evpn_prefix_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,84 @@ TEST_F(EvpnAutoDiscoveryPrefixTest, FromProtoPrefix4) {
}
}

// Build and parse BgpProtoPrefix for reach with VXLAN encap.
// Tag is kMaxTag, so label should be ignored and assumed to be 0.
TEST_F(EvpnAutoDiscoveryPrefixTest, FromProtoPrefix5) {
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, 16777215 };
BOOST_FOREACH(uint32_t label1, label_list) {
string prefix_str = temp + integerToString(EvpnPrefix::kMaxTag);
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(0, label2);
}
}

// Build and parse BgpProtoPrefix for reach with VXLAN encap.
// Tag is greater than kMaxVni, so label should be honored.
TEST_F(EvpnAutoDiscoveryPrefixTest, FromProtoPrefix6) {
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(EvpnPrefix::kMaxVni + 1);
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;
Expand Down Expand Up @@ -1094,6 +1172,129 @@ TEST_F(EvpnMacAdvertisementPrefixTest, FromProtoPrefix12) {
}
}

// Build and parse BgpProtoPrefix for reach with VXLAN encap, w/o ip.
// Tag is greater than kMaxVni, so label should be honored.
TEST_F(EvpnMacAdvertisementPrefixTest, FromProtoPrefix13) {
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(EvpnPrefix::kMaxVni + 1) + 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 greater than kMaxVni, so label should be honored.
TEST_F(EvpnMacAdvertisementPrefixTest, FromProtoPrefix14) {
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(EvpnPrefix::kMaxVni + 1) + 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 greater than kMaxVni, so label should be honored.
TEST_F(EvpnMacAdvertisementPrefixTest, FromProtoPrefix15) {
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(EvpnPrefix::kMaxVni + 1) + 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;
Expand Down

0 comments on commit 35c2a97

Please sign in to comment.