Skip to content

Commit

Permalink
Merge "Add remove-private parameters to RibExportPolicy"
Browse files Browse the repository at this point in the history
  • Loading branch information
Zuul authored and opencontrail-ci-admin committed Aug 12, 2016
2 parents 8a478d4 + a26caba commit 6c83b2a
Show file tree
Hide file tree
Showing 8 changed files with 305 additions and 2 deletions.
4 changes: 4 additions & 0 deletions src/bgp/bgp_aspath.cc
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ size_t AsPathSpec::EncodeLength() const {
return sz;
}

//
// Check AsPathSpec for loops for the given as.
// Return true if the number of occurrences of as exceeds given max loop count.
//
bool AsPathSpec::AsPathLoop(as_t as, uint8_t max_loop_count) const {
uint8_t loop_count = 0;
for (size_t i = 0; i < path_segments.size(); ++i) {
Expand Down
20 changes: 20 additions & 0 deletions src/bgp/bgp_rib_policy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@

#include "bgp/bgp_rib_policy.h"

RibExportPolicy::RemovePrivatePolicy::RemovePrivatePolicy()
: enabled(false),
all(false),
replace(false),
peer_loop_check(false) {
}

RibExportPolicy::RibExportPolicy()
: type(BgpProto::IBGP),
encoding(BGP),
Expand Down Expand Up @@ -60,6 +67,14 @@ RibExportPolicy::RibExportPolicy(BgpProto::BgpPeerType type, Encoding encoding,
assert(encoding == BGP);
}

void RibExportPolicy::SetRemovePrivatePolicy(bool all, bool replace,
bool peer_loop_check) {
remove_private.enabled = true;
remove_private.all = all;
remove_private.replace = replace;
remove_private.peer_loop_check = peer_loop_check;
}

//
// Implement operator< for RibExportPolicy by comparing each of the fields.
//
Expand All @@ -72,5 +87,10 @@ bool RibExportPolicy::operator<(const RibExportPolicy &rhs) const {
BOOL_KEY_COMPARE(affinity, rhs.affinity);
BOOL_KEY_COMPARE(llgr, rhs.llgr);
BOOL_KEY_COMPARE(cluster_id, rhs.cluster_id);
BOOL_KEY_COMPARE(remove_private.enabled, rhs.remove_private.enabled);
BOOL_KEY_COMPARE(remove_private.all, rhs.remove_private.all);
BOOL_KEY_COMPARE(remove_private.replace, rhs.remove_private.replace);
BOOL_KEY_COMPARE(
remove_private.peer_loop_check, rhs.remove_private.peer_loop_check);
return false;
}
11 changes: 11 additions & 0 deletions src/bgp/bgp_rib_policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ struct RibExportPolicy {
XMPP,
};

struct RemovePrivatePolicy {
RemovePrivatePolicy();

bool enabled;
bool all;
bool replace;
bool peer_loop_check;
};

RibExportPolicy();
RibExportPolicy(BgpProto::BgpPeerType type, Encoding encoding,
int affinity, u_int32_t cluster_id);
Expand All @@ -52,6 +61,7 @@ struct RibExportPolicy {
as_t as_number, bool as_override, bool llgr, IpAddress nexthop,
int affinity, u_int32_t cluster_id);

void SetRemovePrivatePolicy(bool all, bool replace, bool peer_loop_check);
bool operator<(const RibExportPolicy &rhs) const;

BgpProto::BgpPeerType type;
Expand All @@ -62,6 +72,7 @@ struct RibExportPolicy {
int affinity;
bool llgr;
uint32_t cluster_id;
RemovePrivatePolicy remove_private;
};

#endif // SRC_BGP_BGP_RIB_POLICY_H_
10 changes: 10 additions & 0 deletions src/bgp/bgp_ribout.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,16 @@ class RibOut {
std::string EncodingString() const {
return IsEncodingXmpp() ? "XMPP" : "BGP";
}
bool remove_private_enabled() const {
return policy_.remove_private.enabled;
}
bool remove_private_all() const { return policy_.remove_private.all; }
bool remove_private_replace() const {
return policy_.remove_private.replace;
}
bool remove_private_peer_loop_check() const {
return policy_.remove_private.peer_loop_check;
}

void FillStatisticsInfo(std::vector<ShowRibOutStatistics> *sros_list) const;

Expand Down
31 changes: 29 additions & 2 deletions src/bgp/bgp_table.cc
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,26 @@ void BgpTable::RibOutDelete(const RibExportPolicy &policy) {
ribout_map_.erase(loc);
}

//
// Process Remove Private information.
//
void BgpTable::ProcessRemovePrivate(const RibOut *ribout, BgpAttr *attr) const {
if (!ribout->remove_private_enabled())
return;

bool all = ribout->remove_private_all();
bool replace = ribout->remove_private_replace();
bool peer_loop_check = ribout->remove_private_peer_loop_check();

as_t replace_asn = replace ? server()->local_autonomous_system() : 0;
as_t peer_asn = peer_loop_check ? ribout->peer_as() : 0;

const AsPathSpec &spec = attr->as_path()->path();
AsPathSpec *new_spec = spec.RemovePrivate(all, replace_asn, peer_asn);
attr->set_as_path(new_spec);
delete new_spec;
}

//
// Process Long Lived Graceful Restart state information.
//
Expand Down Expand Up @@ -247,6 +267,10 @@ UpdateInfo *BgpTable::GetUpdateInfo(RibOut *ribout, BgpRoute *route,
if (clone->local_pref() == 0)
clone->set_local_pref(100);

// Should not normally be needed for iBGP, but there could be
// complex configurations where this is useful.
ProcessRemovePrivate(ribout, clone);

// If the route is locally originated i.e. there's no AsPath,
// then generate a Nil AsPath i.e. one with 0 length. No need
// to modify the AsPath if it already exists since this is an
Expand Down Expand Up @@ -320,6 +344,9 @@ UpdateInfo *BgpTable::GetUpdateInfo(RibOut *ribout, BgpRoute *route,
delete as_path_ptr;
}

// Remove private processing must happen before local AS prepend.
ProcessRemovePrivate(ribout, clone);

// Prepend the local AS to AsPath.
if (clone->as_path() != NULL) {
const AsPathSpec &as_path = clone->as_path()->path();
Expand All @@ -335,9 +362,9 @@ UpdateInfo *BgpTable::GetUpdateInfo(RibOut *ribout, BgpRoute *route,
}

assert(clone);

// Process LLGR information.
ProcessLlgrState(ribout, path, clone);

// Locate the new BgpAttrPtr.
attr_ptr = clone->attr_db()->Locate(clone);
attr = attr_ptr.get();
}
Expand Down
1 change: 1 addition & 0 deletions src/bgp/bgp_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ class BgpTable : public RouteTable {

class DeleteActor;

void ProcessRemovePrivate(const RibOut *ribout, BgpAttr *attr) const;
void ProcessLlgrState(const RibOut *ribout, const BgpPath *path,
BgpAttr *attr);
virtual BgpRoute *TableFind(DBTablePartition *rtp,
Expand Down
97 changes: 97 additions & 0 deletions src/bgp/test/bgp_attr_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -812,6 +812,103 @@ TEST_F(BgpAttrTest, AsPathRemovePrivate7) {
EXPECT_EQ(0, result->CompareTo(expected));
}

//
// Original spec has multiple segments.
// ASs are being removed, not replaced.
// After the first segment is modified, remaining segments should be copied
// over unchanged since all is not true.
//
TEST_F(BgpAttrTest, AsPathRemovePrivate8) {
AsPathSpec original;
AsPathSpec::PathSegment *ops1 = new AsPathSpec::PathSegment;
original.path_segments.push_back(ops1);
ops1->path_segment_type = AsPathSpec::PathSegment::AS_SEQUENCE;
ops1->path_segment.push_back(64512);
ops1->path_segment.push_back(100);
ops1->path_segment.push_back(65000);
AsPathSpec::PathSegment *ops2 = new AsPathSpec::PathSegment;
original.path_segments.push_back(ops2);
ops2->path_segment_type = AsPathSpec::PathSegment::AS_SET;
ops2->path_segment.push_back(64512);
ops2->path_segment.push_back(64513);
AsPathSpec::PathSegment *ops3 = new AsPathSpec::PathSegment;
original.path_segments.push_back(ops3);
ops3->path_segment_type = AsPathSpec::PathSegment::AS_SEQUENCE;
ops3->path_segment.push_back(500);

AsPathSpec expected;
AsPathSpec::PathSegment *eps1 = new AsPathSpec::PathSegment;
expected.path_segments.push_back(eps1);
eps1->path_segment_type = AsPathSpec::PathSegment::AS_SEQUENCE;
eps1->path_segment.push_back(100);
eps1->path_segment.push_back(65000);
AsPathSpec::PathSegment *eps2 = new AsPathSpec::PathSegment;
expected.path_segments.push_back(eps2);
eps2->path_segment_type = AsPathSpec::PathSegment::AS_SET;
eps2->path_segment.push_back(64512);
eps2->path_segment.push_back(64513);
AsPathSpec::PathSegment *eps3 = new AsPathSpec::PathSegment;
expected.path_segments.push_back(eps3);
eps3->path_segment_type = AsPathSpec::PathSegment::AS_SEQUENCE;
eps3->path_segment.push_back(500);

bool all;
as_t asn, peer_asn;
boost::scoped_ptr<AsPathSpec> result;
all = false; asn = 0; peer_asn = 0;
result.reset(original.RemovePrivate(all, asn, peer_asn));
EXPECT_EQ(0, result->CompareTo(expected));
}

//
// Original spec has multiple segments.
// ASs are being replaced, not removed.
// After the first segment is modified, remaining segments should be copied
// over unchanged since all is not true.
//
TEST_F(BgpAttrTest, AsPathRemovePrivate9) {
AsPathSpec original;
AsPathSpec::PathSegment *ops1 = new AsPathSpec::PathSegment;
original.path_segments.push_back(ops1);
ops1->path_segment_type = AsPathSpec::PathSegment::AS_SEQUENCE;
ops1->path_segment.push_back(64512);
ops1->path_segment.push_back(100);
ops1->path_segment.push_back(65000);
AsPathSpec::PathSegment *ops2 = new AsPathSpec::PathSegment;
original.path_segments.push_back(ops2);
ops2->path_segment_type = AsPathSpec::PathSegment::AS_SET;
ops2->path_segment.push_back(64512);
ops2->path_segment.push_back(64513);
AsPathSpec::PathSegment *ops3 = new AsPathSpec::PathSegment;
original.path_segments.push_back(ops3);
ops3->path_segment_type = AsPathSpec::PathSegment::AS_SEQUENCE;
ops3->path_segment.push_back(500);

AsPathSpec expected;
AsPathSpec::PathSegment *eps1 = new AsPathSpec::PathSegment;
expected.path_segments.push_back(eps1);
eps1->path_segment_type = AsPathSpec::PathSegment::AS_SEQUENCE;
eps1->path_segment.push_back(300);
eps1->path_segment.push_back(100);
eps1->path_segment.push_back(65000);
AsPathSpec::PathSegment *eps2 = new AsPathSpec::PathSegment;
expected.path_segments.push_back(eps2);
eps2->path_segment_type = AsPathSpec::PathSegment::AS_SET;
eps2->path_segment.push_back(64512);
eps2->path_segment.push_back(64513);
AsPathSpec::PathSegment *eps3 = new AsPathSpec::PathSegment;
expected.path_segments.push_back(eps3);
eps3->path_segment_type = AsPathSpec::PathSegment::AS_SEQUENCE;
eps3->path_segment.push_back(500);

bool all;
as_t asn, peer_asn;
boost::scoped_ptr<AsPathSpec> result;
all = false; asn = 300; peer_asn = 0;
result.reset(original.RemovePrivate(all, asn, peer_asn));
EXPECT_EQ(0, result->CompareTo(expected));
}

TEST_F(BgpAttrTest, AsPathFormat1) {
AsPathSpec spec;

Expand Down

0 comments on commit 6c83b2a

Please sign in to comment.