Skip to content

Commit

Permalink
Maintain endpoint to BgpPeer map in BgpServer
Browse files Browse the repository at this point in the history
This map is used to lookup a BGPaaS BgpPeer from the source address and
source port of an incoming TCP session. If an exact match is not found,
the source address is used to find matching BgpPeer in master instance.

Highlights:

- Move relevant schema snippet from vnc_cfg.xsd to bgp_schema.xsd
- Add a remote_endpoint field to BgpNeighborConfig
- Populate new field from bgp-as-a-service_parameters property of client
- Update ifmap configuration code to use the router-type instead of name
- Set and update router_type and remote_endpoint fields in BgpPeer
- Resolve paths learnt from BgpPeers of router_type bgpaas-client
- Tweak introspect to show BgpPeers from non-master instances as well
- Add new tests to bgp_ifmap_config_manager_test and bgp_config_test

Change-Id: I93aeeba0d48942a463b772f9503932b50a640764
Partial-Bug: 1518047
  • Loading branch information
Nischal Sheth committed Dec 1, 2015
1 parent 91089e8 commit 53ef848
Show file tree
Hide file tree
Showing 19 changed files with 550 additions and 65 deletions.
2 changes: 2 additions & 0 deletions src/bgp/bgp_config.cc
Expand Up @@ -160,6 +160,7 @@ void BgpNeighborConfig::CopyValues(const BgpNeighborConfig &rhs) {
identifier_ = rhs.identifier_;
address_ = rhs.address_;
port_ = rhs.port_;
remote_endpoint_ = rhs.remote_endpoint_;
hold_time_ = rhs.hold_time_;
loop_count_ = rhs.loop_count_;
local_as_ = rhs.local_as_;
Expand All @@ -179,6 +180,7 @@ int BgpNeighborConfig::CompareTo(const BgpNeighborConfig &rhs) const {
KEY_COMPARE(identifier_, rhs.identifier_);
KEY_COMPARE(address_, rhs.address_);
KEY_COMPARE(port_, rhs.port_);
KEY_COMPARE(remote_endpoint_, rhs.remote_endpoint_);
KEY_COMPARE(hold_time_, rhs.hold_time_);
KEY_COMPARE(loop_count_, rhs.loop_count_);
KEY_COMPARE(local_as_, rhs.local_as_);
Expand Down
13 changes: 13 additions & 0 deletions src/bgp/bgp_config.h
Expand Up @@ -12,6 +12,7 @@
#include <vector>

#include "base/util.h"
#include "io/tcp_session.h"
#include "net/address.h"

class BgpServer;
Expand Down Expand Up @@ -184,6 +185,16 @@ class BgpNeighborConfig {
int port() const { return port_; }
void set_port(int port) { port_ = port; }

TcpSession::Endpoint remote_endpoint() const { return remote_endpoint_; }
void set_remote_endpoint(TcpSession::Endpoint remote_endpoint) {
remote_endpoint_ = remote_endpoint;
}

std::string router_type() const { return router_type_; }
void set_router_type(const std::string &router_type) {
router_type_ = router_type;
}

int hold_time() const { return hold_time_; }
void set_hold_time(int hold_time) { hold_time_ = hold_time; }

Expand Down Expand Up @@ -236,12 +247,14 @@ class BgpNeighborConfig {
std::string instance_name_;
std::string group_name_;
Type type_;
std::string router_type_;
bool admin_down_;
bool passive_;
uint32_t peer_as_;
uint32_t identifier_;
IpAddress address_;
int port_;
TcpSession::Endpoint remote_endpoint_;
int hold_time_;
uint8_t loop_count_;
uint32_t local_as_;
Expand Down
44 changes: 38 additions & 6 deletions src/bgp/bgp_config_ifmap.cc
Expand Up @@ -216,8 +216,11 @@ static void NeighborSetSessionAttributes(
const autogen::BgpSessionAttributes *attr = iter.operator->();
if (attr->bgp_router.empty()) {
common = attr;
} else if (attr->bgp_router == localname ||
attr->bgp_router == "BGPaaS") {
} else if (neighbor->router_type() != "bgpaas-client" &&
attr->bgp_router == localname) {
local = attr;
} else if (neighbor->router_type() == "bgpaas-client" &&
attr->bgp_router == "bgpaas-server") {
local = attr;
}
}
Expand Down Expand Up @@ -267,6 +270,7 @@ static BgpNeighborConfig *MakeBgpNeighborConfig(
// Store a copy of the remote bgp-router's autogen::BgpRouterParams and
// derive the autogen::BgpSessionAttributes for the session.
const autogen::BgpRouterParams &params = remote_router->parameters();
neighbor->set_router_type(params.router_type);
if (params.admin_down) {
neighbor->set_admin_down(true);
}
Expand All @@ -291,14 +295,36 @@ static BgpNeighborConfig *MakeBgpNeighborConfig(
}

neighbor->set_peer_identifier(IpAddressToBgpIdentifier(identifier));

neighbor->set_port(params.port);
neighbor->set_hold_time(params.hold_time);

if (session != NULL) {
NeighborSetSessionAttributes(neighbor, local_name, session);
}

// Get remote endpoint information for bgpaas-clients if appropriate.
if (params.router_type == "bgpaas-client" &&
remote_router->IsPropertySet(
autogen::BgpRouter::BGP_AS_A_SERVICE_PARAMETERS)) {
const autogen::BgpAsAServiceParameters &bgpaas_params =
remote_router->bgp_as_a_service_parameters();
Ip4Address vrouter_address =
Ip4Address::from_string(bgpaas_params.vrouter_ip_address, err);
if (err) {
BGP_LOG_STR(BgpConfig, SandeshLevel::SYS_WARN, BGP_LOG_FLAG_ALL,
"Invalid bgpaas-client vrouter ip address " <<
bgpaas_params.vrouter_ip_address <<
" for neighbor " << neighbor->name());
}
if (bgpaas_params.port < 0 || bgpaas_params.port > 65535) {
BGP_LOG_STR(BgpConfig, SandeshLevel::SYS_WARN, BGP_LOG_FLAG_ALL,
"Invalid bgpaas-client port " << bgpaas_params.port <<
" for neighbor " << neighbor->name());
}
neighbor->set_remote_endpoint(TcpSession::Endpoint(vrouter_address,
static_cast<uint16_t>(bgpaas_params.port)));
}

// Get the local identifier and local as from the master protocol config.
const BgpIfmapProtocolConfig *master_protocol =
master_instance->protocol_config();
Expand Down Expand Up @@ -501,11 +527,17 @@ bool BgpIfmapPeeringConfig::GetRouterPair(DBGraph *db_graph,
IFMapNode *adj = static_cast<IFMapNode *>(iter.operator->());
if (strcmp(adj->table()->Typename(), "bgp-router") != 0)
continue;
autogen::BgpRouter *router =
static_cast<autogen::BgpRouter *>(adj->GetObject());
if (!router)
continue;
const autogen::BgpRouterParams &params = router->parameters();
string instance_name(IdentifierParent(adj->name()));
string name = adj->name().substr(instance_name.size() + 1);
if (name == localname ||
(instance_name != BgpConfigManager::kMasterInstance &&
name == "BGPaaS")) {
if (name == localname && params.router_type != "bgpaas-client") {
local = adj;
} else if (instance_name != BgpConfigManager::kMasterInstance &&
params.router_type == "bgpaas-server") {
local = adj;
} else {
remote = adj;
Expand Down
21 changes: 18 additions & 3 deletions src/bgp/bgp_peer.cc
Expand Up @@ -343,7 +343,9 @@ BgpPeer::BgpPeer(BgpServer *server, RoutingInstance *instance,
: server_(server),
rtinstance_(instance),
peer_key_(config),
remote_endpoint_(config->remote_endpoint()),
peer_name_(config->name()),
router_type_(config->router_type()),
config_(config),
index_(server->RegisterPeer(this)),
trigger_(boost::bind(&BgpPeer::ResumeClose, this),
Expand All @@ -359,6 +361,7 @@ BgpPeer::BgpPeer(BgpServer *server, RoutingInstance *instance,
send_ready_(true),
admin_down_(config->admin_down()),
passive_(config->passive()),
resolve_paths_(config->router_type() == "bgpaas-client"),
state_machine_(BgpObjectFactory::Create<StateMachine>(this)),
membership_req_pending_(0),
defer_close_(false),
Expand Down Expand Up @@ -575,6 +578,13 @@ void BgpPeer::ConfigUpdate(const BgpNeighborConfig *config) {
clear_session = true;
}

if (router_type_ != config->router_type()) {
router_type_ = config->router_type();
peer_info.set_router_type(router_type_);
resolve_paths_ = (config->router_type() == "bgpaas-client"),
clear_session = true;
}

// 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
Expand All @@ -594,6 +604,11 @@ void BgpPeer::ConfigUpdate(const BgpNeighborConfig *config) {
clear_session = true;
}

if (remote_endpoint_ != config->remote_endpoint()) {
remote_endpoint_ = config->remote_endpoint();
clear_session = true;
}

BgpProto::BgpPeerType old_type = PeerType();
if (local_as_ != config->local_as()) {
local_as_ = config->local_as();
Expand Down Expand Up @@ -624,8 +639,8 @@ void BgpPeer::ConfigUpdate(const BgpNeighborConfig *config) {
peer_type_ = (peer_as_ == local_as_) ? BgpProto::IBGP : BgpProto::EBGP;

if (old_type != PeerType()) {
peer_info.set_peer_type(PeerType() == BgpProto::IBGP ?
"internal" : "external");
peer_info.set_peer_type(
PeerType() == BgpProto::IBGP ? "internal" : "external");
policy_.type = peer_type_;
policy_.as_number = peer_as_;
clear_session = true;
Expand Down Expand Up @@ -1118,7 +1133,7 @@ void BgpPeer::ProcessNlri(Address::Family family, DBRequest::DBOperation oper,

uint32_t BgpPeer::GetPathFlags(Address::Family family,
const BgpAttr *attr) const {
uint32_t flags = 0;
uint32_t flags = resolve_paths_ ? BgpPath::ResolveNexthop : 0;

// Check for OriginatorId loop in case we are an RR client.
if (peer_type_ == BgpProto::IBGP &&
Expand Down
6 changes: 6 additions & 0 deletions src/bgp/bgp_peer.h
Expand Up @@ -137,8 +137,10 @@ class BgpPeer : public IPeer {
return peer_key_.endpoint.address().to_string();
}
const BgpPeerKey &peer_key() const { return peer_key_; }
TcpSession::Endpoint remote_endpoint() const { return remote_endpoint_; }
const std::string &peer_name() const { return peer_name_; }
const std::string &peer_basename() const { return peer_basename_; }
std::string router_type() const { return router_type_; }

StateMachine::State GetState() const;
virtual const std::string GetStateName() const;
Expand Down Expand Up @@ -335,9 +337,12 @@ class BgpPeer : public IPeer {
// Backpointer to routing instance
RoutingInstance *rtinstance_;
BgpPeerKey peer_key_;
TcpSession::Endpoint remote_endpoint_;
std::string peer_name_;
std::string peer_basename_;
std::string router_type_; // bgp_schema.xsd:BgpRouterType
const BgpNeighborConfig *config_;

// Global peer index
int index_;
TaskTrigger trigger_;
Expand Down Expand Up @@ -368,6 +373,7 @@ class BgpPeer : public IPeer {
bool send_ready_;
bool admin_down_;
bool passive_;
bool resolve_paths_;

boost::scoped_ptr<StateMachine> state_machine_;
uint64_t membership_req_pending_;
Expand Down
1 change: 1 addition & 0 deletions src/bgp/bgp_peer.sandesh
Expand Up @@ -491,6 +491,7 @@ struct BgpPeerInfoData {
2: optional bool deleted
23: optional bool admin_down;
24: optional bool passive;
25: optional string router_type; // bgp_schema.xsd:BgpRouterType
3: optional string peer_type; // internal/external
20: optional string peer_address;
4: optional u32 local_asn;
Expand Down
39 changes: 38 additions & 1 deletion src/bgp/bgp_server.cc
Expand Up @@ -24,6 +24,7 @@
using boost::system::error_code;
using process::ConnectionState;
using std::boolalpha;
using std::make_pair;
using std::noboolalpha;
using std::string;

Expand Down Expand Up @@ -176,9 +177,14 @@ class BgpServer::ConfigUpdater {
if (event == BgpConfigManager::CFG_ADD ||
event == BgpConfigManager::CFG_CHANGE) {
BgpPeer *peer = peer_manager->PeerLocate(server_, neighbor_config);
server_->RemovePeer(peer->remote_endpoint(), peer);
peer->ConfigUpdate(neighbor_config);
server_->InsertPeer(peer->remote_endpoint(), peer);
} else if (event == BgpConfigManager::CFG_DELETE) {
peer_manager->TriggerPeerDeletion(neighbor_config);
BgpPeer *peer = peer_manager->TriggerPeerDeletion(neighbor_config);
if (peer) {
server_->RemovePeer(peer->remote_endpoint(), peer);
}
}
}

Expand Down Expand Up @@ -375,6 +381,37 @@ BgpPeer *BgpServer::FindPeer(const string &name) {
return (loc != peer_list_.end() ? loc->second : NULL);
}

void BgpServer::InsertPeer(TcpSession::Endpoint remote, BgpPeer *peer) {
if (!remote.port() || remote.address().is_unspecified())
return;

EndpointToBgpPeerList::iterator loc = endpoint_peer_list_.find(remote);
if (loc != endpoint_peer_list_.end()) {
loc->second->Clear(BgpProto::Notification::PeerDeconfigured);
endpoint_peer_list_.erase(loc);
}
endpoint_peer_list_.insert(make_pair(remote, peer));
}

void BgpServer::RemovePeer(TcpSession::Endpoint remote, BgpPeer *peer) {
EndpointToBgpPeerList::iterator loc = endpoint_peer_list_.find(remote);
if (loc != endpoint_peer_list_.end() && loc->second == peer) {
endpoint_peer_list_.erase(loc);
}
}

BgpPeer *BgpServer::FindPeer(TcpSession::Endpoint remote) const {
EndpointToBgpPeerList::const_iterator loc =
endpoint_peer_list_.find(remote);
return (loc == endpoint_peer_list_.end() ? NULL : loc->second);
}

BgpPeer *BgpServer::FindNextPeer(TcpSession::Endpoint remote) const {
EndpointToBgpPeerList::const_iterator loc =
endpoint_peer_list_.upper_bound(remote);
return (loc == endpoint_peer_list_.end() ? NULL : loc->second);
}

const string &BgpServer::localname() const {
return config_mgr_->localname();
}
Expand Down
8 changes: 8 additions & 0 deletions src/bgp/bgp_server.h
Expand Up @@ -52,6 +52,7 @@ class BgpServer {
typedef boost::function<void(Ip4Address)> IdentifierUpdateCb;
typedef boost::function<void(BgpPeer *)> VisitorFn;
typedef std::set<IStaticRouteMgr *> StaticRouteMgrList;

explicit BgpServer(EventManager *evm);
virtual ~BgpServer();

Expand All @@ -62,6 +63,11 @@ class BgpServer {
int RegisterPeer(BgpPeer *peer);
void UnregisterPeer(BgpPeer *peer);
BgpPeer *FindPeer(const std::string &name);
void InsertPeer(TcpSession::Endpoint remote, BgpPeer *peer);
void RemovePeer(TcpSession::Endpoint remote, BgpPeer *peer);
BgpPeer *FindPeer(TcpSession::Endpoint remote) const;
BgpPeer *FindNextPeer(
TcpSession::Endpoint remote = TcpSession::Endpoint()) const;

void Shutdown();

Expand Down Expand Up @@ -209,6 +215,7 @@ class BgpServer {
typedef std::vector<AdminDownCb> AdminDownListenersList;
typedef std::vector<ASNUpdateCb> ASNUpdateListenersList;
typedef std::vector<IdentifierUpdateCb> IdentifierUpdateListenersList;
typedef std::map<TcpSession::Endpoint, BgpPeer *> EndpointToBgpPeerList;

void RoutingInstanceMgrDeletionComplete(RoutingInstanceMgr *mgr);

Expand All @@ -232,6 +239,7 @@ class BgpServer {
tbb::atomic<uint32_t> num_up_peer_;
tbb::atomic<uint32_t> closing_count_;
BgpPeerList peer_list_;
EndpointToBgpPeerList endpoint_peer_list_;

boost::scoped_ptr<LifetimeManager> lifetime_manager_;
boost::scoped_ptr<DeleteActor> deleter_;
Expand Down
18 changes: 9 additions & 9 deletions src/bgp/bgp_session_manager.cc
Expand Up @@ -94,17 +94,17 @@ bool BgpSessionManager::ProcessWriteReady(TcpSessionPtr tcp_session) {
}

//
// Search in every routing instance for a matching BgpPeer.
// Search for a matching BgpPeer.
// First look for an exact match in the EndpointToBgpPeerList in BgpServer.
// Then look for a matching address in the master instance.
//
BgpPeer *BgpSessionManager::FindPeer(Endpoint remote) {
for (RoutingInstanceMgr::RoutingInstanceIterator it =
server_->routing_instance_mgr()->begin();
it != server_->routing_instance_mgr()->end(); ++it) {
BgpPeer *peer = it->peer_manager()->PeerLookup(remote);
if (peer)
return peer;
}
return NULL;
BgpPeer *peer = server_->FindPeer(remote);
if (peer)
return peer;
const RoutingInstance *instance =
server_->routing_instance_mgr()->GetDefaultRoutingInstance();
return (instance ? instance->peer_manager()->PeerLookup(remote) : NULL);
}

//
Expand Down

0 comments on commit 53ef848

Please sign in to comment.