diff --git a/src/bgp/SConscript b/src/bgp/SConscript index 97188085dc8..d45a90212f6 100644 --- a/src/bgp/SConscript +++ b/src/bgp/SConscript @@ -59,6 +59,7 @@ libbgp = env.Library('bgp', 'bgp_session_manager.cc', 'bgp_session.cc', 'bgp_show_config.cc', + 'bgp_show_neighbor.cc', 'bgp_show_route_summary.cc', 'bgp_show_routing_instance.cc', 'bgp_table.cc', diff --git a/src/bgp/bgp_peer.cc b/src/bgp/bgp_peer.cc index e4784087d29..140792407c4 100644 --- a/src/bgp/bgp_peer.cc +++ b/src/bgp/bgp_peer.cc @@ -1713,7 +1713,7 @@ void BgpPeer::FillBgpNeighborDebugState(BgpNeighborResp &resp, resp.set_tx_socket_stats(peer_socket_stats); } -void BgpPeer::FillNeighborInfo(BgpSandeshContext *bsc, +void BgpPeer::FillNeighborInfo(const BgpSandeshContext *bsc, vector *nbr_list, bool summary) const { BgpNeighborResp nbr; nbr.set_peer(peer_basename_); diff --git a/src/bgp/bgp_peer.h b/src/bgp/bgp_peer.h index 6a1e812cf9c..28325305415 100644 --- a/src/bgp/bgp_peer.h +++ b/src/bgp/bgp_peer.h @@ -154,7 +154,7 @@ class BgpPeer : public IPeer { const BgpNeighborConfig *config() const { return config_; } virtual void SetDataCollectionKey(BgpPeerInfo *peer_info) const; - void FillNeighborInfo(BgpSandeshContext *bsc, + void FillNeighborInfo(const BgpSandeshContext *bsc, std::vector *nbr_list, bool summary) const; // thread-safe diff --git a/src/bgp/bgp_peer.sandesh b/src/bgp/bgp_peer.sandesh index 795b53214b2..5162ed95093 100644 --- a/src/bgp/bgp_peer.sandesh +++ b/src/bgp/bgp_peer.sandesh @@ -22,8 +22,7 @@ traceobject sandesh BgpPeerObjectTrace { } request sandesh BgpNeighborReq { - 1: string neighbor; - 2: string domain; + 1: string search_string; } struct BgpNeighborRoutingInstance { @@ -79,10 +78,14 @@ struct BgpNeighborResp { response sandesh BgpNeighborListResp { 1: list neighbors; + 2: optional string next_batch (link="BgpNeighborReqIterate", + link_title="next_batch"); } response sandesh ShowBgpNeighborSummaryResp { 1: list neighbors; + 2: optional string next_batch (link="ShowBgpNeighborSummaryReqIterate", + link_title="next_batch"); } request sandesh ShowBgpNeighborSummaryReq { diff --git a/src/bgp/bgp_peer_internal.sandesh b/src/bgp/bgp_peer_internal.sandesh index 7a7a47e218d..f7a93ec0684 100644 --- a/src/bgp/bgp_peer_internal.sandesh +++ b/src/bgp/bgp_peer_internal.sandesh @@ -4,6 +4,14 @@ include "bgp/bgp_peer.sandesh" +request sandesh BgpNeighborReqIterate { + 1: string iterate_info; +} + +request sandesh ShowBgpNeighborSummaryReqIterate { + 1: string iterate_info; +} + request sandesh ShowNeighborStatisticsReq { 1: string bgp_or_xmpp; // BGP or XMPP 2: string up_or_down; // "UP" for Established, "DOWN" for not-Established diff --git a/src/bgp/bgp_peer_membership.cc b/src/bgp/bgp_peer_membership.cc index 7eafbc41446..f6d036f74ee 100644 --- a/src/bgp/bgp_peer_membership.cc +++ b/src/bgp/bgp_peer_membership.cc @@ -26,6 +26,8 @@ #include "bgp/scheduling_group.h" #include "db/db.h" +using std::vector; + int PeerRibMembershipManager::membership_task_id_ = -1; const int PeerRibMembershipManager::kMembershipTaskInstanceId; @@ -811,6 +813,17 @@ IPeerRib *PeerRibMembershipManager::IPeerRibFind(IPeer *ipeer, return (iter != peer_rib_set_.end() ? *iter : NULL); } +// +// Find the IPeerRib corresponding to the given IPeer and BgpTable. +// Const version. +// +const IPeerRib *PeerRibMembershipManager::IPeerRibFind(IPeer *ipeer, + BgpTable *table) const { + IPeerRib peer_rib(ipeer, table, NULL); + PeerRibSet::const_iterator iter = peer_rib_set_.find(&peer_rib); + return (iter != peer_rib_set_.end() ? *iter : NULL); +} + // // Find or create the IPeerRib corresponding to the given IPeer and BgpTable. // @@ -824,34 +837,42 @@ IPeerRib *PeerRibMembershipManager::IPeerRibLocate(IPeer *ipeer, // Return the instance-id of the IPeer for the BgpTable. // int PeerRibMembershipManager::GetRegistrationId(const IPeer *ipeer, - BgpTable *table) { + const BgpTable *table) const { assert(ipeer->IsXmppPeer()); - IPeerRib *peer_rib = IPeerRibFind(const_cast(ipeer), table); + const IPeerRib *peer_rib = IPeerRibFind( + const_cast(ipeer), const_cast(table)); return (peer_rib ? peer_rib->instance_id() : -1); } void PeerRibMembershipManager::FillPeerMembershipInfo(const IPeer *peer, - BgpNeighborResp *resp) { + BgpNeighborResp *resp) const { assert(resp->get_routing_tables().size() == 0); IPeer *nc_peer = const_cast(peer); - SchedulingGroupManager *sg_mgr = server_->scheduling_group_manager(); - SchedulingGroup *sg = sg_mgr->PeerGroup(nc_peer); - resp->set_send_state(sg ? - (sg->PeerInSync(nc_peer) ? "in sync" : "not in sync") : - "not advertising"); - IPeerRib peer_rib(nc_peer, NULL, this); - PeerRibMembershipManager::PeerRibSet::iterator it = - peer_rib_set_.lower_bound(&peer_rib); - std::vector table_list; - for (; it != peer_rib_set_.end(); it++) { - if ((*it)->ipeer() != peer) break; + const SchedulingGroupManager *sg_mgr = server_->scheduling_group_manager(); + const SchedulingGroup *sg = sg_mgr->PeerGroup(nc_peer); + if (sg) { + resp->set_send_state( + sg->PeerInSync(nc_peer) ? "in sync" : "not in sync"); + } else { + resp->set_send_state("not advertising"); + } + + IPeerRib peer_rib( + nc_peer, NULL, const_cast(this)); + vector table_list; + for (PeerRibMembershipManager::PeerRibSet::const_iterator it = + peer_rib_set_.lower_bound(&peer_rib); + it != peer_rib_set_.end(); ++it) { + if ((*it)->ipeer() != peer) + break; BgpNeighborRoutingTable table; table.set_name((*it)->table()->name()); table.set_current_state("subscribed"); table_list.push_back(table); } - if (table_list.size()) resp->set_routing_tables(table_list); + if (table_list.size()) + resp->set_routing_tables(table_list); } void PeerRibMembershipManager::FillRegisteredTable(const IPeer *peer, diff --git a/src/bgp/bgp_peer_membership.h b/src/bgp/bgp_peer_membership.h index 0210181cd3e..463e348d9c7 100644 --- a/src/bgp/bgp_peer_membership.h +++ b/src/bgp/bgp_peer_membership.h @@ -168,7 +168,7 @@ class IPeerRib { // PeerMembershipMgr. // struct IPeerRibCompare { - bool operator()(const IPeerRib *lhs, const IPeerRib *rhs) { + bool operator()(const IPeerRib *lhs, const IPeerRib *rhs) const { return lhs->operator<(*rhs); } }; @@ -226,7 +226,7 @@ class PeerRibMembershipManager { } return false; } - int GetRegistrationId(const IPeer *ipeer, BgpTable *table); + int GetRegistrationId(const IPeer *ipeer, const BgpTable *table) const; void Enqueue(IPeerRibEvent *event) { event_queue_->Enqueue(event); } @@ -234,8 +234,9 @@ class PeerRibMembershipManager { void FillRoutingInstanceTableInfo(ShowRoutingInstanceTable *srit, const BgpTable *table) const; - void FillPeerMembershipInfo(const IPeer *peer, BgpNeighborResp *resp); + void FillPeerMembershipInfo(const IPeer *peer, BgpNeighborResp *resp) const; IPeerRib *IPeerRibFind(IPeer *ipeer, BgpTable *table); + const IPeerRib *IPeerRibFind(IPeer *ipeer, BgpTable *table) const; bool IsQueueEmpty() const { return event_queue_->IsQueueEmpty(); } void FillRegisteredTable(const IPeer *peer, std::vector *list); size_t GetMembershipCount() const { return peer_rib_set_.size(); } diff --git a/src/bgp/bgp_sandesh.cc b/src/bgp/bgp_sandesh.cc index ff78c47d284..c40a4b5543e 100644 --- a/src/bgp/bgp_sandesh.cc +++ b/src/bgp/bgp_sandesh.cc @@ -638,105 +638,6 @@ void ShowRouteReqIterate::HandleRequest() const { RequestPipeline rp(ps); } -class ShowNeighborHandler { -public: - static bool CallbackS1(const Sandesh *sr, - const RequestPipeline::PipeSpec ps, int stage, - int instNum, RequestPipeline::InstData *data); -}; - -bool ShowNeighborHandler::CallbackS1(const Sandesh *sr, - const RequestPipeline::PipeSpec ps, - int stage, int instNum, - RequestPipeline::InstData * data) { - vector nbr_list; - const BgpNeighborReq *req = - static_cast(ps.snhRequest_.get()); - BgpSandeshContext *bsc = - static_cast(req->client_context()); - RoutingInstanceMgr *rim = bsc->bgp_server->routing_instance_mgr(); - if (req->get_domain() != "") { - RoutingInstance *ri = rim->GetRoutingInstance(req->get_domain()); - if (ri) - ri->peer_manager()->FillBgpNeighborInfo( - bsc, &nbr_list, req->get_neighbor(), false); - } else { - for (RoutingInstanceMgr::RoutingInstanceIterator it = rim->begin(); - it != rim->end(); ++it) { - it->peer_manager()->FillBgpNeighborInfo( - bsc, &nbr_list, req->get_neighbor(), false); - } - } - - bsc->ShowNeighborExtension(&nbr_list, req); - - BgpNeighborListResp *resp = new BgpNeighborListResp; - resp->set_neighbors(nbr_list); - resp->set_context(req->context()); - resp->Response(); - return true; -} - -// handler for 'show bgp neighbor' -void BgpNeighborReq::HandleRequest() const { - RequestPipeline::PipeSpec ps(this); - RequestPipeline::StageSpec s1; - TaskScheduler *scheduler = TaskScheduler::GetInstance(); - s1.taskId_ = scheduler->GetTaskId("bgp::PeerMembership"); - s1.cbFn_ = ShowNeighborHandler::CallbackS1; - s1.instances_.push_back(0); - ps.stages_= list_of(s1); - RequestPipeline rp(ps); - -} - -class ShowNeighborSummaryHandler { -public: - static bool CallbackS1(const Sandesh *sr, - const RequestPipeline::PipeSpec ps, - int stage, int instNum, - RequestPipeline::InstData *data); -}; - -bool ShowNeighborSummaryHandler::CallbackS1(const Sandesh *sr, - const RequestPipeline::PipeSpec ps, - int stage, int instNum, - RequestPipeline::InstData * data) { - vector nbr_list; - const ShowBgpNeighborSummaryReq *req = - static_cast(ps.snhRequest_.get()); - const string &search_string = req->get_search_string(); - BgpSandeshContext *bsc = - static_cast(req->client_context()); - RoutingInstanceMgr *rim = bsc->bgp_server->routing_instance_mgr(); - for (RoutingInstanceMgr::RoutingInstanceIterator it = rim->begin(); - it != rim->end(); ++it) { - it->peer_manager()->FillBgpNeighborInfo( - bsc, &nbr_list, search_string, true); - } - - bsc->ShowNeighborSummaryExtension(&nbr_list, req); - - ShowBgpNeighborSummaryResp *resp = new ShowBgpNeighborSummaryResp; - resp->set_neighbors(nbr_list); - resp->set_context(req->context()); - resp->Response(); - return true; -} - -// handler for 'show bgp neighbor summary' -void ShowBgpNeighborSummaryReq::HandleRequest() const { - RequestPipeline::PipeSpec ps(this); - RequestPipeline::StageSpec s1; - TaskScheduler *scheduler = TaskScheduler::GetInstance(); - s1.taskId_ = scheduler->GetTaskId("bgp::PeerMembership"); - s1.cbFn_ = ShowNeighborSummaryHandler::CallbackS1; - s1.instances_.push_back(0); - ps.stages_= list_of(s1); - RequestPipeline rp(ps); - -} - class ShowNeighborStatisticsHandler { public: static bool CallbackS1(const Sandesh *sr, @@ -1403,30 +1304,25 @@ BgpSandeshContext::BgpSandeshContext() void BgpSandeshContext::SetNeighborShowExtensions( const NeighborListExtension &show_neighbor, - const NeighborSummaryListExtension &show_neighbor_summary, const NeighborStatisticsExtension &show_neighbor_statistics) { show_neighbor_ext_ = show_neighbor; - show_neighbor_summary_ext_ = show_neighbor_summary; show_neighbor_statistics_ext_ = show_neighbor_statistics; } -void BgpSandeshContext::ShowNeighborExtension( - std::vector *list, const BgpNeighborReq *req) { - if (show_neighbor_ext_) { - show_neighbor_ext_(list, this, req); - } -} - -void BgpSandeshContext::ShowNeighborSummaryExtension( - std::vector *list, const ShowBgpNeighborSummaryReq *req) { - if (show_neighbor_summary_ext_) { - show_neighbor_summary_ext_(list, this, req); - } +bool BgpSandeshContext::ShowNeighborExtension(const BgpSandeshContext *bsc, + bool summary, uint32_t page_limit, uint32_t iter_limit, + const string &start_neighbor, const string &search_string, + vector *list, string *next_neighbor) const { + if (!show_neighbor_ext_) + return true; + bool done = show_neighbor_ext_(bsc, summary, page_limit, iter_limit, + start_neighbor, search_string, list, next_neighbor); + return done; } void BgpSandeshContext::ShowNeighborStatisticsExtension( - size_t *count, const ShowNeighborStatisticsReq *req) { - if (show_neighbor_statistics_ext_) { - show_neighbor_statistics_ext_(count, this, req); - } + size_t *count, const ShowNeighborStatisticsReq *req) const { + if (!show_neighbor_statistics_ext_) + return; + show_neighbor_statistics_ext_(count, this, req); } diff --git a/src/bgp/bgp_sandesh.h b/src/bgp/bgp_sandesh.h index c76523d692f..cd57373a43d 100644 --- a/src/bgp/bgp_sandesh.h +++ b/src/bgp/bgp_sandesh.h @@ -16,35 +16,28 @@ class ShowBgpNeighborSummaryReq; class ShowNeighborStatisticsReq; struct BgpSandeshContext : public SandeshContext { - typedef boost::function *, - BgpSandeshContext *, - const BgpNeighborReq *)> - NeighborListExtension; - typedef boost::function *, - BgpSandeshContext *, - const ShowBgpNeighborSummaryReq *)> - NeighborSummaryListExtension; - typedef boost::function - NeighborStatisticsExtension; + typedef boost::function *, std::string *)> NeighborListExtension; + + typedef boost::function NeighborStatisticsExtension; BgpSandeshContext(); void SetNeighborShowExtensions( const NeighborListExtension &show_neighbor, - const NeighborSummaryListExtension &show_neighbor_summary, const NeighborStatisticsExtension &show_neighbor_statistics); BgpServer *bgp_server; BgpXmppChannelManager *xmpp_peer_manager; - void ShowNeighborExtension(std::vector *list, - const BgpNeighborReq *req); - void ShowNeighborSummaryExtension(std::vector *list, - const ShowBgpNeighborSummaryReq *req); + bool ShowNeighborExtension(const BgpSandeshContext *bsc, bool summary, + uint32_t page_limit, uint32_t iter_limit, + const std::string &start_neighbor, const std::string &search_string, + std::vector *list, std::string *next_neighbor) const; void ShowNeighborStatisticsExtension(size_t *count, - const ShowNeighborStatisticsReq *req); + const ShowNeighborStatisticsReq *req) const; // For testing. bool test_mode() const { return test_mode_; } @@ -59,7 +52,6 @@ struct BgpSandeshContext : public SandeshContext { uint32_t page_limit_; uint32_t iter_limit_; NeighborListExtension show_neighbor_ext_; - NeighborSummaryListExtension show_neighbor_summary_ext_; NeighborStatisticsExtension show_neighbor_statistics_ext_; }; diff --git a/src/bgp/bgp_show_neighbor.cc b/src/bgp/bgp_show_neighbor.cc new file mode 100644 index 00000000000..a4a4a40a555 --- /dev/null +++ b/src/bgp/bgp_show_neighbor.cc @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. + */ + +#include "bgp/bgp_show_handler.h" + +#include + +#include "bgp/bgp_peer_internal_types.h" +#include "bgp/bgp_peer_types.h" +#include "bgp/bgp_server.h" +#include "bgp/routing-instance/peer_manager.h" +#include "bgp/routing-instance/routing_instance.h" + +using std::string; +using std::vector; + +// +// Specialization of BgpShowHandler<>::CallbackCommon for regular introspect. +// +// Note that we don't both paginating bgp neighbors since the list should be +// pretty small. We always add at least one xmpp neighbor to the list and then +// paginate the xmpp neighbors as needed. +// +template <> +bool BgpShowHandler::CallbackCommon( + const BgpSandeshContext *bsc, Data *data) { + uint32_t page_limit = bsc->page_limit() ? bsc->page_limit() : kPageLimit; + uint32_t iter_limit = bsc->iter_limit() ? bsc->iter_limit() : kIterLimit; + + // Look only at the master instance since we don't have bgp neighbors in + // other instances currently. + RoutingInstanceMgr *rim = bsc->bgp_server->routing_instance_mgr(); + const RoutingInstance *rtinstance = rim->GetDefaultRoutingInstance(); + if (rtinstance && data->next_entry.empty()) { + rtinstance->peer_manager()->FillBgpNeighborInfo( + bsc, &data->show_list, data->search_string, false); + } + + // Add xmpp neighbors. + string next_neighbor; + bool done = bsc->ShowNeighborExtension(bsc, false, page_limit, iter_limit, + data->next_entry, data->search_string, &data->show_list, + &next_neighbor); + if (!next_neighbor.empty()) + SaveContextToData(next_neighbor, done, data); + return done; +} + +// +// Specialization of BgpShowHandler<>::FillShowList for regular introspect. +// +template <> +void BgpShowHandler::FillShowList( + BgpNeighborListResp *resp, const vector &show_list) { + resp->set_neighbors(show_list); +} + +// +// Specialization of BgpShowHandler<>::CallbackCommon for summary introspect. +// +// Note that we don't both paginating bgp neighbors since the list should be +// pretty small. We always add at least one xmpp neighbor to the list and then +// paginate the xmpp neighbors as needed. +// +template <> +bool BgpShowHandler::CallbackCommon( + const BgpSandeshContext *bsc, Data *data) { + uint32_t page_limit = bsc->page_limit() ? bsc->page_limit() : kPageLimit; + uint32_t iter_limit = bsc->iter_limit() ? bsc->iter_limit() : kIterLimit; + + // Look only at the master instance since we don't have bgp neighbors in + // other instances currently. + RoutingInstanceMgr *rim = bsc->bgp_server->routing_instance_mgr(); + const RoutingInstance *rtinstance = rim->GetDefaultRoutingInstance(); + if (rtinstance && data->next_entry.empty()) { + rtinstance->peer_manager()->FillBgpNeighborInfo( + bsc, &data->show_list, data->search_string, true); + } + + // Add xmpp neighbors. + string next_neighbor; + bool done = bsc->ShowNeighborExtension(bsc, true, page_limit, iter_limit, + data->next_entry, data->search_string, &data->show_list, + &next_neighbor); + if (!next_neighbor.empty()) + SaveContextToData(next_neighbor, done, data); + return done; +} + +// +// Specialization of BgpShowHandler<>::FillShowList for summary introspect. +// +template <> +void BgpShowHandler::FillShowList( + ShowBgpNeighborSummaryResp *resp, + const vector &show_list) { + resp->set_neighbors(show_list); +} + +// +// Handler for BgpNeighborReq. +// +void BgpNeighborReq::HandleRequest() const { + RequestPipeline::PipeSpec ps(this); + RequestPipeline::StageSpec s1; + TaskScheduler *scheduler = TaskScheduler::GetInstance(); + + s1.taskId_ = scheduler->GetTaskId("bgp::PeerMembership"); + s1.cbFn_ = boost::bind(&BgpShowHandler< + BgpNeighborReq, + BgpNeighborReqIterate, + BgpNeighborListResp, + BgpNeighborResp>::Callback, _1, _2, _3, _4, _5); + s1.allocFn_ = BgpShowHandler< + BgpNeighborReq, + BgpNeighborReqIterate, + BgpNeighborListResp, + BgpNeighborResp>::CreateData; + s1.instances_.push_back(0); + ps.stages_.push_back(s1); + RequestPipeline rp(ps); +} + +// +// Handler for BgpNeighborReqIterate. +// +void BgpNeighborReqIterate::HandleRequest() const { + RequestPipeline::PipeSpec ps(this); + RequestPipeline::StageSpec s1; + TaskScheduler *scheduler = TaskScheduler::GetInstance(); + + s1.taskId_ = scheduler->GetTaskId("bgp::PeerMembership"); + s1.cbFn_ = boost::bind(&BgpShowHandler< + BgpNeighborReq, + BgpNeighborReqIterate, + BgpNeighborListResp, + BgpNeighborResp>::CallbackIterate, _1, _2, _3, _4, _5); + s1.allocFn_ = BgpShowHandler< + BgpNeighborReq, + BgpNeighborReqIterate, + BgpNeighborListResp, + BgpNeighborResp>::CreateData; + s1.instances_.push_back(0); + ps.stages_.push_back(s1); + RequestPipeline rp(ps); +} + +// +// Handler for ShowBgpNeighborSummaryReq. +// +void ShowBgpNeighborSummaryReq::HandleRequest() const { + RequestPipeline::PipeSpec ps(this); + RequestPipeline::StageSpec s1; + TaskScheduler *scheduler = TaskScheduler::GetInstance(); + + s1.taskId_ = scheduler->GetTaskId("bgp::PeerMembership"); + s1.cbFn_ = boost::bind(&BgpShowHandler< + ShowBgpNeighborSummaryReq, + ShowBgpNeighborSummaryReqIterate, + ShowBgpNeighborSummaryResp, + BgpNeighborResp>::Callback, _1, _2, _3, _4, _5); + s1.allocFn_ = BgpShowHandler< + ShowBgpNeighborSummaryReq, + ShowBgpNeighborSummaryReqIterate, + ShowBgpNeighborSummaryResp, + BgpNeighborResp>::CreateData; + s1.instances_.push_back(0); + ps.stages_.push_back(s1); + RequestPipeline rp(ps); +} + +// +// Handler for ShowBgpNeighborSummaryReqIterate. +// +void ShowBgpNeighborSummaryReqIterate::HandleRequest() const { + RequestPipeline::PipeSpec ps(this); + RequestPipeline::StageSpec s1; + TaskScheduler *scheduler = TaskScheduler::GetInstance(); + + s1.taskId_ = scheduler->GetTaskId("bgp::PeerMembership"); + s1.cbFn_ = boost::bind(&BgpShowHandler< + ShowBgpNeighborSummaryReq, + ShowBgpNeighborSummaryReqIterate, + ShowBgpNeighborSummaryResp, + BgpNeighborResp>::CallbackIterate, _1, _2, _3, _4, _5); + s1.allocFn_ = BgpShowHandler< + ShowBgpNeighborSummaryReq, + ShowBgpNeighborSummaryReqIterate, + ShowBgpNeighborSummaryResp, + BgpNeighborResp>::CreateData; + s1.instances_.push_back(0); + ps.stages_.push_back(s1); + RequestPipeline rp(ps); +} diff --git a/src/bgp/bgp_xmpp_channel.cc b/src/bgp/bgp_xmpp_channel.cc index 85d52212d7d..def7c8b80ad 100644 --- a/src/bgp/bgp_xmpp_channel.cc +++ b/src/bgp/bgp_xmpp_channel.cc @@ -725,6 +725,10 @@ IPeer *BgpXmppChannel::Peer() { return peer_.get(); } +const IPeer *BgpXmppChannel::Peer() const { + return peer_.get(); +} + boost::asio::ip::tcp::endpoint BgpXmppChannel::endpoint() const { return channel_->connection()->endpoint(); } @@ -1809,9 +1813,9 @@ void BgpXmppChannel::MembershipRequestCallback(IPeer *ipeer, BgpTable *table) { membership_response_worker_.Enqueue(table->name()); } -void BgpXmppChannel::FillInstanceMembershipInfo(BgpNeighborResp *resp) { +void BgpXmppChannel::FillInstanceMembershipInfo(BgpNeighborResp *resp) const { vector instance_list; - BOOST_FOREACH(SubscribedRoutingInstanceList::value_type &entry, + BOOST_FOREACH(const SubscribedRoutingInstanceList::value_type &entry, routing_instances_) { BgpNeighborRoutingInstance instance; instance.set_name(entry.first->name()); @@ -1824,7 +1828,7 @@ void BgpXmppChannel::FillInstanceMembershipInfo(BgpNeighborResp *resp) { instance.set_import_targets(import_targets); instance_list.push_back(instance); } - BOOST_FOREACH(VrfMembershipRequestMap::value_type &entry, + BOOST_FOREACH(const VrfMembershipRequestMap::value_type &entry, vrf_membership_request_map_) { BgpNeighborRoutingInstance instance; instance.set_name(entry.first); @@ -1835,7 +1839,7 @@ void BgpXmppChannel::FillInstanceMembershipInfo(BgpNeighborResp *resp) { resp->set_routing_instances(instance_list); } -void BgpXmppChannel::FillTableMembershipInfo(BgpNeighborResp *resp) { +void BgpXmppChannel::FillTableMembershipInfo(BgpNeighborResp *resp) const { vector old_table_list = resp->get_routing_tables(); set old_table_set; vector new_table_list; @@ -1848,7 +1852,7 @@ void BgpXmppChannel::FillTableMembershipInfo(BgpNeighborResp *resp) { } } - BOOST_FOREACH(RoutingTableMembershipRequestMap::value_type &entry, + BOOST_FOREACH(const RoutingTableMembershipRequestMap::value_type &entry, routingtable_membership_request_map_) { BgpNeighborRoutingTable table; table.set_name(entry.first); @@ -2230,13 +2234,13 @@ BgpXmppChannelManager::BgpXmppChannelManager(XmppServer *xmpp_server, BgpXmppChannelManager::~BgpXmppChannelManager() { assert(channel_map_.empty()); + assert(channel_name_map_.empty()); assert(closing_count_ == 0); if (xmpp_server_) { xmpp_server_->UnRegisterConnectionEvent(xmps::BGP); } queue_.Shutdown(); - channel_map_.clear(); bgp_server_->UnregisterASNUpdateCallback(asn_listener_id_); bgp_server_->routing_instance_mgr()->UnregisterInstanceOpCallback(id_); } @@ -2245,6 +2249,9 @@ bool BgpXmppChannelManager::IsReadyForDeletion() { return bgp_server_->IsReadyForDeletion(); } +void BgpXmppChannelManager::SetQueueDisable(bool disabled) { + queue_.set_disable(disabled); +} void BgpXmppChannelManager::ASNUpdateCallback(as_t old_asn, as_t old_local_asn) { @@ -2292,8 +2299,9 @@ BgpXmppChannel *BgpXmppChannelManager::FindChannel( return it->second; } -void BgpXmppChannelManager::RemoveChannel(XmppChannel *ch) { - channel_map_.erase(ch); +void BgpXmppChannelManager::RemoveChannel(XmppChannel *channel) { + channel_map_.erase(channel); + channel_name_map_.erase(channel->ToString()); } BgpXmppChannel *BgpXmppChannelManager::CreateChannel(XmppChannel *channel) { @@ -2311,6 +2319,8 @@ void BgpXmppChannelManager::XmppHandleChannelEvent(XmppChannel *channel, if (it == channel_map_.end()) { bgp_xmpp_channel = CreateChannel(channel); channel_map_.insert(make_pair(channel, bgp_xmpp_channel)); + channel_name_map_.insert( + make_pair(channel->ToString(), bgp_xmpp_channel)); BGP_LOG_PEER(Message, bgp_xmpp_channel->Peer(), Sandesh::LoggingUtLevel(), BGP_LOG_FLAG_SYSLOG, BGP_PEER_DIR_IN, @@ -2361,7 +2371,7 @@ void BgpXmppChannel::Close() { // // Return connection's remote tcp endpoint if available // -boost::asio::ip::tcp::endpoint BgpXmppChannel::remote_endpoint() { +boost::asio::ip::tcp::endpoint BgpXmppChannel::remote_endpoint() const { const XmppSession *session = GetSession(); if (session) { return session->remote_endpoint(); @@ -2372,7 +2382,7 @@ boost::asio::ip::tcp::endpoint BgpXmppChannel::remote_endpoint() { // // Return connection's local tcp endpoint if available // -boost::asio::ip::tcp::endpoint BgpXmppChannel::local_endpoint() { +boost::asio::ip::tcp::endpoint BgpXmppChannel::local_endpoint() const { const XmppSession *session = GetSession(); if (session) { return session->local_endpoint(); diff --git a/src/bgp/bgp_xmpp_channel.h b/src/bgp/bgp_xmpp_channel.h index c221ae976e4..bdd411938bd 100644 --- a/src/bgp/bgp_xmpp_channel.h +++ b/src/bgp/bgp_xmpp_channel.h @@ -79,13 +79,14 @@ class BgpXmppChannel { void Close(); IPeer *Peer(); + const IPeer *Peer() const; virtual boost::asio::ip::tcp::endpoint endpoint() const; std::string ToString() const; std::string ToUVEKey() const; std::string StateName() const; - boost::asio::ip::tcp::endpoint remote_endpoint(); - boost::asio::ip::tcp::endpoint local_endpoint(); + boost::asio::ip::tcp::endpoint remote_endpoint() const; + boost::asio::ip::tcp::endpoint local_endpoint() const; void set_peer_deleted(); // For unit testing only. bool peer_deleted() const; @@ -101,8 +102,8 @@ class BgpXmppChannel { void RoutingInstanceCallback(std::string vrf_name, int op); void ASNUpdateCallback(as_t old_asn, as_t old_local_asn); void IdentifierUpdateCallback(Ip4Address old_identifier); - void FillInstanceMembershipInfo(BgpNeighborResp *resp); - void FillTableMembershipInfo(BgpNeighborResp *resp); + void FillInstanceMembershipInfo(BgpNeighborResp *resp) const; + void FillTableMembershipInfo(BgpNeighborResp *resp) const; const XmppChannel *channel() const { return channel_; } @@ -240,11 +241,23 @@ class BgpXmppChannel { class BgpXmppChannelManager { public: typedef std::map XmppChannelMap; + typedef std::map XmppChannelNameMap; + typedef XmppChannelNameMap::const_iterator const_name_iterator; + typedef boost::function VisitorFn; BgpXmppChannelManager(XmppServer *, BgpServer *); virtual ~BgpXmppChannelManager(); - typedef boost::function VisitorFn; + const_name_iterator name_cbegin() const { + return channel_name_map_.begin(); + } + const_name_iterator name_cend() const { + return channel_name_map_.end(); + } + const_name_iterator name_clower_bound(const std::string &name) const { + return channel_name_map_.lower_bound(name); + } + void VisitChannels(BgpXmppChannelManager::VisitorFn); BgpXmppChannel *FindChannel(const XmppChannel *channel); BgpXmppChannel *FindChannel(std::string client); @@ -258,6 +271,7 @@ class BgpXmppChannelManager { queue_.Enqueue(bx_channel); } bool IsReadyForDeletion(); + void SetQueueDisable(bool disabled); void RoutingInstanceCallback(std::string vrf_name, int op); void ASNUpdateCallback(as_t old_asn, as_t old_local_asn); void IdentifierUpdateCallback(Ip4Address old_identifier); @@ -287,6 +301,7 @@ class BgpXmppChannelManager { BgpServer *bgp_server_; WorkQueue queue_; XmppChannelMap channel_map_; + XmppChannelNameMap channel_name_map_; int id_; int asn_listener_id_; int identifier_listener_id_; diff --git a/src/bgp/bgp_xmpp_sandesh.cc b/src/bgp/bgp_xmpp_sandesh.cc index 4565a869260..072316a2cf9 100644 --- a/src/bgp/bgp_xmpp_sandesh.cc +++ b/src/bgp/bgp_xmpp_sandesh.cc @@ -14,9 +14,10 @@ #include "xmpp/xmpp_connection.h" #include "xmpp/xmpp_server.h" -using namespace std; +using std::string; +using std::vector; -static bool ShowXmppNeighborMatch(BgpXmppChannel *bx_channel, +static bool ShowXmppNeighborMatch(const BgpXmppChannel *bx_channel, const string &search_string) { if (search_string.empty()) return true; @@ -30,77 +31,69 @@ static bool ShowXmppNeighborMatch(BgpXmppChannel *bx_channel, return false; } -static void ShowXmppNeighborVisitor( - vector *nbr_list, BgpServer *bgp_server, - const string &search_string, BgpXmppChannel *bx_channel) { - if (!ShowXmppNeighborMatch(bx_channel, search_string)) - return; - BgpNeighborResp resp; - resp.set_peer(bx_channel->ToString()); - resp.set_peer_address(bx_channel->remote_endpoint().address().to_string()); - resp.set_deleted(bx_channel->peer_deleted()); - resp.set_deleted_at(UTCUsecToString(bx_channel->peer_deleted_at())); - resp.set_local_address(bx_channel->local_endpoint().address().to_string()); - resp.set_peer_type("internal"); - resp.set_encoding("XMPP"); - resp.set_state(bx_channel->StateName()); +static void FillXmppNeighborInfo(BgpNeighborResp *bnr, + const BgpSandeshContext *bsc, const BgpXmppChannel *bx_channel, + bool summary) { + bnr->set_peer(bx_channel->ToString()); + bnr->set_peer_address(bx_channel->remote_endpoint().address().to_string()); + bnr->set_deleted(bx_channel->peer_deleted()); + bnr->set_deleted_at(UTCUsecToString(bx_channel->peer_deleted_at())); + bnr->set_local_address(bx_channel->local_endpoint().address().to_string()); + bnr->set_peer_type("internal"); + bnr->set_encoding("XMPP"); + bnr->set_state(bx_channel->StateName()); const XmppConnection *connection = bx_channel->channel()->connection(); - resp.set_configured_hold_time(connection->GetConfiguredHoldTime()); - resp.set_negotiated_hold_time(connection->GetNegotiatedHoldTime()); - resp.set_auth_type(connection->GetXmppAuthenticationType()); - - resp.set_configured_address_families(vector()); - resp.set_negotiated_address_families(vector()); - PeerRibMembershipManager *mgr = - bx_channel->Peer()->server()->membership_mgr(); - mgr->FillPeerMembershipInfo(bx_channel->Peer(), &resp); - bx_channel->FillTableMembershipInfo(&resp); - bx_channel->FillInstanceMembershipInfo(&resp); - - BgpPeer::FillBgpNeighborDebugState(resp, bx_channel->Peer()->peer_stats()); - nbr_list->push_back(resp); -} + bnr->set_negotiated_hold_time(connection->GetNegotiatedHoldTime()); + bnr->set_auth_type(connection->GetXmppAuthenticationType()); + if (summary) + return; -static void ShowXmppNeighbor( - vector *list, BgpSandeshContext *bsc, - const BgpNeighborReq *req) { - bsc->xmpp_peer_manager->VisitChannels( - boost::bind(ShowXmppNeighborVisitor, - list, bsc->bgp_server, req->get_neighbor(), _1)); -} + bnr->set_configured_hold_time(connection->GetConfiguredHoldTime()); + bnr->set_configured_address_families(vector()); + bnr->set_negotiated_address_families(vector()); + const PeerRibMembershipManager *mgr = bsc->bgp_server->membership_mgr(); + mgr->FillPeerMembershipInfo(bx_channel->Peer(), bnr); + bx_channel->FillTableMembershipInfo(bnr); + bx_channel->FillInstanceMembershipInfo(bnr); -static void ShowXmppNeighborSummaryVisitor( - vector *nbr_list, - const string &search_string, BgpXmppChannel *bx_channel) { - if (!ShowXmppNeighborMatch(bx_channel, search_string)) - return; - BgpNeighborResp resp; - resp.set_peer(bx_channel->ToString()); - resp.set_deleted(bx_channel->peer_deleted()); - resp.set_deleted_at(UTCUsecToString(bx_channel->peer_deleted_at())); - resp.set_peer_address(bx_channel->remote_endpoint().address().to_string()); - resp.set_peer_type("internal"); - resp.set_encoding("XMPP"); - resp.set_state(bx_channel->StateName()); - resp.set_local_address(bx_channel->local_endpoint().address().to_string()); - const XmppConnection *connection = bx_channel->channel()->connection(); - resp.set_negotiated_hold_time(connection->GetNegotiatedHoldTime()); - resp.set_auth_type(connection->GetXmppAuthenticationType()); - nbr_list->push_back(resp); + BgpPeer::FillBgpNeighborDebugState(*bnr, bx_channel->Peer()->peer_stats()); } -static void ShowXmppNeighborSummary( - vector *list, BgpSandeshContext *bsc, - const ShowBgpNeighborSummaryReq *req) { - bsc->xmpp_peer_manager->VisitChannels( - boost::bind(ShowXmppNeighborSummaryVisitor, - list, req->get_search_string(), _1)); +static bool ShowXmppNeighbor(const BgpSandeshContext *bsc, bool summary, + uint32_t page_limit, uint32_t iter_limit, const string &start_neighbor, + const string &search_string, vector *list, + string *next_neighbor) { + const BgpXmppChannelManager *bxcm = bsc->xmpp_peer_manager; + BgpXmppChannelManager::const_name_iterator it = + bxcm->name_clower_bound(start_neighbor); + for (uint32_t iter_count = 0; it != bxcm->name_cend(); ++it, ++iter_count) { + const BgpXmppChannel *bx_channel = it->second; + if (!ShowXmppNeighborMatch(bx_channel, search_string)) + continue; + BgpNeighborResp bnr; + FillXmppNeighborInfo(&bnr, bsc, bx_channel, summary); + list->push_back(bnr); + if (list->size() >= page_limit) + break; + if (iter_count >= iter_limit) + break; + } + + // All done if we've looked at all channels. + if (it == bxcm->name_cend() || ++it == bxcm->name_cend()) + return true; + + // Return true if we've reached the page limit, false if we've reached the + // iteration limit. + bool done = list->size() >= page_limit; + *next_neighbor = it->second->ToString(); + return done; } static void ShowXmppNeighborStatisticsVisitor( - size_t *count, BgpServer *bgp_server, string domain, - string up_or_down, BgpXmppChannel *channel) { + size_t *count, const BgpServer *bgp_server, string domain, + string up_or_down, const BgpXmppChannel *channel) { if (boost::iequals(up_or_down, "up") && !channel->Peer()->IsReady()) { return; @@ -110,14 +103,16 @@ static void ShowXmppNeighborStatisticsVisitor( } if (!domain.empty()) { - RoutingInstanceMgr *rim = bgp_server->routing_instance_mgr(); - RoutingInstance *ri = rim->GetRoutingInstance(domain); - if (!ri) return; - BgpTable *table = ri->GetTable(Address::INET); - if (!table) return; - - if (!bgp_server->membership_mgr()->IPeerRibFind(channel->Peer(), - table)) { + const RoutingInstanceMgr *rim = bgp_server->routing_instance_mgr(); + const RoutingInstance *ri = rim->GetRoutingInstance(domain); + if (!ri) + return; + const BgpTable *table = ri->GetTable(Address::INET); + if (!table) + return; + + if (bgp_server->membership_mgr()->GetRegistrationId( + channel->Peer(), table) < 0) { return; } } @@ -126,7 +121,7 @@ static void ShowXmppNeighborStatisticsVisitor( } static void ShowXmppNeighborStatistics( - size_t *count, BgpSandeshContext *bsc, + size_t *count, const BgpSandeshContext *bsc, const ShowNeighborStatisticsReq *req) { bsc->xmpp_peer_manager->VisitChannels( boost::bind(ShowXmppNeighborStatisticsVisitor, count, @@ -135,9 +130,8 @@ static void ShowXmppNeighborStatistics( } -void RegisterSandeshShowXmppExtensions(BgpSandeshContext *ctx) { - ctx->SetNeighborShowExtensions( +void RegisterSandeshShowXmppExtensions(BgpSandeshContext *bsc) { + bsc->SetNeighborShowExtensions( &ShowXmppNeighbor, - &ShowXmppNeighborSummary, &ShowXmppNeighborStatistics); } diff --git a/src/bgp/routing-instance/peer_manager.cc b/src/bgp/routing-instance/peer_manager.cc index cb471aa4bd1..f4a16d476e1 100644 --- a/src/bgp/routing-instance/peer_manager.cc +++ b/src/bgp/routing-instance/peer_manager.cc @@ -228,11 +228,22 @@ BgpPeer *PeerManager::NextPeer(BgpPeerKey &peer_key) { return NULL; } -void PeerManager::FillBgpNeighborInfo(BgpSandeshContext *bsc, +const BgpPeer *PeerManager::NextPeer(BgpPeerKey &peer_key) const { + // Do a partial match + BgpPeerKeyMap::const_iterator loc = peers_by_key_.upper_bound(peer_key); + if (loc != peers_by_key_.end()) { + peer_key = loc->second->peer_key(); + return loc->second; + } + + return NULL; +} + +void PeerManager::FillBgpNeighborInfo(const BgpSandeshContext *bsc, vector *nbr_list, const string &search_string, - bool summary) { + bool summary) const { BgpPeerKey key = BgpPeerKey(); - while (BgpPeer *peer = NextPeer(key)) { + while (const BgpPeer *peer = NextPeer(key)) { if (search_string.empty() || (peer->peer_basename().find(search_string) != string::npos) || (peer->peer_address_string().find(search_string) != string::npos) || diff --git a/src/bgp/routing-instance/peer_manager.h b/src/bgp/routing-instance/peer_manager.h index 880eb42c20e..b080dee2532 100644 --- a/src/bgp/routing-instance/peer_manager.h +++ b/src/bgp/routing-instance/peer_manager.h @@ -39,10 +39,11 @@ class PeerManager { virtual void DestroyIPeer(IPeer *ipeer); virtual BgpPeer *NextPeer(BgpPeerKey &key); + virtual const BgpPeer *NextPeer(BgpPeerKey &key) const; - void FillBgpNeighborInfo(BgpSandeshContext *bsc, - std::vector *nbr_list, - const std::string &search_string, bool summary); + void FillBgpNeighborInfo(const BgpSandeshContext *bsc, + std::vector *nbr_list, + const std::string &search_string, bool summary) const; size_t GetNeighborCount(std::string up_or_down); diff --git a/src/bgp/routing-instance/routing_instance.cc b/src/bgp/routing-instance/routing_instance.cc index 6cfed727bd2..a7532a1b0cf 100644 --- a/src/bgp/routing-instance/routing_instance.cc +++ b/src/bgp/routing-instance/routing_instance.cc @@ -76,6 +76,13 @@ bool RoutingInstanceMgr::deleted() { return deleter()->IsDeleted(); } +// +// Return the default routing instance. +// +const RoutingInstance *RoutingInstanceMgr::GetDefaultRoutingInstance() const { + return instances_.Find(BgpConfigManager::kMasterInstance); +} + // // Go through all export targets for the RoutingInstance and add an entry for // each one to the InstanceTargetMap. @@ -856,10 +863,13 @@ string RoutingInstance::GetTableName(string instance_name, BgpTable *RoutingInstance::GetTable(Address::Family fmly) { string table_name = RoutingInstance::GetTableName(name_, fmly); RouteTableList::const_iterator loc = GetTables().find(table_name); - if (loc != GetTables().end()) { - return loc->second; - } - return NULL; + return (loc != GetTables().end() ? loc->second : NULL); +} + +const BgpTable *RoutingInstance::GetTable(Address::Family fmly) const { + string table_name = RoutingInstance::GetTableName(name_, fmly); + RouteTableList::const_iterator loc = GetTables().find(table_name); + return (loc != GetTables().end() ? loc->second : NULL); } string RoutingInstance::GetVrfFromTableName(const string table) { diff --git a/src/bgp/routing-instance/routing_instance.h b/src/bgp/routing-instance/routing_instance.h index 78a6478e551..fcd0b7aff62 100644 --- a/src/bgp/routing-instance/routing_instance.h +++ b/src/bgp/routing-instance/routing_instance.h @@ -62,6 +62,7 @@ class RoutingInstance { static std::string GetVrfFromTableName(const std::string table); BgpTable *GetTable(Address::Family fmly); + const BgpTable *GetTable(Address::Family fmly) const; void AddTable(BgpTable *tbl); @@ -112,6 +113,7 @@ class RoutingInstance { StaticRouteMgr *static_route_mgr() { return static_route_mgr_.get(); } PeerManager *peer_manager() { return peer_manager_.get(); } + const PeerManager *peer_manager() const { return peer_manager_.get(); } private: class DeleteActor; @@ -224,6 +226,7 @@ class RoutingInstanceMgr { return instances_.lower_bound(name); } + const RoutingInstance *GetDefaultRoutingInstance() const; RoutingInstance *GetRoutingInstance(const std::string &name) { return instances_.Find(name); } diff --git a/src/bgp/test/SConscript b/src/bgp/test/SConscript index 351d1a7bbf3..d25d7e91e2c 100644 --- a/src/bgp/test/SConscript +++ b/src/bgp/test/SConscript @@ -220,6 +220,11 @@ bgp_sg_test = env.UnitTest('bgp_sg_test', ['bgp_sg_test.cc']) env.Alias('src/bgp:bgp_sg_test', bgp_sg_test) +bgp_show_neighbor_test = env.UnitTest('bgp_show_neighbor_test', + ['bgp_show_neighbor_test.cc']) +env.Alias('src/bgp:bgp_show_neighbor_test', + bgp_show_neighbor_test) + bgp_show_route_summary_test = env.UnitTest('bgp_show_route_summary_test', ['bgp_show_route_summary_test.cc']) env.Alias('src/bgp:bgp_show_route_summary_test', @@ -391,6 +396,7 @@ test_suite = [ bgp_server_test, bgp_session_test, bgp_sg_test, + bgp_show_neighbor_test, bgp_show_routing_instance_test, bgp_stress_test, bgp_table_export_test, diff --git a/src/bgp/test/bgp_server_test_util.cc b/src/bgp/test/bgp_server_test_util.cc index 9029224d1e9..3e393bc0ed4 100644 --- a/src/bgp/test/bgp_server_test_util.cc +++ b/src/bgp/test/bgp_server_test_util.cc @@ -30,6 +30,7 @@ #include "schema/vnc_cfg_types.h" #include "testing/gunit.h" +using boost::uuids::nil_generator; using namespace boost::asio; using namespace boost; using namespace std; @@ -133,7 +134,7 @@ BgpPeer *BgpServerTest::FindPeer(const char *routing_instance, return rti->peer_manager()->PeerLookup(name); } -const BgpPeer *BgpServerTest::FindMatchingPeer(const char *routing_instance, +BgpPeer *BgpServerTest::FindMatchingPeer(const char *routing_instance, const std::string &name) { RoutingInstance *rti = inst_mgr_->GetRoutingInstance(routing_instance); PeerManager *peer_manager = rti->peer_manager(); @@ -264,6 +265,9 @@ void BgpPeerTest::BindLocalEndpoint(BgpSession *session) { if (!config_->uuid().empty()) { boost::uuids::string_generator gen; peer_key.uuid = gen(config_->uuid()); + } else { + boost::uuids::nil_generator nil; + peer_key.uuid == nil(); } tbb::mutex::scoped_lock lock(peer_connect_map_mutex_); peer_connect_map_[local_endpoint] = peer_key; @@ -281,25 +285,24 @@ PeerManagerTest::PeerManagerTest(RoutingInstance *instance) BgpPeer *PeerManagerTest::PeerLocate( BgpServer *server, const BgpNeighborConfig *config) { BgpPeer *peer = PeerManager::PeerLocate(server, config); - PeerByUuidMap::iterator loc = peers_by_uuid_.find(peer->peer_key().uuid); - - if (loc != peers_by_uuid_.end()) { - if (peer != loc->second) { - assert(peer == loc->second); - } - return peer; + boost::uuids::nil_generator nil; + if (peer->peer_key().uuid != nil()) { + PeerByUuidMap::iterator loc = peers_by_uuid_.find(peer->peer_key().uuid); + assert(loc == peers_by_uuid_.end() || peer == loc->second); + peers_by_uuid_.insert(make_pair(peer->peer_key().uuid, peer)); } - - peers_by_uuid_.insert(make_pair(peer->peer_key().uuid, peer)); return peer; } void PeerManagerTest::DestroyIPeer(IPeer *ipeer) { BgpPeerTest *peer = static_cast(ipeer); - PeerByUuidMap::iterator loc = peers_by_uuid_.find(peer->peer_key().uuid); - - assert(loc != peers_by_uuid_.end()); - peers_by_uuid_.erase(loc); + boost::uuids::nil_generator nil; + if (peer->peer_key().uuid != nil()) { + PeerByUuidMap::iterator loc = + peers_by_uuid_.find(peer->peer_key().uuid); + assert(loc != peers_by_uuid_.end()); + peers_by_uuid_.erase(loc); + } PeerManager::DestroyIPeer(ipeer); } @@ -322,6 +325,9 @@ BgpPeer *PeerManagerTest::PeerLookup(ip::tcp::endpoint remote_endpoint) { if (present) { BGP_DEBUG_UT("Peer key found in peer_connect_map_, peer_key.endpoint: " << peer_key.endpoint << ", uuid: " << peer_key.uuid); + boost::uuids::nil_generator nil; + if (peer_key.uuid == nil()) + return PeerManager::PeerLookup(remote_endpoint); } else { peer_key.endpoint = remote_endpoint; BGP_WARN_UT("Peer key not found in peer_connect_map_, " diff --git a/src/bgp/test/bgp_server_test_util.h b/src/bgp/test/bgp_server_test_util.h index d6bf3746371..7bc5e26bafc 100644 --- a/src/bgp/test/bgp_server_test_util.h +++ b/src/bgp/test/bgp_server_test_util.h @@ -190,8 +190,8 @@ class BgpServerTest : public BgpServer { const std::string &uuid); BgpPeer *FindPeer(const char *routing_instance, const std::string &peername); - const BgpPeer *FindMatchingPeer(const char *routing_instance, - const std::string &name); + BgpPeer *FindMatchingPeer(const char *routing_instance, + const std::string &name); void DisableAllPeers(); void EnableAllPeers(); void Shutdown(bool verify = true); diff --git a/src/bgp/test/bgp_show_neighbor_test.cc b/src/bgp/test/bgp_show_neighbor_test.cc new file mode 100644 index 00000000000..87099934598 --- /dev/null +++ b/src/bgp/test/bgp_show_neighbor_test.cc @@ -0,0 +1,1143 @@ +/* + * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. + */ + +#include "base/test/task_test_util.h" +#include "bgp/bgp_config.h" +#include "bgp/bgp_factory.h" +#include "bgp/bgp_peer_membership.h" +#include "bgp/bgp_sandesh.h" +#include "bgp/bgp_session_manager.h" +#include "bgp/bgp_xmpp_channel.h" +#include "bgp/bgp_xmpp_sandesh.h" +#include "bgp/test/bgp_server_test_util.h" +#include "bgp/test/bgp_test_util.h" +#include "bgp/xmpp_message_builder.h" +#include "control-node/control_node.h" +#include "control-node/test/network_agent_mock.h" +#include "ifmap/ifmap_server_parser.h" +#include "ifmap/test/ifmap_test_util.h" +#include "io/test/event_manager_test.h" +#include "schema/bgp_schema_types.h" +#include "schema/vnc_cfg_types.h" +#include "testing/gunit.h" +#include "xmpp/xmpp_factory.h" + +using std::cout; +using std::endl; +using std::string; +using std::vector; + +static const char *config_template = "\ +\ + \ + 192.168.0.1\ + 64512\ +
127.0.0.1
\ + %d\ + \ + \ + inet-vpn\ + \ + \ + \ + \ + inet-vpn\ + \ + \ +
\ + \ + 192.168.1.1\ + 64512\ +
127.0.1.1
\ + %d\ + \ + \ + inet-vpn\ + \ + \ + \ + \ + inet-vpn\ + \ + \ +
\ + \ + 192.168.1.2\ + 64512\ +
127.0.1.2
\ + %d\ + \ + \ + inet-vpn\ + \ + \ + \ + \ + inet-vpn\ + \ + \ +
\ +
\ +"; + +// +// Template structure to pass to fixture class template. Needed because +// gtest fixture class template can accept only one template parameter. +// +template +struct TypeDefinition { + typedef T1 ReqT; + typedef T2 ReqIterateT; + typedef T3 RespT; +}; + +// +// List of TypeDefinitions we want to test. +// +typedef ::testing::Types < + TypeDefinition< + BgpNeighborReq, + BgpNeighborReqIterate, + BgpNeighborListResp>, + TypeDefinition< + ShowBgpNeighborSummaryReq, + ShowBgpNeighborSummaryReqIterate, + ShowBgpNeighborSummaryResp> > TypeDefinitionList; + +// +// Fixture class template - will be instantiated further below for each entry +// in TypeDefinitionList. +// +template +class BgpShowNeighborTest : public ::testing::Test { +public: + void ValidateResponse(Sandesh *sandesh, + vector &result, const string &next_batch) { + typename T::RespT *resp = dynamic_cast(sandesh); + TASK_UTIL_EXPECT_TRUE(resp != NULL); + TASK_UTIL_EXPECT_EQ(result.size(), resp->get_neighbors().size()); + TASK_UTIL_EXPECT_EQ(next_batch, resp->get_next_batch()); + for (size_t i = 0; i < resp->get_neighbors().size(); ++i) { + TASK_UTIL_EXPECT_EQ(result[i], resp->get_neighbors()[i].get_peer()); + cout << resp->get_neighbors()[i].log() << endl; + } + validate_done_ = true; + } + +protected: + BgpShowNeighborTest() + : thread_(&evm_), xmpp_server_x_(NULL), validate_done_(false) { + } + + bool RequestIsDetail() const { return false; } + + virtual void SetUp() { + IFMapServerParser *parser = IFMapServerParser::GetInstance("schema"); + bgp_schema_ParserInit(parser); + vnc_cfg_ParserInit(parser); + + bgp_server_x_.reset(new BgpServerTest(&evm_, "X")); + bgp_server_x_->session_manager()->Initialize(0); + xmpp_server_x_ = + new XmppServerTest(&evm_, test::XmppDocumentMock::kControlNodeJID); + xmpp_server_x_->Initialize(0, false); + bcm_x_.reset( + new BgpXmppChannelManager(xmpp_server_x_, bgp_server_x_.get())); + sandesh_context_.bgp_server = bgp_server_x_.get(); + sandesh_context_.xmpp_peer_manager = bcm_x_.get(); + Sandesh::set_client_context(&sandesh_context_); + RegisterSandeshShowXmppExtensions(&sandesh_context_); + + bgp_server_y1_.reset(new BgpServerTest(&evm_, "Y1")); + bgp_server_y1_->session_manager()->Initialize(0); + bgp_server_y2_.reset(new BgpServerTest(&evm_, "Y2")); + bgp_server_y2_->session_manager()->Initialize(0); + + thread_.Start(); + Configure(); + task_util::WaitForIdle(); + + CreateAgents(); + SubscribeAgents(); + } + + virtual void TearDown() { + ShutdownAgents(); + + xmpp_server_x_->Shutdown(); + task_util::WaitForIdle(); + bgp_server_x_->Shutdown(); + bgp_server_y1_->Shutdown(); + bgp_server_y2_->Shutdown(); + task_util::WaitForIdle(); + + bcm_x_.reset(); + TcpServerManager::DeleteServer(xmpp_server_x_); + xmpp_server_x_ = NULL; + + DeleteAgents(); + + IFMapCleanUp(); + task_util::WaitForIdle(); + + evm_.Shutdown(); + thread_.Join(); + task_util::WaitForIdle(); + } + + void IFMapCleanUp() { + IFMapServerParser::GetInstance("vnc_cfg")->MetadataClear("vnc_cfg"); + IFMapServerParser::GetInstance("schema")->MetadataClear("schema"); + } + + void Configure() { + char config[4096]; + snprintf(config, sizeof(config), config_template, + bgp_server_x_->session_manager()->GetPort(), + bgp_server_y1_->session_manager()->GetPort(), + bgp_server_y2_->session_manager()->GetPort()); + + bgp_server_x_->Configure(config); + bgp_server_y1_->Configure(config); + bgp_server_y2_->Configure(config); + task_util::WaitForIdle(); + TASK_UTIL_EXPECT_EQ(2, bgp_server_x_->NumUpPeer()); + TASK_UTIL_EXPECT_EQ(2, bgp_server_y1_->NumUpPeer()); + TASK_UTIL_EXPECT_EQ(2, bgp_server_y2_->NumUpPeer()); + + if (RequestIsDetail()) { + vector instance_names; + for (int vn_idx = 100; vn_idx < 104; ++vn_idx) { + string vn_name = string("vn") + integerToString(vn_idx); + instance_names.push_back(vn_name); + } + NetworkConfig(instance_names); + VerifyNetworkConfig(bgp_server_x_.get(), instance_names); + } + } + + void NetworkConfig(const vector &instance_names) { + string netconf(bgp_util::NetworkConfigGenerate(instance_names)); + IFMapServerParser *parser = IFMapServerParser::GetInstance("schema"); + parser->Receive( + bgp_server_x_->config_db(), netconf.data(), netconf.length(), 0); + task_util::WaitForIdle(); + } + + void VerifyNetworkConfig(BgpServerTest *server, + const vector &instance_names) { + for (vector::const_iterator iter = instance_names.begin(); + iter != instance_names.end(); ++iter) { + TASK_UTIL_WAIT_NE_NO_MSG( + server->routing_instance_mgr()->GetRoutingInstance(*iter), + NULL, 1000, 10000, "Wait for routing instance.."); + const RoutingInstance *rti = + server->routing_instance_mgr()->GetRoutingInstance(*iter); + TASK_UTIL_WAIT_NE_NO_MSG(rti->virtual_network_index(), + 0, 1000, 10000, "Wait for vn index.."); + } + } + + void CreateAgents() { + for (int idx = 0; idx < 12; ++idx) { + string name = string("agent") + integerToString(900 + idx); + string address = string("127.0.2.") + integerToString(idx); + test::NetworkAgentMock *agent = new test::NetworkAgentMock( + &evm_, name, xmpp_server_x_->GetPort(), address, "127.0.0.1"); + agents_.push_back(agent); + agent_names_.push_back(name); + TASK_UTIL_EXPECT_TRUE(agent->IsEstablished()); + } + } + + void SubscribeAgents() { + if (!RequestIsDetail()) + return; + for (int vn_idx = 100; vn_idx < 104; ++vn_idx) { + string vn_name = string("vn") + integerToString(vn_idx); + for (int idx = 0; idx < 12; ++idx) { + agents_[idx]->Subscribe(vn_name, vn_idx); + } + } + // VNs * Tables per VN * Agents + Peers * AFs + TASK_UTIL_EXPECT_EQ(4 * 4 * 12 + 2 * 1, + bgp_server_x_->membership_mgr()->GetMembershipCount()); + task_util::WaitForIdle(); + } + + void ShutdownAgents() { + for (int idx = 0; idx < 12; ++idx) { + agents_[idx]->SessionDown(); + TASK_UTIL_EXPECT_FALSE(agents_[idx]->IsEstablished()); + } + } + + void DeleteAgents() { + for (int idx = 0; idx < 12; ++idx) { + agents_[idx]->Delete(); + } + STLDeleteValues(&agents_); + } + + void PauseBgpPeerDelete() { + BgpPeer *peer_y1 = bgp_server_x_->FindMatchingPeer( + BgpConfigManager::kMasterInstance, "Y1"); + peer_y1->deleter()->PauseDelete(); + BgpPeer *peer_y2 = bgp_server_x_->FindMatchingPeer( + BgpConfigManager::kMasterInstance, "Y2"); + peer_y2->deleter()->PauseDelete(); + } + + void ResumeBgpPeerDelete() { + BgpPeer *peer_y1 = bgp_server_x_->FindMatchingPeer( + BgpConfigManager::kMasterInstance, "Y1"); + peer_y1->deleter()->ResumeDelete(); + BgpPeer *peer_y2 = bgp_server_x_->FindMatchingPeer( + BgpConfigManager::kMasterInstance, "Y2"); + peer_y2->deleter()->ResumeDelete(); + } + + void AddBgpPeerNames(vector *neighbor_names, + const string &name = string()) { + if (name.empty() || name == "Y1") { + const BgpPeer *peer_y1 = bgp_server_x_->FindMatchingPeer( + BgpConfigManager::kMasterInstance, "Y1"); + EXPECT_TRUE(peer_y1 != NULL); + neighbor_names->push_back(peer_y1->peer_basename()); + } + if (name.empty() || name == "Y2") { + const BgpPeer *peer_y2 = bgp_server_x_->FindMatchingPeer( + BgpConfigManager::kMasterInstance, "Y2"); + EXPECT_TRUE(peer_y2 != NULL); + neighbor_names->push_back(peer_y2->peer_basename()); + } + } + + EventManager evm_; + ServerThread thread_; + boost::scoped_ptr bgp_server_x_; + boost::scoped_ptr bgp_server_y1_; + boost::scoped_ptr bgp_server_y2_; + XmppServerTest *xmpp_server_x_; + boost::scoped_ptr bcm_x_; + bool validate_done_; + BgpSandeshContext sandesh_context_; + vector agents_; + vector agent_names_; +}; + +// Specialization to identify BgpNeighborReq. +template<> +bool BgpShowNeighborTest >::RequestIsDetail() const { + return true; +} + +// +// Instantiate fixture class template for each entry in TypeDefinitionList. +// +TYPED_TEST_CASE(BgpShowNeighborTest, TypeDefinitionList); + +// +// Next neighbor = empty +// Page limit = 64 (default) +// Iteration limit = 0 through 3 +// Should return all neighbors. +// +TYPED_TEST(BgpShowNeighborTest, Request1) { + typedef typename TypeParam::ReqT ReqT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(0); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + this->AddBgpPeerNames(&neighbor_names); + for (int idx = 0; idx < 12; ++idx) { + neighbor_names.push_back(this->agent_names_[idx]); + } + string next_batch; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqT *req = new ReqT; + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = empty +// Page limit = 14 (number of neighbors) +// Iteration limit = 0 through 3 +// Should return all neighbors. +// +TYPED_TEST(BgpShowNeighborTest, Request2) { + typedef typename TypeParam::ReqT ReqT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(14); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + this->AddBgpPeerNames(&neighbor_names); + for (int idx = 0; idx < 12; ++idx) { + neighbor_names.push_back(this->agent_names_[idx]); + } + string next_batch; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqT *req = new ReqT; + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = empty +// Page limit = 1 through (Number of Bgp Peers + 1) +// Iteration limit = 1024 +// Should return 2 bgp neighbors + first xmpp neighbor. +// +TYPED_TEST(BgpShowNeighborTest, Request3) { + typedef typename TypeParam::ReqT ReqT; + + for (uint32_t page_limit = 1; page_limit <= 3; ++page_limit) { + this->sandesh_context_.set_page_limit(page_limit); + this->sandesh_context_.set_iter_limit(0); + vector neighbor_names; + this->AddBgpPeerNames(&neighbor_names); + neighbor_names.push_back(this->agent_names_[0]); + string next_batch = this->agent_names_[1] + "||"; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqT *req = new ReqT; + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = empty +// Page limit = 6 +// Iteration limit = 0 through 3 +// Should return 2 bgp neighbors + first 4 xmpp neighbors. +// +TYPED_TEST(BgpShowNeighborTest, Request4) { + typedef typename TypeParam::ReqT ReqT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(6); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + this->AddBgpPeerNames(&neighbor_names); + for (int idx = 0; idx < 4; ++idx) { + neighbor_names.push_back(this->agent_names_[idx]); + } + string next_batch = this->agent_names_[4] + "||"; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqT *req = new ReqT; + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = empty +// Page limit = 64 (default) +// Iteration limit = 0 through 3 +// Search string = "" +// Should return all neighbors. +// +TYPED_TEST(BgpShowNeighborTest, RequestWithSearch1) { + typedef typename TypeParam::ReqT ReqT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(0); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + this->AddBgpPeerNames(&neighbor_names); + for (int idx = 0; idx < 12; ++idx) { + neighbor_names.push_back(this->agent_names_[idx]); + } + string next_batch; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqT *req = new ReqT; + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = empty +// Page limit = 64 (default) +// Iteration limit = 0 through 3 +// Search string = "Y" +// Should return all neighbors with "Y". +// +TYPED_TEST(BgpShowNeighborTest, RequestWithSearch2) { + typedef typename TypeParam::ReqT ReqT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(0); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + this->AddBgpPeerNames(&neighbor_names); + string next_batch; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqT *req = new ReqT; + req->set_search_string("Y"); + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = empty +// Page limit = 64 (default) +// Iteration limit = 0 through 3 +// Search string = "agent" +// Should return all neighbors with "agent". +// +TYPED_TEST(BgpShowNeighborTest, RequestWithSearch3) { + typedef typename TypeParam::ReqT ReqT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(0); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + for (int idx = 0; idx < 12; ++idx) { + neighbor_names.push_back(this->agent_names_[idx]); + } + string next_batch; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqT *req = new ReqT; + req->set_search_string("agent"); + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = empty +// Page limit = 12 (number of matching neighbors) +// Iteration limit = 0 through 3 +// Search string = "agent" +// Should return all neighbors with "agent". +// +TYPED_TEST(BgpShowNeighborTest, RequestWithSearch4) { + typedef typename TypeParam::ReqT ReqT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(0); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + for (int idx = 0; idx < 12; ++idx) { + neighbor_names.push_back(this->agent_names_[idx]); + } + string next_batch; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqT *req = new ReqT; + req->set_search_string("agent"); + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = empty +// Page limit = 4 +// Iteration limit = 0 through 3 +// Search string = "agent" +// Should return first 4 neighbors with "agent". +// +TYPED_TEST(BgpShowNeighborTest, RequestWithSearch5) { + typedef typename TypeParam::ReqT ReqT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(4); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + for (int idx = 0; idx < 4; ++idx) { + neighbor_names.push_back(this->agent_names_[idx]); + } + string next_batch = "agent904||agent"; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqT *req = new ReqT; + req->set_search_string("agent"); + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = empty +// Page limit = 64 (default) +// Iteration limit = 0 through 3 +// Search string = "xyz" +// Should return empty list. +// +TYPED_TEST(BgpShowNeighborTest, RequestWithSearch6) { + typedef typename TypeParam::ReqT ReqT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(0); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + string next_batch; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqT *req = new ReqT; + req->set_search_string("xyz"); + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = empty +// Page limit = 64 (default) +// Iteration limit = 0 through 3 +// Search string = "deleted" +// Should return empty list. +// +TYPED_TEST(BgpShowNeighborTest, RequestWithSearch7) { + typedef typename TypeParam::ReqT ReqT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(0); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + string next_batch; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqT *req = new ReqT; + req->set_search_string("deleted"); + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = empty +// Page limit = 64 (default) +// Iteration limit = 1024 (default) +// Search string = "deleted" +// Should return all neighbors (they are marked deleted) +// +TYPED_TEST(BgpShowNeighborTest, RequestWithSearch8) { + typedef typename TypeParam::ReqT ReqT; + + this->PauseBgpPeerDelete(); + this->bcm_x_->SetQueueDisable(true); + this->ShutdownAgents(); + this->bgp_server_x_->Shutdown(false); + this->sandesh_context_.set_page_limit(0); + this->sandesh_context_.set_iter_limit(0); + vector neighbor_names; + this->AddBgpPeerNames(&neighbor_names); + for (int idx = 0; idx < 12; ++idx) { + neighbor_names.push_back(this->agent_names_[idx]); + } + string next_batch; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqT *req = new ReqT; + req->set_search_string("deleted"); + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + this->bcm_x_->SetQueueDisable(false); + this->ResumeBgpPeerDelete(); +} + +// +// Next neighbor = empty +// Page limit = 64 (default) +// Iteration limit = 1024 (default) +// Search string = "Y1" +// Should return 1 neighbor. +// +TYPED_TEST(BgpShowNeighborTest, RequestWithSearch9) { + typedef typename TypeParam::ReqT ReqT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(0); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + this->AddBgpPeerNames(&neighbor_names, "Y1"); + string next_batch; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqT *req = new ReqT; + req->set_search_string("Y1"); + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = empty +// Page limit = 64 (default) +// Iteration limit = 1024 (default) +// Search string = "127.0.1.1" +// Should return 1 neighbor. +// +TYPED_TEST(BgpShowNeighborTest, RequestWithSearch10) { + typedef typename TypeParam::ReqT ReqT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(0); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + this->AddBgpPeerNames(&neighbor_names, "Y1"); + string next_batch; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqT *req = new ReqT; + req->set_search_string("127.0.1.1"); + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = empty +// Page limit = 64 (default) +// Iteration limit = 1024 (default) +// Search string = "agent907" +// Should return 1 neighbor. +// +TYPED_TEST(BgpShowNeighborTest, RequestWithSearch11) { + typedef typename TypeParam::ReqT ReqT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(0); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + neighbor_names.push_back("agent907"); + string next_batch; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqT *req = new ReqT; + req->set_search_string("agent907"); + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = empty +// Page limit = 64 (default) +// Iteration limit = 1024 (default) +// Search string = "127.0.2.7" +// Should return 1 neighbor. +// +TYPED_TEST(BgpShowNeighborTest, RequestWithSearch12) { + typedef typename TypeParam::ReqT ReqT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(0); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + neighbor_names.push_back("agent907"); + string next_batch; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqT *req = new ReqT; + req->set_search_string("127.0.2.7"); + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = "agent901" +// Page limit = 64 (default) +// Iteration limit = 0 through 3 +// Should return all neighbors including and after "agent901". +// +TYPED_TEST(BgpShowNeighborTest, RequestIterate1) { + typedef typename TypeParam::ReqIterateT ReqIterateT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(0); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + for (int idx = 1; idx < 12; ++idx) { + neighbor_names.push_back(this->agent_names_[idx]); + } + string next_batch; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqIterateT *req = new ReqIterateT; + req->set_iterate_info("agent901||"); + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = "agent901" +// Page limit = 11 +// Iteration limit = 0 through 3 +// Should return all neighbors including and after "agent901". +// +TYPED_TEST(BgpShowNeighborTest, RequestIterate2) { + typedef typename TypeParam::ReqIterateT ReqIterateT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(11); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + for (int idx = 1; idx < 12; ++idx) { + neighbor_names.push_back(this->agent_names_[idx]); + } + string next_batch; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqIterateT *req = new ReqIterateT; + req->set_iterate_info("agent901||"); + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = "agent901" +// Page limit = 4 +// Iteration limit = 0 through 3 +// Should return first 4 neighbors including and after "agent901". +// +TYPED_TEST(BgpShowNeighborTest, RequestIterate3) { + typedef typename TypeParam::ReqIterateT ReqIterateT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(4); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + for (int idx = 1; idx < 5; ++idx) { + neighbor_names.push_back(this->agent_names_[idx]); + } + string next_batch = "agent905||"; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqIterateT *req = new ReqIterateT; + req->set_iterate_info("agent901||"); + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = "" +// Page limit = 4 +// Iteration limit = 0 through 3 +// Should return empty list. +// +TYPED_TEST(BgpShowNeighborTest, RequestIterate4) { + typedef typename TypeParam::ReqIterateT ReqIterateT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(4); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + string next_batch; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqIterateT *req = new ReqIterateT; + req->set_iterate_info(""); + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = malformed +// Page limit = 4 +// Iteration limit = 0 through 3 +// Should return empty list. +// +TYPED_TEST(BgpShowNeighborTest, RequestIterate5) { + typedef typename TypeParam::ReqIterateT ReqIterateT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(4); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + string next_batch; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqIterateT *req = new ReqIterateT; + req->set_iterate_info("agent901"); + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = malformed +// Page limit = 4 +// Iteration limit = 0 through 3 +// Should return empty list. +// +TYPED_TEST(BgpShowNeighborTest, RequestIterate6) { + typedef typename TypeParam::ReqIterateT ReqIterateT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(4); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + string next_batch; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqIterateT *req = new ReqIterateT; + req->set_iterate_info("agent901|"); + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = "agent919" +// Page limit = 4 +// Iteration limit = 0 through 3 +// Should return empty list. +// +TYPED_TEST(BgpShowNeighborTest, RequestIterate7) { + typedef typename TypeParam::ReqIterateT ReqIterateT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(4); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + string next_batch; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqIterateT *req = new ReqIterateT; + req->set_iterate_info("agent919||"); + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = "agent901" +// Page limit = 64 (default) +// Iteration limit = 0 through 3 +// Search string = "agent90" +// Should return all neighbors including and after "agent901" with "agent90" +// +TYPED_TEST(BgpShowNeighborTest, RequestIterateWithSearch1) { + typedef typename TypeParam::ReqIterateT ReqIterateT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(0); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + for (int idx = 1; idx < 10; ++idx) { + neighbor_names.push_back(this->agent_names_[idx]); + } + string next_batch; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqIterateT *req = new ReqIterateT; + req->set_iterate_info("agent901||agent90"); + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = "agent901" +// Page limit = 4 +// Iteration limit = 0 through 3 +// Search string = "agent90" +// Should return first 4 neighbors including and after "agent901" with "agent90" +// +TYPED_TEST(BgpShowNeighborTest, RequestIterateWithSearch2) { + typedef typename TypeParam::ReqIterateT ReqIterateT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(4); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + for (int idx = 1; idx < 5; ++idx) { + neighbor_names.push_back(this->agent_names_[idx]); + } + string next_batch = "agent905||agent90"; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqIterateT *req = new ReqIterateT; + req->set_iterate_info("agent901||agent90"); + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = "agent901" +// Page limit = 9 +// Iteration limit = 0 through 3 +// Search string = "agent90" +// Should return first 9 neighbors including and after "agent901" with "agent90" +// +TYPED_TEST(BgpShowNeighborTest, RequestIterateWithSearch3) { + typedef typename TypeParam::ReqIterateT ReqIterateT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(9); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + for (int idx = 1; idx < 10; ++idx) { + neighbor_names.push_back(this->agent_names_[idx]); + } + string next_batch = "agent910||agent90"; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqIterateT *req = new ReqIterateT; + req->set_iterate_info("agent901||agent90"); + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +// +// Next neighbor = "agent901" +// Page limit = 9 +// Iteration limit = 1 through 3 +// Search string = "agent92" +// Should return empty list. +// +TYPED_TEST(BgpShowNeighborTest, RequestIterateWithSearch4) { + typedef typename TypeParam::ReqIterateT ReqIterateT; + + for (uint32_t iter_limit = 0; iter_limit <= 3; ++iter_limit) { + this->sandesh_context_.set_page_limit(9); + this->sandesh_context_.set_iter_limit(iter_limit); + vector neighbor_names; + string next_batch; + Sandesh::set_response_callback(boost::bind( + &BgpShowNeighborTest::ValidateResponse, this, + _1, neighbor_names, next_batch)); + this->validate_done_ = false; + ReqIterateT *req = new ReqIterateT; + req->set_iterate_info("agent901||agent92"); + req->HandleRequest(); + req->Release(); + TASK_UTIL_EXPECT_TRUE(this->validate_done_); + } +} + +class TestEnvironment : public ::testing::Environment { + virtual ~TestEnvironment() { } +}; + +static void SetUp() { + ControlNode::SetDefaultSchedulingPolicy(); + BgpServerTest::GlobalSetUp(); + BgpObjectFactory::Register( + boost::factory()); + BgpObjectFactory::Register( + boost::factory()); + XmppObjectFactory::Register( + boost::factory()); +} + +static void TearDown() { + task_util::WaitForIdle(); + TaskScheduler *scheduler = TaskScheduler::GetInstance(); + scheduler->Terminate(); +} + +int main(int argc, char **argv) { + bgp_log_test::init(); + ::testing::InitGoogleTest(&argc, argv); + ::testing::AddGlobalTestEnvironment(new TestEnvironment()); + SetUp(); + int result = RUN_ALL_TESTS(); + TearDown(); + return result; +} diff --git a/src/bgp/test/bgp_xmpp_test.cc b/src/bgp/test/bgp_xmpp_test.cc index 103eff748b9..79805dfc815 100644 --- a/src/bgp/test/bgp_xmpp_test.cc +++ b/src/bgp/test/bgp_xmpp_test.cc @@ -194,49 +194,6 @@ class BgpXmppUnitTest : public ::testing::Test { return cfg; } - static void ValidateNeighborResponse(Sandesh *sandesh, - vector &result) { - BgpNeighborListResp *resp = - dynamic_cast(sandesh); - TASK_UTIL_EXPECT_NE((BgpNeighborListResp *)NULL, resp); - - TASK_UTIL_EXPECT_EQ(result.size(), resp->get_neighbors().size()); - - cout << "*******************************************************"<get_neighbors().size(); i++) { - TASK_UTIL_EXPECT_EQ(result[i], - resp->get_neighbors()[i].routing_tables.size()); - cout << resp->get_neighbors()[i].peer << " " - << resp->get_neighbors()[i].encoding << endl; - size_t j = 0; - for (; j < resp->get_neighbors()[i].routing_tables.size(); j++) { - cout << "\t" << - resp->get_neighbors()[i].routing_tables[j].name << endl; - } - } - cout << "*******************************************************"< &result) { - ShowBgpNeighborSummaryResp *resp = - dynamic_cast(sandesh); - TASK_UTIL_EXPECT_TRUE(resp != NULL); - TASK_UTIL_EXPECT_EQ(result.size(), resp->get_neighbors().size()); - - cout << "*******************************************************"<get_neighbors().size(); i++) { - cout << resp->get_neighbors()[i].log() << endl; - TASK_UTIL_EXPECT_EQ(result[i], - resp->get_neighbors()[i].peer_address); - } - cout << "*******************************************************"< &result) { ShowRouteResp *resp = dynamic_cast(sandesh); TASK_UTIL_EXPECT_NE((ShowRouteResp *)NULL, resp); @@ -423,115 +380,9 @@ TEST_F(BgpXmppUnitTest, Connection) { sandesh_context.xmpp_peer_manager = bgp_channel_manager_; Sandesh::set_client_context(&sandesh_context); - // show neighbor - cout << "ValidateNeighborResponse:" << endl; - std::vector result = list_of(2)(9); // inet, ermvpn, enet, inet6 - Sandesh::set_response_callback(boost::bind(ValidateNeighborResponse, - _1, result)); - BgpNeighborReq *nbr_req = new BgpNeighborReq; - validate_done_ = false; - nbr_req->HandleRequest(); - nbr_req->Release(); - WAIT_EQ(true, validate_done_); - - // show neighbor for specific instance - cout << "ValidateNeighborResponse:" << endl; - result = list_of(2)(9); - Sandesh::set_response_callback(boost::bind(ValidateNeighborResponse, - _1, result)); - nbr_req = new BgpNeighborReq; - nbr_req->set_domain(BgpConfigManager::kMasterInstance); - validate_done_ = false; - nbr_req->HandleRequest(); - nbr_req->Release(); - WAIT_EQ(true, validate_done_); - - // show neighbor for non-existent instance shows only xmpp neighbors - cout << "ValidateNeighborResponse:" << endl; - result = list_of(9); - Sandesh::set_response_callback(boost::bind(ValidateNeighborResponse, - _1, result)); - nbr_req = new BgpNeighborReq; - nbr_req->set_domain("xyz"); - validate_done_ = false; - nbr_req->HandleRequest(); - nbr_req->Release(); - WAIT_EQ(true, validate_done_); - - // show neighbor for given name - cout << "ValidateNeighborResponse for agent@vnsw.contrailsystems.com:" << endl; - result = list_of(9); - Sandesh::set_response_callback(boost::bind(ValidateNeighborResponse, - _1, result)); - nbr_req = new BgpNeighborReq; - nbr_req->set_neighbor("agent@vnsw.contrailsystems.com"); - validate_done_ = false; - nbr_req->HandleRequest(); - nbr_req->Release(); - WAIT_EQ(true, validate_done_); - - // show neighbor for given name - cout << "ValidateNeighborResponse for 127.0.0.1:" << endl; - result = list_of(9); - Sandesh::set_response_callback(boost::bind(ValidateNeighborResponse, - _1, result)); - nbr_req = new BgpNeighborReq; - nbr_req->set_neighbor("agent@vnsw.contrailsystems.com"); - validate_done_ = false; - nbr_req->HandleRequest(); - nbr_req->Release(); - WAIT_EQ(true, validate_done_); - - // show neighbor for given address - cout << "ValidateNeighborResponse for 127.0.0.2:" << endl; - result = list_of(2); - Sandesh::set_response_callback(boost::bind(ValidateNeighborResponse, - _1, result)); - nbr_req = new BgpNeighborReq; - nbr_req->set_neighbor("127.0.0.2"); - validate_done_ = false; - nbr_req->HandleRequest(); - nbr_req->Release(); - WAIT_EQ(true, validate_done_); - - // show neighbor summary - cout << "ValidateNeighborSummaryResponse:" << endl; - vector s_result = list_of("127.0.0.2")("127.0.0.1"); - Sandesh::set_response_callback(boost::bind(ValidateNeighborSummaryResponse, - _1, s_result)); - ShowBgpNeighborSummaryReq *nbr_s_req = new ShowBgpNeighborSummaryReq; - validate_done_ = false; - nbr_s_req->HandleRequest(); - nbr_s_req->Release(); - WAIT_EQ(true, validate_done_); - - // show neighbor summary with good search string - cout << "ValidateNeighborSummaryResponse:" << endl; - s_result = list_of("127.0.0.1"); - Sandesh::set_response_callback(boost::bind(ValidateNeighborSummaryResponse, - _1, s_result)); - nbr_s_req = new ShowBgpNeighborSummaryReq; - validate_done_ = false; - nbr_s_req->set_search_string("0.0.1"); - nbr_s_req->HandleRequest(); - nbr_s_req->Release(); - WAIT_EQ(true, validate_done_); - - // show neighbor summary with bad search string - cout << "ValidateNeighborSummaryResponse:" << endl; - s_result.clear(); - Sandesh::set_response_callback(boost::bind(ValidateNeighborSummaryResponse, - _1, s_result)); - nbr_s_req = new ShowBgpNeighborSummaryReq; - validate_done_ = false; - nbr_s_req->set_search_string("127.0.0.7"); - nbr_s_req->HandleRequest(); - nbr_s_req->Release(); - WAIT_EQ(true, validate_done_); - // show route cout << "ValidateShowRouteResponse:" << endl; - result = list_of(1)(1)(1)(1); + std::vector result = list_of(1)(1)(1)(1); Sandesh::set_response_callback(boost::bind(ValidateShowRouteResponse, _1, result)); ShowRouteReq *show_req = new ShowRouteReq;