-
Notifications
You must be signed in to change notification settings - Fork 390
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Prevent loops when re-originating service chain routes
Implement a new attribute called OriginVnPath to keep track of VNs from which a given route has been re-originated. The OriginVn of ServiceChain destination routing instance gets prepended to OriginVnPath when adding the ServiceChain route. Further, a route is not re-originated if source routing instance's OriginVn is already in the OriginVnPath. This prevents route re-origination loops even if VNs are mis-configured such that multiple VNs have the same route target and there are transit VNs with mis-configured route targets as well. Change-Id: Iab76ad4b07a69f71383db8e72531fb31bade04bd Closes-Bug: 1401010
- Loading branch information
Nischal Sheth
committed
Jan 5, 2015
1 parent
963cb34
commit 0a70be6
Showing
20 changed files
with
898 additions
and
99 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.