Skip to content

Commit

Permalink
Add loops functionality for bgp peer
Browse files Browse the repository at this point in the history
Highlights:

- A loop_count can be configured for peer or peer address family
- Value configured under peer address family overrides per peer value
- Default value of loop_count is 0
- Paths with upto loop count occurrences of asn are accepted by peer
- Include address family attributes in introspect output
- Add unit tests to cover new functionality

Change-Id: I8e558473a2c467a1bb0fb42ea299919167f11560
Partial-Bug: 1513278
  • Loading branch information
Nischal Sheth committed Nov 16, 2015
1 parent 7ee63e8 commit 42d7551
Show file tree
Hide file tree
Showing 17 changed files with 506 additions and 49 deletions.
13 changes: 9 additions & 4 deletions src/bgp/bgp_aspath.cc
Expand Up @@ -90,11 +90,16 @@ size_t AsPathSpec::EncodeLength() const {
return sz;
}

bool AsPathSpec::AsPathLoop(as_t as) const {
for (size_t i = 0; i < path_segments.size(); i++)
for (size_t j = 0; j < path_segments[i]->path_segment.size(); j++)
if (path_segments[i]->path_segment[j] == as)
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) {
for (size_t j = 0; j < path_segments[i]->path_segment.size(); ++j) {
if (path_segments[i]->path_segment[j] == as &&
++loop_count > max_loop_count) {
return true;
}
}
}
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion src/bgp/bgp_aspath.h
Expand Up @@ -55,7 +55,7 @@ struct AsPathSpec : public BgpAttribute {

as_t AsLeftMost() const;
bool AsLeftMostMatch(as_t as) const;
bool AsPathLoop(as_t as) const;
bool AsPathLoop(as_t as, uint8_t max_loop_count = 0) const;

virtual int CompareTo(const BgpAttribute &rhs_attr) const;
virtual void ToCanonical(BgpAttr *attr);
Expand Down
3 changes: 3 additions & 0 deletions src/bgp/bgp_config.cc
Expand Up @@ -144,6 +144,7 @@ BgpNeighborConfig::BgpNeighborConfig()
identifier_(0),
port_(BgpConfigManager::kDefaultPort),
hold_time_(0),
loop_count_(0),
local_as_(0),
local_identifier_(0),
last_change_at_(UTCTimestampUsec()) {
Expand All @@ -160,6 +161,7 @@ void BgpNeighborConfig::CopyValues(const BgpNeighborConfig &rhs) {
address_ = rhs.address_;
port_ = rhs.port_;
hold_time_ = rhs.hold_time_;
loop_count_ = rhs.loop_count_;
local_as_ = rhs.local_as_;
local_identifier_ = rhs.local_identifier_;
auth_data_ = rhs.auth_data_;
Expand All @@ -178,6 +180,7 @@ int BgpNeighborConfig::CompareTo(const BgpNeighborConfig &rhs) const {
KEY_COMPARE(address_, rhs.address_);
KEY_COMPARE(port_, rhs.port_);
KEY_COMPARE(hold_time_, rhs.hold_time_);
KEY_COMPARE(loop_count_, rhs.loop_count_);
KEY_COMPARE(local_as_, rhs.local_as_);
KEY_COMPARE(local_identifier_, rhs.local_identifier_);
KEY_COMPARE(auth_data_, rhs.auth_data_);
Expand Down
4 changes: 4 additions & 0 deletions src/bgp/bgp_config.h
Expand Up @@ -183,6 +183,9 @@ class BgpNeighborConfig {
int hold_time() const { return hold_time_; }
void set_hold_time(int hold_time) { hold_time_ = hold_time; }

uint8_t loop_count() const { return loop_count_; }
void set_loop_count(uint8_t loop_count) { loop_count_ = loop_count; }

uint32_t local_as() const { return local_as_; }
void set_local_as(uint32_t local_as) { local_as_ = local_as; }

Expand Down Expand Up @@ -233,6 +236,7 @@ class BgpNeighborConfig {
IpAddress address_;
int port_;
int hold_time_;
uint8_t loop_count_;
uint32_t local_as_;
uint32_t local_identifier_;
mutable uint64_t last_change_at_;
Expand Down
1 change: 1 addition & 0 deletions src/bgp/bgp_config_ifmap.cc
Expand Up @@ -169,6 +169,7 @@ static void NeighborSetSessionAttributes(
}
if (attributes != NULL) {
neighbor->set_passive(attributes->passive);
neighbor->set_loop_count(attributes->loop_count);
if (attributes->admin_down) {
neighbor->set_admin_down(true);
}
Expand Down
75 changes: 54 additions & 21 deletions src/bgp/bgp_peer.cc
Expand Up @@ -254,8 +254,13 @@ class BgpPeer::DeleteActor : public LifetimeActor {
// Constructor for BgpPeerFamilyAttributes.
//
BgpPeerFamilyAttributes::BgpPeerFamilyAttributes(
const BgpNeighborConfig *config,
const BgpFamilyAttributesConfig &family_config) {
loop_count = family_config.loop_count;
if (family_config.loop_count) {
loop_count = family_config.loop_count;
} else {
loop_count = config->loop_count();
}
prefix_limit = family_config.prefix_limit;
}

Expand Down Expand Up @@ -528,7 +533,7 @@ bool BgpPeer::ProcessFamilyAttributesConfig(const BgpNeighborConfig *config) {
Address::FamilyFromString(family_config.family);
assert(family != Address::UNSPEC);
BgpPeerFamilyAttributes *family_attributes =
new BgpPeerFamilyAttributes(family_config);
new BgpPeerFamilyAttributes(config, family_config);
family_attributes_list[family] = family_attributes;
}

Expand Down Expand Up @@ -1103,31 +1108,37 @@ void BgpPeer::ProcessNlri(Address::Family family, DBRequest::DBOperation oper,
}
}

void BgpPeer::ProcessUpdate(const BgpProto::Update *msg, size_t msgsize) {
BgpAttrPtr attr = server_->attr_db()->Locate(msg->path_attributes);
// Check as path loop and neighbor-as
const BgpAttr *path_attr = attr.get();
uint32_t BgpPeer::GetPathFlags(Address::Family family,
const BgpAttr *attr) const {
uint32_t flags = 0;

if (path_attr->as_path() != NULL) {
// Check whether neighbor has appended its AS to the AS_PATH
if ((PeerType() == BgpProto::EBGP) &&
(!path_attr->as_path()->path().AsLeftMostMatch(peer_as()))) {
flags |= BgpPath::NoNeighborAs;
}

// Check for AS_PATH loop
if (path_attr->as_path()->path().AsPathLoop(local_as_)) {
flags |= BgpPath::AsPathLooped;
}
}

// Check for OriginatorId loop in case we are an RR client.
if (peer_type_ == BgpProto::IBGP &&
path_attr->originator_id().to_ulong() == ntohl(local_bgp_id_)) {
attr->originator_id().to_ulong() == ntohl(local_bgp_id_)) {
flags |= BgpPath::OriginatorIdLooped;
}

if (!attr->as_path())
return flags;

// Check whether neighbor has appended its AS to the AS_PATH.
if ((PeerType() == BgpProto::EBGP) &&
(!attr->as_path()->path().AsLeftMostMatch(peer_as()))) {
flags |= BgpPath::NoNeighborAs;
}

// Check for AS_PATH loop.
uint8_t max_loop_count = family_attributes_list_[family]->loop_count;
if (attr->as_path()->path().AsPathLoop(local_as_, max_loop_count)) {
flags |= BgpPath::AsPathLooped;
}

return flags;
}

void BgpPeer::ProcessUpdate(const BgpProto::Update *msg, size_t msgsize) {
BgpAttrPtr attr = server_->attr_db()->Locate(msg->path_attributes);

uint32_t reach_count = 0, unreach_count = 0;
RoutingInstance *instance = GetRoutingInstance();
if (msg->nlri.size() || msg->withdrawn_routes.size()) {
Expand Down Expand Up @@ -1159,6 +1170,7 @@ void BgpPeer::ProcessUpdate(const BgpProto::Update *msg, size_t msgsize) {
table->Enqueue(&req);
}

uint32_t flags = GetPathFlags(Address::INET, attr.get());
reach_count += msg->nlri.size();
for (vector<BgpProtoPrefix *>::const_iterator it = msg->nlri.begin();
it != msg->nlri.end(); ++it) {
Expand Down Expand Up @@ -1214,8 +1226,11 @@ void BgpPeer::ProcessUpdate(const BgpProto::Update *msg, size_t msgsize) {
return;
}

if ((*ait)->code == BgpAttribute::MPReachNlri)
uint32_t flags = 0;
if ((*ait)->code == BgpAttribute::MPReachNlri) {
flags = GetPathFlags(family, attr.get());
attr = GetMpNlriNexthop(nlri, attr);
}

switch (family) {
case Address::INET:
Expand Down Expand Up @@ -1605,6 +1620,23 @@ void BgpPeer::FillBgpNeighborDebugState(BgpNeighborResp &resp,
resp.set_tx_socket_stats(peer_socket_stats);
}

void BgpPeer::FillBgpNeighborFamilyAttributes(BgpNeighborResp *nbr) const {
vector<ShowBgpNeighborFamily> show_family_attributes_list;
for (int idx = Address::UNSPEC; idx < Address::NUM_FAMILIES; ++idx) {
if (!family_attributes_list_[idx])
continue;
ShowBgpNeighborFamily show_family_attributes;
show_family_attributes.family =
Address::FamilyToString(static_cast<Address::Family>(idx));
show_family_attributes.loop_count =
family_attributes_list_[idx]->loop_count;
show_family_attributes.prefix_limit =
family_attributes_list_[idx]->prefix_limit;
show_family_attributes_list.push_back(show_family_attributes);
}
nbr->set_family_attributes_list(show_family_attributes_list);
}

void BgpPeer::FillNeighborInfo(const BgpSandeshContext *bsc,
vector<BgpNeighborResp> *nbr_list, bool summary) const {
BgpNeighborResp nbr;
Expand Down Expand Up @@ -1637,6 +1669,7 @@ void BgpPeer::FillNeighborInfo(const BgpSandeshContext *bsc,
nbr.set_configured_address_families(configured_families_);
nbr.set_negotiated_address_families(negotiated_families_);
nbr.set_configured_hold_time(state_machine_->GetConfiguredHoldTime());
FillBgpNeighborFamilyAttributes(&nbr);
FillBgpNeighborDebugState(nbr, peer_stats_.get());
PeerRibMembershipManager *mgr = server_->membership_mgr();
mgr->FillPeerMembershipInfo(this, &nbr);
Expand Down
6 changes: 5 additions & 1 deletion src/bgp/bgp_peer.h
Expand Up @@ -43,7 +43,8 @@ class BgpSandeshContext;
// Address::Family value.
//
struct BgpPeerFamilyAttributes {
BgpPeerFamilyAttributes(const BgpFamilyAttributesConfig &family_config);
BgpPeerFamilyAttributes(const BgpNeighborConfig *config,
const BgpFamilyAttributesConfig &family_config);
uint8_t loop_count;
uint32_t prefix_limit;
};
Expand Down Expand Up @@ -305,6 +306,7 @@ class BgpPeer : public IPeer {

void UnregisterAllTables();

uint32_t GetPathFlags(Address::Family family, const BgpAttr *attr) const;
virtual bool MpNlriAllowed(uint16_t afi, uint8_t safi);
BgpAttrPtr GetMpNlriNexthop(BgpMpNlri *nlri, BgpAttrPtr attr);
template <typename TableT, typename PrefixT>
Expand All @@ -323,6 +325,8 @@ class BgpPeer : public IPeer {
void PostCloseRelease();
void CustomClose();

void FillBgpNeighborFamilyAttributes(BgpNeighborResp *nbr) const;

std::string BytesToHexString(const u_int8_t *msg, size_t size);

BgpServer *server_;
Expand Down
15 changes: 15 additions & 0 deletions src/bgp/bgp_peer.sandesh
Expand Up @@ -39,6 +39,12 @@ struct BgpNeighborRoutingTable {
4: string pending_request;
}

struct ShowBgpNeighborFamily {
string family;
u32 loop_count;
u32 prefix_limit;
}

struct BgpNeighborResp {
1: string peer (link="BgpNeighborReq"); // Peer name
36: bool deleted; // Deletion in progress
Expand All @@ -63,6 +69,7 @@ struct BgpNeighborResp {
45: optional list<string> auth_keys;
38: optional list<string> configured_address_families;
39: optional list<string> negotiated_address_families;
49: optional list<ShowBgpNeighborFamily> family_attributes_list;
40: optional u32 configured_hold_time;
41: u32 negotiated_hold_time;
46: u32 primary_path_count;
Expand Down Expand Up @@ -433,6 +440,12 @@ struct ShowBgpPeeringConfig {
4: list<ShowBgpSessionConfig> sessions;
}

struct ShowBgpNeighborFamilyConfig {
1: string family;
2: i32 loop_count;
3: i32 prefix_limit;
}

struct ShowBgpNeighborConfig {
1: string instance_name;
2: string name;
Expand All @@ -445,10 +458,12 @@ struct ShowBgpNeighborConfig {
5: string identifier;
6: string address;
14: i32 hold_time;
16: i32 loop_count;
10: string last_change_at;
11: optional string auth_type;
12: optional list<string> auth_keys;
7: list<string> address_families;
17: list<ShowBgpNeighborFamilyConfig> family_attributes_list;
}

response sandesh ShowBgpNeighborConfigResp {
Expand Down
12 changes: 12 additions & 0 deletions src/bgp/bgp_sandesh.cc
Expand Up @@ -466,13 +466,25 @@ class ShowBgpNeighborConfigHandler {
nbr.set_address(neighbor->peer_address().to_string());
nbr.set_address_families(neighbor->GetAddressFamilies());
nbr.set_hold_time(neighbor->hold_time());
nbr.set_loop_count(neighbor->loop_count());
nbr.set_last_change_at(
UTCUsecToString(neighbor->last_change_at()));
nbr.set_auth_type(neighbor->auth_data().KeyTypeToString());
if (bsc->test_mode()) {
nbr.set_auth_keys(neighbor->auth_data().KeysToStringDetail());
}

vector<ShowBgpNeighborFamilyConfig> family_attributes_list;
BOOST_FOREACH(const BgpFamilyAttributesConfig family_config,
neighbor->family_attributes_list()) {
ShowBgpNeighborFamilyConfig family_attributes;
family_attributes.family = family_config.family;
family_attributes.loop_count = family_config.loop_count;
family_attributes.prefix_limit = family_config.prefix_limit;
family_attributes_list.push_back(family_attributes);
}
nbr.set_family_attributes_list(family_attributes_list);

nbr_list.push_back(nbr);
}

Expand Down

0 comments on commit 42d7551

Please sign in to comment.