Skip to content

Commit

Permalink
Update BgpPeer to support per address-family configuration
Browse files Browse the repository at this point in the history
Highlights:

- BgpFamilyAttributesConfig contains configuration for an address family
- Add vector of BgpFamilyAttributesConfig elements to BgpNeighborConfig
- Tweak IFMap and YAML code to build list of BgpFamilyAttributesConfig
- BgpPeerFamilyAttributes represents an address family in a BgpPeer
- Add a vector of pointers to BgpPeerFamilyAttributes in a BgpPeer
- Adjust code and unit tests to use new data structures

Pending:

- Implementation of back end code for loop_count and prefix_limit knobs

Change-Id: I6bce2a913677582e32c4f1ebee8d55f904850817
Partial-Bug: 1513278
  • Loading branch information
Nischal Sheth committed Nov 9, 2015
1 parent a74e059 commit d43ba9d
Show file tree
Hide file tree
Showing 11 changed files with 213 additions and 62 deletions.
21 changes: 18 additions & 3 deletions src/bgp/bgp_config.cc
Expand Up @@ -3,8 +3,11 @@
*/
#include "bgp/bgp_config.h"

#include <boost/foreach.hpp>

#include "base/string_util.h"
#include "base/time_util.h"
#include "base/util.h"

const char *BgpConfigManager::kMasterInstance =
"default-domain:default-project:ip-fabric:__default__";
Expand Down Expand Up @@ -156,7 +159,7 @@ void BgpNeighborConfig::CopyValues(const BgpNeighborConfig &rhs) {
local_as_ = rhs.local_as_;
local_identifier_ = rhs.local_identifier_;
auth_data_ = rhs.auth_data_;
address_families_ = rhs.address_families_;
family_attributes_list_ = rhs.family_attributes_list_;
}

int BgpNeighborConfig::CompareTo(const BgpNeighborConfig &rhs) const {
Expand All @@ -172,8 +175,20 @@ int BgpNeighborConfig::CompareTo(const BgpNeighborConfig &rhs) const {
KEY_COMPARE(local_as_, rhs.local_as_);
KEY_COMPARE(local_identifier_, rhs.local_identifier_);
KEY_COMPARE(auth_data_, rhs.auth_data_);
KEY_COMPARE(address_families_, rhs.address_families_);
return 0;
return STLSortedCompare(
family_attributes_list_.begin(), family_attributes_list_.end(),
rhs.family_attributes_list_.begin(), rhs.family_attributes_list_.end(),
BgpFamilyAttributesConfigCompare());
}

BgpNeighborConfig::AddressFamilyList BgpNeighborConfig::GetAddressFamilies(
) const {
BgpNeighborConfig::AddressFamilyList family_list;
BOOST_FOREACH(const BgpFamilyAttributesConfig family_config,
family_attributes_list_) {
family_list.push_back(family_config.family);
}
return family_list;
}

std::string BgpNeighborConfig::AuthKeyTypeToString() const {
Expand Down
42 changes: 37 additions & 5 deletions src/bgp/bgp_config.h
Expand Up @@ -79,6 +79,33 @@ class AuthenticationData {
AuthenticationKeyChain key_chain_;
};

//
// Per address family configuration for a BGP neighbor.
//
struct BgpFamilyAttributesConfig {
BgpFamilyAttributesConfig(const std::string &family)
: family(family), loop_count(0), prefix_limit(0) {
}

std::string family;
uint8_t loop_count;
uint32_t prefix_limit;
};

//
// Comparator for BgpFamilyAttributesConfig.
//
struct BgpFamilyAttributesConfigCompare {
int operator()(const BgpFamilyAttributesConfig lhs,
const BgpFamilyAttributesConfig rhs) const {
KEY_COMPARE(lhs.family, rhs.family);
KEY_COMPARE(lhs.loop_count, rhs.loop_count);
KEY_COMPARE(lhs.prefix_limit, rhs.prefix_limit);
return 0;
}
};

//
// The configuration associated with a BGP neighbor.
//
// BgpNeighborConfig represents a single session between the local bgp-router
Expand All @@ -102,6 +129,8 @@ class AuthenticationData {
class BgpNeighborConfig {
public:
typedef std::vector<std::string> AddressFamilyList;
typedef std::vector<BgpFamilyAttributesConfig> FamilyAttributesList;

enum Type {
UNSPECIFIED,
IBGP,
Expand Down Expand Up @@ -163,12 +192,15 @@ class BgpNeighborConfig {
auth_data_ = in_auth_data;
}

const AddressFamilyList &address_families() const {
return address_families_;
AddressFamilyList GetAddressFamilies() const;

const FamilyAttributesList &family_attributes_list() const {
return family_attributes_list_;
}

void set_address_families(const AddressFamilyList &address_families) {
address_families_ = address_families;
void set_family_attributes_list(
const FamilyAttributesList &family_attributes_list) {
family_attributes_list_ = family_attributes_list;
}

uint64_t last_change_at() const { return last_change_at_; }
Expand Down Expand Up @@ -197,7 +229,7 @@ class BgpNeighborConfig {
uint32_t local_identifier_;
mutable uint64_t last_change_at_;
AuthenticationData auth_data_;
AddressFamilyList address_families_;
FamilyAttributesList family_attributes_list_;

DISALLOW_COPY_AND_ASSIGN(BgpNeighborConfig);
};
Expand Down
62 changes: 55 additions & 7 deletions src/bgp/bgp_config_ifmap.cc
Expand Up @@ -89,6 +89,54 @@ static void BuildKeyChain(BgpNeighborConfig *neighbor,
neighbor->set_keydata(keydata);
}

//
// Build list of BgpFamilyAttributesConfig elements from the list of address
// families. This is provided for backward compatibility with configurations
// that represent each family with a simple string.
//
static void BuildFamilyAttributesList(BgpNeighborConfig *neighbor,
const BgpNeighborConfig::AddressFamilyList &family_list) {
BgpNeighborConfig::FamilyAttributesList family_attributes_list;
BOOST_FOREACH(const string &family, family_list) {
BgpFamilyAttributesConfig family_attributes(family);
family_attributes_list.push_back(family_attributes);
}

neighbor->set_family_attributes_list(family_attributes_list);
}

//
// Build list of BgpFamilyAttributesConfig elements from BgpFamilyAttributes
// list in BgpSessionAttributes.
//
// Implement backward compatibility by also adding BgpFamilyAttributesConfig
// elements for families that are not in BgpFamilyAttributes list but are in
// the address_families list.
//
static void BuildFamilyAttributesList(BgpNeighborConfig *neighbor,
const autogen::BgpSessionAttributes *attributes) {
set<string> family_set;
BgpNeighborConfig::FamilyAttributesList family_attributes_list;
BOOST_FOREACH(const autogen::BgpFamilyAttributes &family_config,
attributes->family_attributes) {
BgpFamilyAttributesConfig family_attributes(
family_config.address_family);
family_attributes.loop_count = family_config.loop_count;
family_attributes.prefix_limit = family_config.prefix_limit.maximum;
family_attributes_list.push_back(family_attributes);
family_set.insert(family_config.address_family);
}

BOOST_FOREACH(const string &family, attributes->address_families.family) {
if (family_set.find(family) != family_set.end())
continue;
BgpFamilyAttributesConfig family_attributes(family);
family_attributes_list.push_back(family_attributes);
}

neighbor->set_family_attributes_list(family_attributes_list);
}

//
// Set the autogen::BgpSessionAttributes for this BgpNeighborConfig.
//
Expand Down Expand Up @@ -120,7 +168,7 @@ static void NeighborSetSessionAttributes(
attributes = local;
}
if (attributes != NULL) {
neighbor->set_address_families(attributes->address_families.family);
BuildFamilyAttributesList(neighbor, attributes);
BuildKeyChain(neighbor, attributes->auth_data);
}
}
Expand Down Expand Up @@ -191,17 +239,17 @@ static BgpNeighborConfig *MakeBgpNeighborConfig(
neighbor->set_local_as(params.autonomous_system);
}

if (neighbor->address_families().empty()) {
neighbor->set_address_families(params.address_families.family);
if (neighbor->family_attributes_list().empty()) {
BuildFamilyAttributesList(neighbor, params.address_families.family);
}
if (neighbor->auth_data().Empty()) {
const autogen::BgpRouterParams &lp = local_router->parameters();
BuildKeyChain(neighbor, lp.auth_data);
}
}

if (neighbor->address_families().empty()) {
neighbor->set_address_families(default_addr_family_list);
if (neighbor->family_attributes_list().empty()) {
BuildFamilyAttributesList(neighbor, default_addr_family_list);
}

return neighbor;
Expand Down Expand Up @@ -745,7 +793,7 @@ void BgpIfmapInstanceConfig::AddNeighbor(BgpConfigManager *manager,
BgpIdentifierToString(neighbor->local_identifier()),
neighbor->local_as(),
neighbor->peer_address().to_string(), neighbor->peer_as(),
neighbor->address_families(), neighbor->AuthKeyTypeToString(),
neighbor->GetAddressFamilies(), neighbor->AuthKeyTypeToString(),
neighbor->AuthKeysToString());
neighbors_.insert(make_pair(neighbor->name(), neighbor));
manager->Notify(neighbor, BgpConfigManager::CFG_ADD);
Expand All @@ -766,7 +814,7 @@ void BgpIfmapInstanceConfig::ChangeNeighbor(BgpConfigManager *manager,
BgpIdentifierToString(neighbor->local_identifier()),
neighbor->local_as(),
neighbor->peer_address().to_string(), neighbor->peer_as(),
neighbor->address_families(), neighbor->AuthKeyTypeToString(),
neighbor->GetAddressFamilies(), neighbor->AuthKeyTypeToString(),
neighbor->AuthKeysToString());
manager->Notify(neighbor, BgpConfigManager::CFG_CHANGE);
}
Expand Down
7 changes: 4 additions & 3 deletions src/bgp/bgp_config_yaml.cc
Expand Up @@ -349,7 +349,7 @@ static bool ParseBgpGroupNeighborCommon(

if (node["address-families"]) {
YAML::Node families = node["address-families"];
BgpNeighborConfig::AddressFamilyList list;
BgpNeighborConfig::FamilyAttributesList list;
for (YAML::const_iterator iter = families.begin();
iter != families.end(); ++iter) {
string family;
Expand All @@ -363,9 +363,10 @@ static bool ParseBgpGroupNeighborCommon(
*error_msg = "Invalid address family value: " + family;
return false;
}
list.push_back(family);
BgpFamilyAttributesConfig family_config(family);
list.push_back(family_config);
}
neighbor->set_address_families(list);
neighbor->set_family_attributes_list(list);
}
return true;
}
Expand Down
80 changes: 52 additions & 28 deletions src/bgp/bgp_peer.cc
Expand Up @@ -250,6 +250,15 @@ class BgpPeer::DeleteActor : public LifetimeActor {
BgpPeer *peer_;
};

//
// Constructor for BgpPeerFamilyAttributes.
//
BgpPeerFamilyAttributes::BgpPeerFamilyAttributes(
const BgpFamilyAttributesConfig &family_config) {
loop_count = family_config.loop_count;
prefix_limit = family_config.prefix_limit;
}

void BgpPeer::ReceiveEndOfRIB(Address::Family family, size_t msgsize) {
inc_rx_end_of_rib();
BGP_LOG_PEER(Message, this, SandeshLevel::SYS_INFO,
Expand Down Expand Up @@ -352,7 +361,6 @@ BgpPeer::BgpPeer(BgpServer *server, RoutingInstance *instance,
peer_as_(config->peer_as()),
local_bgp_id_(config->local_identifier()),
peer_bgp_id_(0),
configured_families_(config->address_families()),
peer_type_((config->peer_as() == config->local_as()) ?
BgpProto::IBGP : BgpProto::EBGP),
policy_((config->peer_as() == config->local_as()) ?
Expand All @@ -375,13 +383,9 @@ BgpPeer::BgpPeer(BgpServer *server, RoutingInstance *instance,

refcount_ = 0;
primary_path_count_ = 0;
sort(configured_families_.begin(), configured_families_.end());
BOOST_FOREACH(string family, configured_families_) {
Address::Family fmly = Address::FamilyFromString(family);
assert(fmly != Address::UNSPEC);
family_.insert(fmly);
}

ProcessAuthKeyChainConfig(config);
ProcessFamilyAttributesConfig(config);

BgpPeerInfoData peer_info;
peer_info.set_name(ToUVEKey());
Expand All @@ -390,14 +394,14 @@ BgpPeer::BgpPeer(BgpServer *server, RoutingInstance *instance,
peer_info.set_local_asn(local_as_);
peer_info.set_peer_asn(peer_as_);
peer_info.set_local_id(local_bgp_id_);
if (!config->address_families().empty())
peer_info.set_configured_families(config->address_families());
peer_info.set_configured_families(config->GetAddressFamilies());
peer_info.set_peer_address(peer_key_.endpoint.address().to_string());
BGPPeerInfo::Send(peer_info);
}

BgpPeer::~BgpPeer() {
assert(GetRefCount() == 0);
STLDeleteValues(&family_attributes_list_);
ClearListenSocketAuthKey();
BgpPeerInfoData peer_info;
peer_info.set_name(ToUVEKey());
Expand Down Expand Up @@ -505,6 +509,34 @@ void BgpPeer::LogInstallAuthKeys(const std::string &oper,
BGP_PEER_DIR_NA, logstr);
}

//
// Process family attributes configuration and update the family attributes
// list.
//
// Return true is there's a change, false otherwise.
//
bool BgpPeer::ProcessFamilyAttributesConfig(const BgpNeighborConfig *config) {
FamilyAttributesList family_attributes_list(Address::NUM_FAMILIES);
BOOST_FOREACH(const BgpFamilyAttributesConfig family_config,
config->family_attributes_list()) {
Address::Family family =
Address::FamilyFromString(family_config.family);
assert(family != Address::UNSPEC);
BgpPeerFamilyAttributes *family_attributes =
new BgpPeerFamilyAttributes(family_config);
family_attributes_list[family] = family_attributes;
}

int ret = STLSortedCompare(
family_attributes_list.begin(), family_attributes_list.end(),
family_attributes_list_.begin(), family_attributes_list_.end(),
BgpPeerFamilyAttributesCompare());
STLDeleteValues(&family_attributes_list_);
family_attributes_list_ = family_attributes_list;
configured_families_ = config->GetAddressFamilies();
return (ret != 0);
}

void BgpPeer::ConfigUpdate(const BgpNeighborConfig *config) {
if (IsDeleted())
return;
Expand All @@ -513,41 +545,30 @@ void BgpPeer::ConfigUpdate(const BgpNeighborConfig *config) {

// During peer deletion, configuration gets completely deleted. In that
// case, there is no need to update the rest and flap the peer.
if (!config_) return;

AddressFamilyList new_families;
configured_families_ = config->address_families();
sort(configured_families_.begin(), configured_families_.end());
BOOST_FOREACH(string family, configured_families_) {
Address::Family fmly = Address::FamilyFromString(family);
assert(fmly != Address::UNSPEC);
new_families.insert(fmly);
}
if (!config_)
return;

bool clear_session = false;

BgpPeerInfoData peer_info;
peer_info.set_name(ToUVEKey());

// Check if there is any change in the peer address.
// If the peer address is changing, remove the key for the older address.
// Update with the new peer address and then process the key chain info
// for the new peer below.
BgpPeerKey key(config);
if (peer_key_ != key) {
// If the peer address is changing, remove the key for the older
// address. Update with the new peer address and then process the
// keychain info for the new peer below.
ClearListenSocketAuthKey();
peer_key_ = key;
peer_info.set_peer_address(peer_key_.endpoint.address().to_string());
clear_session = true;
}

ProcessAuthKeyChainConfig(config);

// Check if there is any change in the configured address families.
if (family_ != new_families) {
family_ = new_families;
if (ProcessFamilyAttributesConfig(config)) {
clear_session = true;
peer_info.set_configured_families(config->address_families());
peer_info.set_configured_families(configured_families_);
}

BgpProto::BgpPeerType old_type = PeerType();
Expand Down Expand Up @@ -966,7 +987,10 @@ void BgpPeer::SetCapabilities(const BgpProto::OpenMessage *msg) {
peer_info.set_families(families);

negotiated_families_.clear();
BOOST_FOREACH(Address::Family family, family_) {
for (int idx = Address::UNSPEC; idx < Address::NUM_FAMILIES; ++idx) {
if (!family_attributes_list_[idx])
continue;
Address::Family family = static_cast<Address::Family>(idx);
uint16_t afi;
uint8_t safi;
tie(afi, safi) = BgpAf::FamilyToAfiSafi(family);
Expand Down

0 comments on commit d43ba9d

Please sign in to comment.