Skip to content

Commit

Permalink
Merge "Prevent loops when re-originating service chain routes"
Browse files Browse the repository at this point in the history
  • Loading branch information
Zuul authored and opencontrail-ci-admin committed Jan 14, 2015
2 parents 6a1d132 + 0a70be6 commit 3941b64
Show file tree
Hide file tree
Showing 20 changed files with 898 additions and 99 deletions.
1 change: 1 addition & 0 deletions src/bgp/SConscript
Expand Up @@ -46,6 +46,7 @@ libbgp = env.Library('bgp',
'bgp_log.cc',
'bgp_message_builder.cc',
'bgp_multicast.cc',
'bgp_origin_vn_path.cc',
'bgp_path.cc',
'bgp_peer.cc',
'bgp_peer_close.cc',
Expand Down
33 changes: 31 additions & 2 deletions src/bgp/bgp_attr.cc
Expand Up @@ -536,6 +536,7 @@ BgpAttr::BgpAttr(const BgpAttr &rhs)
as_path_(rhs.as_path_),
community_(rhs.community_),
ext_community_(rhs.ext_community_),
origin_vn_path_(rhs.origin_vn_path_),
pmsi_tunnel_(rhs.pmsi_tunnel_),
edge_discovery_(rhs.edge_discovery_),
edge_forwarding_(rhs.edge_forwarding_),
Expand Down Expand Up @@ -563,8 +564,8 @@ void BgpAttr::set_community(const CommunitySpec *comm) {
}
}

void BgpAttr::set_ext_community(ExtCommunityPtr comm) {
ext_community_ = comm;
void BgpAttr::set_ext_community(ExtCommunityPtr extcomm) {
ext_community_ = extcomm;
}

void BgpAttr::set_ext_community(const ExtCommunitySpec *extcomm) {
Expand All @@ -575,6 +576,18 @@ void BgpAttr::set_ext_community(const ExtCommunitySpec *extcomm) {
}
}

void BgpAttr::set_origin_vn_path(OriginVnPathPtr ovnpath) {
origin_vn_path_ = ovnpath;
}

void BgpAttr::set_origin_vn_path(const OriginVnPathSpec *spec) {
if (spec) {
origin_vn_path_ = attr_db_->server()->ovnpath_db()->Locate(*spec);
} else {
origin_vn_path_ = NULL;
}
}

void BgpAttr::set_pmsi_tunnel(const PmsiTunnelSpec *pmsi_spec) {
if (pmsi_spec) {
pmsi_tunnel_.reset(new PmsiTunnel(*pmsi_spec));
Expand Down Expand Up @@ -649,6 +662,13 @@ int BgpAttr::CompareTo(const BgpAttr &rhs) const {
if (ret != 0) return ret;
}

if (origin_vn_path_.get() == NULL || rhs.origin_vn_path_.get() == NULL) {
KEY_COMPARE(origin_vn_path_.get(), rhs.origin_vn_path_.get());
} else {
int ret = origin_vn_path_->CompareTo(*rhs.origin_vn_path_);
if (ret != 0) return ret;
}

return 0;
}

Expand Down Expand Up @@ -680,6 +700,7 @@ std::size_t hash_value(BgpAttr const &attr) {
if (attr.as_path_) boost::hash_combine(hash, *attr.as_path_);
if (attr.community_) boost::hash_combine(hash, *attr.community_);
if (attr.ext_community_) boost::hash_combine(hash, *attr.ext_community_);
if (attr.origin_vn_path_) boost::hash_combine(hash, *attr.origin_vn_path_);

return hash;
}
Expand All @@ -703,6 +724,14 @@ BgpAttrPtr BgpAttrDB::ReplaceExtCommunityAndLocate(const BgpAttr *attr,
return Locate(clone);
}

// Return a clone of attribute with updated origin vn path.
BgpAttrPtr BgpAttrDB::ReplaceOriginVnPathAndLocate(const BgpAttr *attr,
OriginVnPathPtr ovnpath) {
BgpAttr *clone = new BgpAttr(*attr);
clone->set_origin_vn_path(ovnpath);
return Locate(clone);
}

// Return a clone of attribute with updated local preference.
BgpAttrPtr BgpAttrDB::ReplaceLocalPreferenceAndLocate(const BgpAttr *attr,
uint32_t local_pref) {
Expand Down
15 changes: 12 additions & 3 deletions src/bgp/bgp_attr.h
Expand Up @@ -17,6 +17,7 @@
#include "base/util.h"
#include "bgp/bgp_aspath.h"
#include "bgp/bgp_attr_base.h"
#include "bgp/bgp_origin_vn_path.h"
#include "bgp/bgp_server.h"
#include "bgp/community.h"
#include "net/address.h"
Expand Down Expand Up @@ -159,7 +160,9 @@ struct BgpMpNlri : public BgpAttribute {
BgpAttribute(code, ExtendedLength|kFlags), afi(afi), safi(safi) {
nexthop.clear();
}
explicit BgpMpNlri(const BgpAttribute &rhs) : BgpAttribute(rhs) {}
explicit BgpMpNlri(const BgpAttribute &rhs)
: BgpAttribute(rhs), afi(0), safi(0) {
}
~BgpMpNlri() {
STLDeleteValues(&nlri);
}
Expand Down Expand Up @@ -521,8 +524,10 @@ class BgpAttr {
void set_as_path(const AsPathSpec *spec);
void set_community(CommunityPtr comm);
void set_community(const CommunitySpec *comm);
void set_ext_community(ExtCommunityPtr comm);
void set_ext_community(ExtCommunityPtr extcomm);
void set_ext_community(const ExtCommunitySpec *extcomm);
void set_origin_vn_path(OriginVnPathPtr ovnpath);
void set_origin_vn_path(const OriginVnPathSpec *spec);
void set_pmsi_tunnel(const PmsiTunnelSpec *pmsi_spec);
void set_edge_discovery(const EdgeDiscoverySpec *edspec);
void set_edge_forwarding(const EdgeForwardingSpec *efspec);
Expand All @@ -546,6 +551,7 @@ class BgpAttr {
int as_path_count() const { return as_path_ ? as_path_->AsCount() : 0; }
const Community *community() const { return community_.get(); }
const ExtCommunity *ext_community() const { return ext_community_.get(); }
const OriginVnPath *origin_vn_path() const { return origin_vn_path_.get(); }
const PmsiTunnel *pmsi_tunnel() const { return pmsi_tunnel_.get(); }
const EdgeDiscovery *edge_discovery() const {
return edge_discovery_.get();
Expand Down Expand Up @@ -579,6 +585,7 @@ class BgpAttr {
AsPathPtr as_path_;
CommunityPtr community_;
ExtCommunityPtr ext_community_;
OriginVnPathPtr origin_vn_path_;
PmsiTunnelPtr pmsi_tunnel_;
EdgeDiscoveryPtr edge_discovery_;
EdgeForwardingPtr edge_forwarding_;
Expand Down Expand Up @@ -619,7 +626,9 @@ class BgpAttrDB : public BgpPathAttributeDB<BgpAttr, BgpAttrPtr, BgpAttrSpec,
BgpAttrPtr ReplaceCommunityAndLocate(const BgpAttr *attr,
const Community *community);
BgpAttrPtr ReplaceExtCommunityAndLocate(const BgpAttr *attr,
ExtCommunityPtr com);
ExtCommunityPtr extcomm);
BgpAttrPtr ReplaceOriginVnPathAndLocate(const BgpAttr *attr,
OriginVnPathPtr ovnpath);
BgpAttrPtr ReplaceLocalPreferenceAndLocate(const BgpAttr *attr,
uint32_t local_pref);
BgpAttrPtr ReplaceOriginatorIdAndLocate(const BgpAttr *attr,
Expand Down
1 change: 1 addition & 0 deletions src/bgp/bgp_attr_base.h
Expand Up @@ -44,6 +44,7 @@ struct BgpAttribute : public ParseObject {
PmsiTunnel = 22,
McastEdgeDiscovery = 241,
McastEdgeForwarding = 242,
OriginVnPath = 243,
};
enum Subcode {
OList = 1,
Expand Down
12 changes: 12 additions & 0 deletions src/bgp/bgp_message_builder.cc
Expand Up @@ -92,6 +92,18 @@ void BgpMessage::StartReach(const RibOutAttr *roattr, const BgpRoute *route) {
update.path_attributes.push_back(ext_comm);
}

if (attr->origin_vn_path() && attr->origin_vn_path()->origin_vns().size()) {
OriginVnPathSpec *ovnpath_spec = new OriginVnPathSpec;
const OriginVnPath::OriginVnList &v =
attr->origin_vn_path()->origin_vns();
for (OriginVnPath::OriginVnList::const_iterator it = v.begin();
it != v.end(); ++it) {
uint64_t value = get_value(it->data(), it->size());
ovnpath_spec->origin_vns.push_back(value);
}
update.path_attributes.push_back(ovnpath_spec);
}

if (attr->pmsi_tunnel()) {
PmsiTunnelSpec *pmsi_spec =
new PmsiTunnelSpec(attr->pmsi_tunnel()->pmsi_tunnel());
Expand Down
96 changes: 96 additions & 0 deletions src/bgp/bgp_origin_vn_path.cc
@@ -0,0 +1,96 @@
/*
* Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
*/

#include "bgp/bgp_origin_vn_path.h"

#include <boost/foreach.hpp>

#include <algorithm>
#include <string>

#include "bgp/bgp_proto.h"

using std::string;
using std::vector;

string OriginVnPathSpec::ToString() const {
char repr[80];
snprintf(repr, sizeof(repr), "OriginVnPath <code: %d, flags: %02x> : %lu",
code, flags, origin_vns.size());
return string(repr);
}

int OriginVnPathSpec::CompareTo(const BgpAttribute &rhs) const {
int ret = BgpAttribute::CompareTo(rhs);
if (ret != 0)
return ret;
KEY_COMPARE(origin_vns,
static_cast<const OriginVnPathSpec &>(rhs).origin_vns);
return 0;
}

void OriginVnPathSpec::ToCanonical(BgpAttr *attr) {
attr->set_origin_vn_path(this);
}

OriginVnPath::OriginVnPath(OriginVnPathDB *ovnpath_db,
const OriginVnPathSpec spec)
: ovnpath_db_(ovnpath_db) {
refcount_ = 0;
for (vector<uint64_t>::const_iterator it = spec.origin_vns.begin();
it < spec.origin_vns.end(); ++it) {
OriginVnValue value;
put_value(value.data(), value.size(), *it);
origin_vns_.push_back(value);
}
}

void OriginVnPath::Remove() {
ovnpath_db_->Delete(this);
}

void OriginVnPath::Prepend(const OriginVnValue &value) {
OriginVnList::iterator it = origin_vns_.begin();
origin_vns_.insert(it, value);
}

bool OriginVnPath::Contains(const OriginVnValue &val) const {
for (OriginVnList::const_iterator it = origin_vns_.begin();
it != origin_vns_.end(); ++it) {
if (*it == val)
return true;
}
return false;
}

int OriginVnPath::CompareTo(const OriginVnPath &rhs) const {
KEY_COMPARE(origin_vns_.size(), rhs.origin_vns_.size());

OriginVnList::const_iterator it1, it2;
for (it1 = origin_vns_.begin(), it2 = rhs.origin_vns_.begin();
it1 < origin_vns_.end(); ++it1, ++it2) {
if (*it1 < *it2) {
return -1;
}
if (*it1 > *it2) {
return 1;
}
}
return 0;
}

OriginVnPathDB::OriginVnPathDB(BgpServer *server) {
}

OriginVnPathPtr OriginVnPathDB::PrependAndLocate(const OriginVnPath *ovnpath,
const OriginVnPath::OriginVnValue &value) {
OriginVnPath *clone;
if (ovnpath) {
clone = new OriginVnPath(*ovnpath);
} else {
clone = new OriginVnPath(this);
}
clone->Prepend(value);
return Locate(clone);
}
118 changes: 118 additions & 0 deletions src/bgp/bgp_origin_vn_path.h
@@ -0,0 +1,118 @@
/*
* Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
*/

#ifndef SRC_BGP_BGP_ORIGIN_VN_PATH_H_
#define SRC_BGP_BGP_ORIGIN_VN_PATH_H_

#include <boost/array.hpp>
#include <boost/intrusive_ptr.hpp>
#include <tbb/atomic.h>

#include <set>
#include <string>
#include <vector>

#include "bgp/bgp_attr_base.h"
#include "base/parse_object.h"
#include "base/util.h"

class BgpAttr;
class OriginVnPathDB;
class BgpServer;

struct OriginVnPathSpec : public BgpAttribute {
static const int kSize = -1;
static const uint8_t kFlags = Optional | Transitive;
OriginVnPathSpec() : BgpAttribute(OriginVnPath, kFlags) { }
explicit OriginVnPathSpec(const BgpAttribute &rhs) : BgpAttribute(rhs) { }
std::vector<uint64_t> origin_vns;
virtual int CompareTo(const BgpAttribute &rhs_attr) const;
virtual void ToCanonical(BgpAttr *attr);
virtual std::string ToString() const;
};

class OriginVnPath {
public:
typedef boost::array<uint8_t, 8> OriginVnValue;
typedef std::vector<OriginVnValue> OriginVnList;

explicit OriginVnPath(OriginVnPathDB *ovnpath_db)
: ovnpath_db_(ovnpath_db) {
refcount_ = 0;
}
explicit OriginVnPath(const OriginVnPath &rhs)
: ovnpath_db_(rhs.ovnpath_db_),
origin_vns_(rhs.origin_vns_) {
refcount_ = 0;
}
explicit OriginVnPath(OriginVnPathDB *ovnpath_db,
const OriginVnPathSpec spec);
virtual ~OriginVnPath() { }

virtual void Remove();
void Prepend(const OriginVnValue &value);
bool Contains(const OriginVnValue &value) const;
int CompareTo(const OriginVnPath &rhs) const;

const OriginVnList &origin_vns() const { return origin_vns_; }

friend std::size_t hash_value(const OriginVnPath &ovnpath) {
size_t hash = 0;
for (OriginVnList::const_iterator it = ovnpath.origin_vns_.begin();
it != ovnpath.origin_vns_.end(); ++it) {
boost::hash_range(hash, it->begin(), it->end());
}
return hash;
}

private:
friend int intrusive_ptr_add_ref(const OriginVnPath *covnpath);
friend int intrusive_ptr_del_ref(const OriginVnPath *covnpath);
friend void intrusive_ptr_release(const OriginVnPath *covnpath);

mutable tbb::atomic<int> refcount_;
OriginVnPathDB *ovnpath_db_;
OriginVnList origin_vns_;
};

inline int intrusive_ptr_add_ref(const OriginVnPath *covnpath) {
return covnpath->refcount_.fetch_and_increment();
}

inline int intrusive_ptr_del_ref(const OriginVnPath *covnpath) {
return covnpath->refcount_.fetch_and_decrement();
}

inline void intrusive_ptr_release(const OriginVnPath *covnpath) {
int prev = covnpath->refcount_.fetch_and_decrement();
if (prev == 1) {
OriginVnPath *ovnpath = const_cast<OriginVnPath *>(covnpath);
ovnpath->Remove();
assert(ovnpath->refcount_ == 0);
delete ovnpath;
}
}

typedef boost::intrusive_ptr<const OriginVnPath> OriginVnPathPtr;

struct OriginVnPathCompare {
bool operator()(const OriginVnPath *lhs, const OriginVnPath *rhs) {
return lhs->CompareTo(*rhs) < 0;
}
};

class OriginVnPathDB : public BgpPathAttributeDB<OriginVnPath, OriginVnPathPtr,
OriginVnPathSpec,
OriginVnPathCompare,
OriginVnPathDB> {
public:
explicit OriginVnPathDB(BgpServer *server);
OriginVnPathPtr PrependAndLocate(const OriginVnPath *ovnpath,
const OriginVnPath::OriginVnValue &value);

private:
DISALLOW_COPY_AND_ASSIGN(OriginVnPathDB);
};

#endif // SRC_BGP_BGP_ORIGIN_VN_PATH_H_
1 change: 1 addition & 0 deletions src/bgp/bgp_peer.sandesh
Expand Up @@ -139,6 +139,7 @@ struct ShowRoutePath {
14: string primary_table (link="ShowRouteReq");
15: list<string> communities;
16: string origin_vn;
20: list<string> origin_vn_path;
19: string sequence_no;
17: u32 flags;
}
Expand Down

0 comments on commit 3941b64

Please sign in to comment.