Skip to content

Commit

Permalink
Use ethernet tag as label if encapsulation is VXLAN
Browse files Browse the repository at this point in the history
Note that we still encode/decode the label as a 20-bit value
in this release.

This provides backward compatibility with older 2.0 releases
and forward compatibility with 2.20 and newer releases. Note
that all releases set the VNI as the ethernet tag.

Change-Id: I60cdae79cf4a8b60ebb9ed271ccafca4193d4a91
Closes-Bug: 1464781
  • Loading branch information
Nischal Sheth committed Jun 16, 2015
1 parent b8394ba commit 54a798d
Show file tree
Hide file tree
Showing 6 changed files with 391 additions and 14 deletions.
20 changes: 18 additions & 2 deletions src/bgp/bgp_attr_base.cc
Expand Up @@ -12,16 +12,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) {
Expand Down
4 changes: 2 additions & 2 deletions src/bgp/bgp_attr_base.h
Expand Up @@ -94,8 +94,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<uint8_t> prefix;
int prefixlen;
Expand Down
14 changes: 14 additions & 0 deletions src/bgp/community.cc
Expand Up @@ -212,6 +212,20 @@ vector<string> 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;
Expand Down
1 change: 1 addition & 0 deletions src/bgp/community.h
Expand Up @@ -163,6 +163,7 @@ class ExtCommunity {
}

std::vector<std::string> GetTunnelEncap() const;
bool ContainsTunnelEncapVxlan() const;

static bool is_origin_vn(const ExtCommunityValue &val) {
//
Expand Down
43 changes: 33 additions & 10 deletions src/bgp/evpn/evpn_route.cc
Expand Up @@ -34,6 +34,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) {
}
Expand Down Expand Up @@ -111,10 +138,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: {
Expand Down Expand Up @@ -146,10 +171,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: {
Expand Down Expand Up @@ -229,7 +252,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: {
Expand Down Expand Up @@ -258,7 +281,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: {
Expand Down

0 comments on commit 54a798d

Please sign in to comment.