diff --git a/src/bgp/routing-instance/iroute_aggregator.h b/src/bgp/routing-instance/iroute_aggregator.h index 44601017e76..f36725da8f3 100644 --- a/src/bgp/routing-instance/iroute_aggregator.h +++ b/src/bgp/routing-instance/iroute_aggregator.h @@ -23,8 +23,8 @@ class IRouteAggregator { virtual bool IsAggregateRoute(const BgpRoute *route) const = 0; virtual bool IsContributingRoute(const BgpRoute *route) const = 0; - virtual bool FillAggregateRouteInfo(RoutingInstance *ri, - AggregateRouteEntriesInfo *info) const = 0; + virtual bool FillAggregateRouteInfo(AggregateRouteEntriesInfo *info, + bool summary) const = 0; private: friend class RouteAggregatorTest; diff --git a/src/bgp/routing-instance/route_aggregate.sandesh b/src/bgp/routing-instance/route_aggregate.sandesh index 31e2b7c83da..913f76d53d7 100644 --- a/src/bgp/routing-instance/route_aggregate.sandesh +++ b/src/bgp/routing-instance/route_aggregate.sandesh @@ -9,15 +9,25 @@ struct AggregateRouteInfo { 1: string prefix; 2: bgp_peer.ShowRouteBrief aggregate_rt; 3: string nexthop; - 4: list contributors; - 5: bool deleted; + 4: bool deleted; + 5: optional list contributors; } struct AggregateRouteEntriesInfo { - 1: string ri_name; + 1: string name (link="ShowRouteAggregateReq"); 2: list aggregate_route_list; } +response sandesh ShowRouteAggregateSummaryResp { + 1: list aggregate_route_entries; + 2: optional string next_batch (link="ShowRouteAggregateSummaryReqIterate", + link_title="next_batch"); +} + +request sandesh ShowRouteAggregateSummaryReq { + 1: string search_string; +} + response sandesh ShowRouteAggregateResp { 1: list aggregate_route_entries; 2: optional string next_batch (link="ShowRouteAggregateReqIterate", diff --git a/src/bgp/routing-instance/route_aggregate_internal.sandesh b/src/bgp/routing-instance/route_aggregate_internal.sandesh index c95766b524a..834453ad1fb 100644 --- a/src/bgp/routing-instance/route_aggregate_internal.sandesh +++ b/src/bgp/routing-instance/route_aggregate_internal.sandesh @@ -1,6 +1,11 @@ /* * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. */ + request sandesh ShowRouteAggregateReqIterate { 1: string iterate_info; } + +request sandesh ShowRouteAggregateSummaryReqIterate { + 1: string iterate_info; +} diff --git a/src/bgp/routing-instance/route_aggregator.cc b/src/bgp/routing-instance/route_aggregator.cc index 34d27423df5..83474ba975e 100644 --- a/src/bgp/routing-instance/route_aggregator.cc +++ b/src/bgp/routing-instance/route_aggregator.cc @@ -236,7 +236,7 @@ class AggregateRoute : public ConditionMatch { return contributors_[part_id].empty(); } - void FillShowInfo(AggregateRouteInfo *info) const; + void FillShowInfo(AggregateRouteInfo *info, bool summary) const; private: RoutingInstance *routing_instance_; @@ -481,7 +481,8 @@ void AggregateRoute::set_aggregate_route(BgpRoute *aggregate) { } template -void AggregateRoute::FillShowInfo(AggregateRouteInfo *info) const { +void AggregateRoute::FillShowInfo(AggregateRouteInfo *info, + bool summary) const { BgpTable *table = bgp_table(); info->set_deleted(deleted()); info->set_prefix(aggregate_route_prefix_.ToString()); @@ -493,6 +494,9 @@ void AggregateRoute::FillShowInfo(AggregateRouteInfo *info) const { info->set_nexthop(nexthop_.to_string()); + if (summary) + return; + std::vector contributor_list; BOOST_FOREACH(const RouteList &list, contribute_route_list()) { BOOST_FOREACH(BgpRoute *rt, list) { @@ -688,18 +692,18 @@ bool RouteAggregator::IsContributingRoute(const BgpRoute *route) const { } template -bool RouteAggregator::FillAggregateRouteInfo(RoutingInstance *ri, - AggregateRouteEntriesInfo *info) const { - if (aggregate_route_map().empty()) return false; - - info->set_ri_name(ri->name()); +bool RouteAggregator::FillAggregateRouteInfo(AggregateRouteEntriesInfo *info, + bool summary) const { + if (aggregate_route_map().empty()) + return false; - for (typename AggregateRouteMap::const_iterator it = aggregate_route_map_.begin(); - it != aggregate_route_map_.end(); it++) { + info->set_name(rtinstance_->name()); + for (typename AggregateRouteMap::const_iterator it = + aggregate_route_map_.begin(); it != aggregate_route_map_.end(); it++) { AggregateRouteT *aggregate = static_cast(it->second.get()); AggregateRouteInfo aggregate_info; - aggregate->FillShowInfo(&aggregate_info); + aggregate->FillShowInfo(&aggregate_info, summary); info->aggregate_route_list.push_back(aggregate_info); } return true; diff --git a/src/bgp/routing-instance/route_aggregator.h b/src/bgp/routing-instance/route_aggregator.h index 98e01c6795e..bf49c383c22 100644 --- a/src/bgp/routing-instance/route_aggregator.h +++ b/src/bgp/routing-instance/route_aggregator.h @@ -199,8 +199,8 @@ class RouteAggregator : public IRouteAggregator { virtual bool IsAggregateRoute(const BgpRoute *route) const; virtual bool IsContributingRoute(const BgpRoute *route) const; - virtual bool FillAggregateRouteInfo(RoutingInstance *ri, - AggregateRouteEntriesInfo *info) const; + virtual bool FillAggregateRouteInfo(AggregateRouteEntriesInfo *info, + bool summary) const; private: class DeleteActor; diff --git a/src/bgp/routing-instance/show_route_aggregate.cc b/src/bgp/routing-instance/show_route_aggregate.cc index 53544baa9fb..e78db5a7d3d 100644 --- a/src/bgp/routing-instance/show_route_aggregate.cc +++ b/src/bgp/routing-instance/show_route_aggregate.cc @@ -4,59 +4,54 @@ #include "bgp/bgp_show_handler.h" +#include +#include + #include "bgp/bgp_server.h" #include "bgp/bgp_show_handler.h" #include "bgp/routing-instance/routing_instance.h" #include "bgp/routing-instance/route_aggregator.h" +#include "bgp/routing-instance/route_aggregate_internal_types.h" #include "bgp/routing-instance/route_aggregate_types.h" +using boost::assign::list_of; using std::string; using std::vector; -static bool FillRouteAggregateInfo(Address::Family family, - const string search_string, - AggregateRouteEntriesInfo &info, - RoutingInstance *rtinstance) { - const BgpTable *table = - static_cast(rtinstance->GetTable(family)); - if (!table) - return false; - if (!search_string.empty() && - (table->name().find(search_string) == string::npos) && - (search_string != "deleted" || !table->IsDeleted())) { - return false; - } - - IRouteAggregator *iroute_aggregator = rtinstance->route_aggregator(family); - if (!iroute_aggregator) - return false; - return iroute_aggregator->FillAggregateRouteInfo(rtinstance, &info); -} - -// Specialization of BgpShowHandler<>::CallbackCommon. -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; +static bool FillRouteAggregateInfoList(const BgpSandeshContext *bsc, + bool summary, uint32_t page_limit, uint32_t iter_limit, + const string &start_instance, const string &search_string, + vector *are_list, string *next_instance) { RoutingInstanceMgr *rim = bsc->bgp_server->routing_instance_mgr(); - RoutingInstanceMgr::const_name_iterator it = - rim->name_clower_bound(data->next_entry); + rim->name_clower_bound(start_instance); for (uint32_t iter_count = 0; it != rim->name_cend(); ++it, ++iter_count) { - RoutingInstance *rinstance = it->second; - AggregateRouteEntriesInfo info; - if (FillRouteAggregateInfo(Address::INET, data->search_string, info, - rinstance)) { - data->show_list.push_back(info); - } - if (FillRouteAggregateInfo(Address::INET6, data->search_string, info, - rinstance)) { - data->show_list.push_back(info); + RoutingInstance *rtinstance = it->second; + + vector families = + list_of(Address::INET)(Address::INET6); + BOOST_FOREACH(Address::Family family, families) { + const BgpTable *table = + static_cast(rtinstance->GetTable(family)); + if (!table) + continue; + if (!search_string.empty() && + (table->name().find(search_string) == string::npos) && + (search_string != "deleted" || !table->IsDeleted())) { + continue; + } + + IRouteAggregator *iroute_aggregator = + rtinstance->route_aggregator(family); + if (!iroute_aggregator) + continue; + AggregateRouteEntriesInfo info; + if (!iroute_aggregator->FillAggregateRouteInfo(&info, summary)) + continue; + are_list->push_back(info); } - if (data->show_list.size() >= page_limit) + if (are_list->size() >= page_limit) break; if (iter_count >= iter_limit) break; @@ -68,21 +63,76 @@ bool BgpShowHandlershow_list.size() >= page_limit; - SaveContextToData(it->second->name(), done, data); + bool done = are_list->size() >= page_limit; + *next_instance = it->second->name(); return done; } -// Specialization of BgpShowHandler<>::FillShowList. +// +// Specialization of BgpShowHandler<>::CallbackCommon for regular introspect. +// template <> -void BgpShowHandler::FillShowList( - ShowRouteAggregateResp *resp, - const vector &show_list) { +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; + string next_instance; + bool done = FillRouteAggregateInfoList(bsc, false, page_limit, iter_limit, + data->next_entry, data->search_string, &data->show_list, + &next_instance); + if (!next_instance.empty()) + SaveContextToData(next_instance, done, data); + return done; +} + +// +// Specialization of BgpShowHandler<>::FillShowList for regular introspect. +// +template <> +void BgpShowHandler::FillShowList( + ShowRouteAggregateResp *resp, + const vector &show_list) { resp->set_aggregate_route_entries(show_list); } +// +// Specialization of BgpShowHandler<>::CallbackCommon for summary introspect. +// +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; + string next_instance; + bool done = FillRouteAggregateInfoList(bsc, true, page_limit, iter_limit, + data->next_entry, data->search_string, &data->show_list, + &next_instance); + if (!next_instance.empty()) + SaveContextToData(next_instance, done, data); + return done; +} + +// +// Specialization of BgpShowHandler<>::FillShowList for summary introspect. +// +template <> +void BgpShowHandler::FillShowList( + ShowRouteAggregateSummaryResp *resp, + const vector &show_list) { + resp->set_aggregate_route_entries(show_list); +} + +// // Handler for ShowRouteAggregateReq. +// void ShowRouteAggregateReq::HandleRequest() const { RequestPipeline::PipeSpec ps(this); RequestPipeline::StageSpec s1; @@ -127,3 +177,51 @@ void ShowRouteAggregateReqIterate::HandleRequest() const { ps.stages_.push_back(s1); RequestPipeline rp(ps); } + +// +// Handler for ShowRouteAggregateSummaryReq. +// +void ShowRouteAggregateSummaryReq::HandleRequest() const { + RequestPipeline::PipeSpec ps(this); + RequestPipeline::StageSpec s1; + TaskScheduler *scheduler = TaskScheduler::GetInstance(); + + s1.taskId_ = scheduler->GetTaskId("bgp::RouteAggregate"); + s1.cbFn_ = boost::bind(&BgpShowHandler< + ShowRouteAggregateSummaryReq, + ShowRouteAggregateSummaryReqIterate, + ShowRouteAggregateSummaryResp, + AggregateRouteEntriesInfo>::Callback, _1, _2, _3, _4, _5); + s1.allocFn_ = BgpShowHandler< + ShowRouteAggregateSummaryReq, + ShowRouteAggregateSummaryReqIterate, + ShowRouteAggregateSummaryResp, + AggregateRouteEntriesInfo>::CreateData; + s1.instances_.push_back(0); + ps.stages_.push_back(s1); + RequestPipeline rp(ps); +} + +// +// Handler for ShowRouteAggregateSummaryReqIterate. +// +void ShowRouteAggregateSummaryReqIterate::HandleRequest() const { + RequestPipeline::PipeSpec ps(this); + RequestPipeline::StageSpec s1; + TaskScheduler *scheduler = TaskScheduler::GetInstance(); + + s1.taskId_ = scheduler->GetTaskId("bgp::RouteAggregate"); + s1.cbFn_ = boost::bind(&BgpShowHandler< + ShowRouteAggregateSummaryReq, + ShowRouteAggregateSummaryReqIterate, + ShowRouteAggregateSummaryResp, + AggregateRouteEntriesInfo>::CallbackIterate, _1, _2, _3, _4, _5); + s1.allocFn_ = BgpShowHandler< + ShowRouteAggregateSummaryReq, + ShowRouteAggregateSummaryReqIterate, + ShowRouteAggregateSummaryResp, + AggregateRouteEntriesInfo>::CreateData; + s1.instances_.push_back(0); + ps.stages_.push_back(s1); + RequestPipeline rp(ps); +} diff --git a/src/bgp/test/route_aggregator_test.cc b/src/bgp/test/route_aggregator_test.cc index 84a277cce3f..cc5fffbff55 100644 --- a/src/bgp/test/route_aggregator_test.cc +++ b/src/bgp/test/route_aggregator_test.cc @@ -379,39 +379,50 @@ class RouteAggregatorTest : public ::testing::Test { return list; } - static void ValidateShowRouteAggregationResponse(Sandesh *sandesh, - string &result, RouteAggregatorTest *self, bool empty) { - ShowRouteAggregateResp *resp = - dynamic_cast(sandesh); - TASK_UTIL_EXPECT_NE((ShowRouteAggregateResp *)NULL, resp); - self->validate_done_ = true; - - if (empty) + template + void ValidateResponse(Sandesh *sandesh, string &result, bool empty) { + RespT *resp = dynamic_cast(sandesh); + TASK_UTIL_EXPECT_NE((RespT *) NULL, resp); + + if (empty) { TASK_UTIL_EXPECT_EQ(0, resp->get_aggregate_route_entries().size()); - else + } else { TASK_UTIL_EXPECT_EQ(1, resp->get_aggregate_route_entries().size()); + } int i = 0; BOOST_FOREACH(const AggregateRouteEntriesInfo &info, resp->get_aggregate_route_entries()) { - TASK_UTIL_EXPECT_EQ(info.get_ri_name(), result); + TASK_UTIL_EXPECT_EQ(info.get_name(), result); i++; } + validate_done_ = true; } - void VerifyRouteAggregateSandesh(std::string ri_name, bool empty=false) { + void VerifyRouteAggregateSandesh(std::string ri_name, bool empty = false) { BgpSandeshContext sandesh_context; sandesh_context.bgp_server = bgp_server_.get(); sandesh_context.xmpp_peer_manager = NULL; Sandesh::set_client_context(&sandesh_context); - Sandesh::set_response_callback( - boost::bind(ValidateShowRouteAggregationResponse, _1, ri_name, - this, empty)); + + Sandesh::set_response_callback(boost::bind( + &RouteAggregatorTest::ValidateResponse, + this, _1, ri_name, empty)); ShowRouteAggregateReq *req = new ShowRouteAggregateReq; req->set_search_string(ri_name); validate_done_ = false; req->HandleRequest(); req->Release(); TASK_UTIL_EXPECT_EQ(true, validate_done_); + + Sandesh::set_response_callback(boost::bind( + &RouteAggregatorTest::ValidateResponse, + this, _1, ri_name, empty)); + ShowRouteAggregateSummaryReq *sreq = new ShowRouteAggregateSummaryReq; + sreq->set_search_string(ri_name); + validate_done_ = false; + sreq->HandleRequest(); + sreq->Release(); + TASK_UTIL_EXPECT_EQ(true, validate_done_); } EventManager evm_;