Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include "bgp/bgp_sandesh.h"
6 :
7 : #include <boost/assign/list_of.hpp>
8 : #include <boost/foreach.hpp>
9 : #include <sandesh/request_pipeline.h>
10 :
11 : #include "bgp/bgp_multicast.h"
12 : #include "bgp/bgp_mvpn.h"
13 : #include "bgp/bgp_peer.h"
14 : #include "bgp/bgp_peer_internal_types.h"
15 : #include "bgp/bgp_server.h"
16 : #include "bgp/bgp_session_manager.h"
17 : #include "bgp/ermvpn/ermvpn_table.h"
18 : #include "bgp/inet/inet_table.h"
19 : #include "bgp/mvpn/mvpn_table.h"
20 : #include "bgp/routing-instance/peer_manager.h"
21 : #include "bgp/routing-instance/routing_instance.h"
22 :
23 : using boost::assign::list_of;
24 : using std::string;
25 : using std::vector;
26 :
27 : class ShowNeighborStatisticsHandler {
28 : public:
29 : static bool CallbackS1(const Sandesh *sr,
30 : const RequestPipeline::PipeSpec ps, int stage, int instNum,
31 : RequestPipeline::InstData * data);
32 : static size_t FillBgpNeighborStatistics(
33 : const ShowNeighborStatisticsReq *req, BgpServer *bgp_server);
34 : };
35 :
36 0 : size_t ShowNeighborStatisticsHandler::FillBgpNeighborStatistics(
37 : const ShowNeighborStatisticsReq *req, BgpServer *bgp_server) {
38 0 : size_t count = 0;
39 :
40 0 : if (req->get_bgp_or_xmpp().empty() ||
41 0 : boost::iequals(req->get_bgp_or_xmpp(), "bgp")) {
42 0 : RoutingInstanceMgr *rim = bgp_server->routing_instance_mgr();
43 0 : if (!req->get_domain().empty()) {
44 0 : RoutingInstance *ri = rim->GetRoutingInstance(req->get_domain());
45 0 : PeerManager *pmgr = ri ? ri->peer_manager() : NULL;
46 0 : if (pmgr) {
47 0 : count += pmgr->GetNeighborCount(req->get_up_or_down());
48 : }
49 : } else {
50 0 : RoutingInstanceMgr::RoutingInstanceIterator it = rim->begin();
51 0 : for (; it != rim->end(); it++) {
52 0 : PeerManager *pmgr = it->second->peer_manager();
53 0 : if (pmgr) {
54 0 : count += pmgr->GetNeighborCount(req->get_up_or_down());
55 : }
56 : }
57 : }
58 : }
59 :
60 0 : return count;
61 : }
62 :
63 0 : bool ShowNeighborStatisticsHandler::CallbackS1(
64 : const Sandesh *sr, const RequestPipeline::PipeSpec ps,
65 : int stage, int instNum, RequestPipeline::InstData *data) {
66 : const ShowNeighborStatisticsReq *req;
67 : BgpSandeshContext *bsc;
68 :
69 0 : req = static_cast<const ShowNeighborStatisticsReq *>(ps.snhRequest_.get());
70 0 : bsc = static_cast<BgpSandeshContext *>(req->client_context());
71 :
72 : // Retrieve number of BGP peers.
73 0 : size_t count = FillBgpNeighborStatistics(req, bsc->bgp_server);
74 :
75 : // Retrieve numner of XMPP agents.
76 0 : if (req->get_bgp_or_xmpp().empty() ||
77 0 : boost::iequals(req->get_bgp_or_xmpp(), "xmpp")) {
78 0 : bsc->ShowNeighborStatisticsExtension(&count, req);
79 : }
80 :
81 0 : ShowNeighborStatisticsResp *resp = new ShowNeighborStatisticsResp;
82 0 : resp->set_bgp_or_xmpp(req->get_bgp_or_xmpp());
83 0 : resp->set_up_or_down(req->get_up_or_down());
84 0 : resp->set_domain(req->get_domain());
85 0 : resp->set_count(count);
86 0 : resp->set_context(req->context());
87 0 : resp->Response();
88 :
89 0 : return true;
90 : }
91 :
92 0 : void ShowNeighborStatisticsReq::HandleRequest() const {
93 : // Use config task as we need to examine both bgp and xmpp data bases
94 : // to compute the number of neighbors. Both BGP and XMPP peers are
95 : // inserted/deleted under config task.
96 0 : RequestPipeline::StageSpec s1;
97 0 : s1.taskId_ = TaskScheduler::GetInstance()->GetTaskId("bgp::Config");
98 0 : s1.instances_.push_back(0);
99 0 : s1.cbFn_ = ShowNeighborStatisticsHandler::CallbackS1;
100 :
101 0 : RequestPipeline::PipeSpec ps(this);
102 0 : ps.stages_= list_of(s1)
103 0 : .convert_to_container<vector<RequestPipeline::StageSpec> >();
104 0 : RequestPipeline rp(ps);
105 0 : }
106 :
107 : class ClearBgpNeighborHandler {
108 : public:
109 : static bool CallbackS1(const Sandesh *sr,
110 : const RequestPipeline::PipeSpec ps, int stage,
111 : int instNum, RequestPipeline::InstData * data);
112 : };
113 :
114 0 : bool ClearBgpNeighborHandler::CallbackS1(
115 : const Sandesh *sr, const RequestPipeline::PipeSpec ps,
116 : int stage, int instNum, RequestPipeline::InstData *data) {
117 : const ClearBgpNeighborReq *req;
118 : BgpSandeshContext *bsc;
119 :
120 0 : req = static_cast<const ClearBgpNeighborReq *>(ps.snhRequest_.get());
121 0 : bsc = static_cast<BgpSandeshContext *>(req->client_context());
122 0 : BgpPeer *peer = bsc->bgp_server->FindPeer(req->get_name());
123 :
124 0 : ClearBgpNeighborResp *resp = new ClearBgpNeighborResp;
125 0 : if (!bsc->test_mode()) {
126 0 : resp->set_success(false);
127 0 : } else if (peer) {
128 0 : peer->Clear(BgpProto::Notification::AdminReset);
129 0 : resp->set_success(true);
130 : } else {
131 0 : resp->set_success(false);
132 : }
133 0 : resp->set_context(req->context());
134 0 : resp->Response();
135 :
136 0 : return true;
137 : }
138 :
139 : // handler for 'clear bgp neighbor'
140 0 : void ClearBgpNeighborReq::HandleRequest() const {
141 : // Use config task since neighbors are added/deleted under that task.
142 : // to compute the number of neighbors.
143 0 : RequestPipeline::StageSpec s1;
144 0 : s1.taskId_ = TaskScheduler::GetInstance()->GetTaskId("bgp::Config");
145 0 : s1.instances_.push_back(0);
146 0 : s1.cbFn_ = ClearBgpNeighborHandler::CallbackS1;
147 :
148 0 : RequestPipeline::PipeSpec ps(this);
149 0 : ps.stages_= list_of(s1)
150 0 : .convert_to_container<vector<RequestPipeline::StageSpec> >();
151 0 : RequestPipeline rp(ps);
152 0 : }
153 :
154 : class ShowMulticastManagerDetailHandler {
155 : public:
156 : struct MulticastManagerDetailData : public RequestPipeline::InstData {
157 : vector<ShowMulticastTree> tree_list;
158 : };
159 :
160 0 : static RequestPipeline::InstData *CreateData(int stage) {
161 0 : return (new MulticastManagerDetailData);
162 : }
163 :
164 0 : static void FillMulticastLinkInfo(const McastForwarder *forwarder,
165 : ShowMulticastTreeLink *smtl) {
166 0 : smtl->set_address(forwarder->address().to_string());
167 0 : smtl->set_label(forwarder->label());
168 0 : }
169 :
170 0 : static void FillMulticastForwarderInfo(const McastForwarder *forwarder,
171 : ShowMulticastForwarder *smf) {
172 0 : smf->set_address(forwarder->address().to_string());
173 0 : smf->set_label(forwarder->label());
174 0 : smf->set_label_block(forwarder->label_block()->ToString());
175 0 : smf->set_router_id(forwarder->router_id().to_string());
176 0 : for (McastForwarderList::const_iterator it =
177 0 : forwarder->tree_links_.begin();
178 0 : it != forwarder->tree_links_.end(); ++it) {
179 0 : ShowMulticastTreeLink smtl;
180 0 : FillMulticastLinkInfo(*it, &smtl);
181 0 : smf->links.push_back(smtl);
182 0 : }
183 0 : }
184 :
185 0 : static void FillMulticastTreeInfo(const McastSGEntry *sg,
186 : ShowMulticastTree *smt) {
187 0 : smt->set_group(sg->group().to_string());
188 0 : smt->set_source(sg->source().to_string());
189 0 : for (uint8_t level = McastTreeManager::LevelFirst;
190 0 : level < McastTreeManager::LevelCount; ++level) {
191 0 : if (!sg->IsTreeBuilder(level))
192 0 : continue;
193 0 : for (McastSGEntry::ForwarderSet::const_iterator it =
194 0 : sg->forwarder_sets_[level]->begin();
195 0 : it != sg->forwarder_sets_[level]->end(); ++it) {
196 0 : ShowMulticastForwarder smf;
197 0 : FillMulticastForwarderInfo(*it, &smf);
198 0 : if (level == McastTreeManager::LevelNative) {
199 0 : smt->level0_forwarders.push_back(smf);
200 : } else {
201 0 : smt->level1_forwarders.push_back(smf);
202 : }
203 0 : }
204 : }
205 0 : }
206 :
207 0 : static void FillMulticastPartitionInfo(MulticastManagerDetailData *data,
208 : ErmVpnTable *table, int inst_id) {
209 0 : McastTreeManager *tm = table->GetTreeManager();
210 0 : McastManagerPartition *partition = tm->GetPartition(inst_id);
211 0 : for (McastManagerPartition::SGList::const_iterator it =
212 0 : partition->sg_list_.begin();
213 0 : it != partition->sg_list_.end(); it++) {
214 0 : ShowMulticastTree smt;
215 0 : FillMulticastTreeInfo(*it, &smt);
216 0 : data->tree_list.push_back(smt);
217 0 : }
218 0 : }
219 :
220 0 : static bool CallbackS1(const Sandesh *sr,
221 : const RequestPipeline::PipeSpec ps,
222 : int stage, int instNum,
223 : RequestPipeline::InstData *data) {
224 0 : int inst_id = ps.stages_[stage].instances_[instNum];
225 :
226 0 : MulticastManagerDetailData *mydata =
227 : static_cast<MulticastManagerDetailData *>(data);
228 : const ShowMulticastManagerDetailReq *req =
229 : static_cast<const ShowMulticastManagerDetailReq *>(
230 0 : ps.snhRequest_.get());
231 : BgpSandeshContext *bsc =
232 0 : static_cast<BgpSandeshContext *>(req->client_context());
233 : DBTableBase *table =
234 0 : bsc->bgp_server->database()->FindTable(req->get_name());
235 0 : ErmVpnTable *mcast_table = dynamic_cast<ErmVpnTable *>(table);
236 0 : if (mcast_table && !mcast_table->IsVpnTable())
237 0 : FillMulticastPartitionInfo(mydata, mcast_table, inst_id);
238 :
239 0 : return true;
240 : }
241 :
242 0 : static void CombineMulticastPartitionInfo(
243 : const RequestPipeline::StageData *sd,
244 : vector<ShowMulticastTree> *tree_list) {
245 0 : for (size_t idx = 0; idx < sd->size(); idx++) {
246 : const MulticastManagerDetailData &data =
247 0 : static_cast<const MulticastManagerDetailData &>(sd->at(idx));
248 0 : tree_list->insert(tree_list->end(),
249 : data.tree_list.begin(), data.tree_list.end());
250 : }
251 0 : }
252 :
253 0 : static bool CallbackS2(const Sandesh *sr,
254 : const RequestPipeline::PipeSpec ps,
255 : int stage, int instNum,
256 : RequestPipeline::InstData *data) {
257 : const ShowMulticastManagerReq *req =
258 0 : static_cast<const ShowMulticastManagerReq *>(ps.snhRequest_.get());
259 0 : const RequestPipeline::StageData *sd = ps.GetStageData(0);
260 0 : vector<ShowMulticastTree> tree_list;
261 0 : CombineMulticastPartitionInfo(sd, &tree_list);
262 :
263 : ShowMulticastManagerDetailResp *resp =
264 0 : new ShowMulticastManagerDetailResp;
265 0 : resp->set_trees(tree_list);
266 0 : resp->set_context(req->context());
267 0 : resp->Response();
268 0 : return true;
269 0 : }
270 : };
271 :
272 :
273 0 : void ShowMulticastManagerDetailReq::HandleRequest() const {
274 0 : RequestPipeline::PipeSpec ps(this);
275 :
276 : // Request pipeline has 2 stages.
277 : // First stage to collect multicast manager stats.
278 : // Second stage to fill stats from stage 1 and respond to the request.
279 0 : RequestPipeline::StageSpec s1, s2;
280 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
281 :
282 0 : s1.taskId_ = scheduler->GetTaskId("db::DBTable");
283 0 : s1.allocFn_ = ShowMulticastManagerDetailHandler::CreateData;
284 0 : s1.cbFn_ = ShowMulticastManagerDetailHandler::CallbackS1;
285 0 : for (int i = 0; i < ErmVpnTable::kPartitionCount; i++) {
286 0 : s1.instances_.push_back(i);
287 : }
288 :
289 0 : s2.taskId_ = scheduler->GetTaskId("bgp::ShowCommand");
290 0 : s2.cbFn_ = ShowMulticastManagerDetailHandler::CallbackS2;
291 0 : s2.instances_.push_back(0);
292 :
293 0 : ps.stages_ = list_of(s1)(s2)
294 0 : .convert_to_container<vector<RequestPipeline::StageSpec> >();
295 0 : RequestPipeline rp(ps);
296 0 : }
297 :
298 : class ShowMvpnManagerDetailHandler {
299 : public:
300 : struct MvpnManagerDetailData : public RequestPipeline::InstData {
301 : vector<ShowMvpnNeighbor> neighbors;
302 : };
303 :
304 0 : static RequestPipeline::InstData *CreateData(int stage) {
305 0 : return (new MvpnManagerDetailData);
306 : }
307 :
308 0 : static void FillMvpnNeighborInfo(const MvpnNeighbor *nbr,
309 : ShowMvpnNeighbor *snbr) {
310 0 : snbr->set_rd(nbr->rd().ToString());
311 0 : snbr->set_originator(nbr->originator().to_string());
312 0 : snbr->set_source_as(nbr->source_as());
313 0 : }
314 :
315 0 : static void FillMvpnNeighborsInfo(MvpnManagerDetailData *data,
316 : MvpnTable *table, int inst_id) {
317 0 : MvpnManager *tm = table->manager();
318 0 : if (!tm)
319 0 : return;
320 0 : std::shared_lock<std::shared_mutex> lock(tm->neighbors_mutex());
321 :
322 0 : BOOST_FOREACH(const MvpnManager::NeighborMap::value_type &val,
323 : tm->neighbors()) {
324 0 : ShowMvpnNeighbor snbr;
325 0 : FillMvpnNeighborInfo(&val.second, &snbr);
326 0 : data->neighbors.push_back(snbr);
327 0 : }
328 0 : }
329 :
330 0 : static bool CallbackS1(const Sandesh *sr,
331 : const RequestPipeline::PipeSpec ps,
332 : int stage, int instNum,
333 : RequestPipeline::InstData *data) {
334 0 : int inst_id = ps.stages_[stage].instances_[instNum];
335 :
336 0 : MvpnManagerDetailData *mydata =
337 : static_cast<MvpnManagerDetailData *>(data);
338 : const ShowMvpnManagerDetailReq *req =
339 : static_cast<const ShowMvpnManagerDetailReq *>(
340 0 : ps.snhRequest_.get());
341 : BgpSandeshContext *bsc =
342 0 : static_cast<BgpSandeshContext *>(req->client_context());
343 : DBTableBase *table =
344 0 : bsc->bgp_server->database()->FindTable(req->get_name());
345 0 : MvpnTable *mvpn_table = dynamic_cast<MvpnTable *>(table);
346 0 : if (mvpn_table && !mvpn_table->IsVpnTable())
347 0 : FillMvpnNeighborsInfo(mydata, mvpn_table, inst_id);
348 :
349 0 : ShowMvpnManagerDetailResp *resp = new ShowMvpnManagerDetailResp;
350 0 : resp->set_neighbors(mydata->neighbors);
351 0 : resp->set_context(req->context());
352 0 : resp->Response();
353 :
354 0 : return true;
355 : }
356 : };
357 :
358 0 : void ShowMvpnManagerDetailReq::HandleRequest() const {
359 0 : RequestPipeline::PipeSpec ps(this);
360 0 : RequestPipeline::StageSpec s1, s2;
361 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
362 :
363 0 : s1.taskId_ = scheduler->GetTaskId("db::DBTable");
364 0 : s1.allocFn_ = ShowMvpnManagerDetailHandler::CreateData;
365 0 : s1.cbFn_ = ShowMvpnManagerDetailHandler::CallbackS1;
366 0 : s1.instances_.push_back(0);
367 0 : ps.stages_ = list_of(s1)
368 0 : .convert_to_container<vector<RequestPipeline::StageSpec> >();
369 :
370 0 : RequestPipeline rp(ps);
371 0 : }
372 :
373 : class ShowMvpnProjectManagerDetailHandler {
374 : public:
375 : struct MvpnProjectManagerDetailData : public RequestPipeline::InstData {
376 : vector<ShowMvpnState> states;
377 : };
378 :
379 0 : static RequestPipeline::InstData *CreateData(int stage) {
380 0 : return (new MvpnProjectManagerDetailData);
381 : }
382 :
383 0 : static void FillMvpnProjectStateInfo(const MvpnState *state,
384 : ShowMvpnState *st) {
385 0 : st->set_source(state->sg().source.to_string());
386 0 : st->set_group(state->sg().group.to_string());
387 0 : if (state->global_ermvpn_tree_rt()) {
388 0 : st->set_global_ermvpn_tree_rt(
389 0 : state->global_ermvpn_tree_rt()->ToString());
390 : }
391 0 : if (state->spmsi_rt())
392 0 : st->set_spmsi_rt(state->spmsi_rt()->ToString());
393 0 : if (state->source_active_rt())
394 0 : st->set_source_active_rt(state->source_active_rt()->ToString());
395 :
396 0 : vector<string> spmsi_routes_received;
397 0 : BOOST_FOREACH(MvpnRoute *rt, state->spmsi_routes_received()) {
398 0 : spmsi_routes_received.push_back(rt->ToString());
399 : }
400 0 : st->set_spmsi_routes_received(spmsi_routes_received);
401 :
402 0 : vector<string> leafad_routes_attr_received;
403 0 : BOOST_FOREACH(const MvpnState::RoutesMap::value_type &val,
404 : state->leafad_routes_attr_received()) {
405 0 : const PmsiTunnel *pmsi = val.second->pmsi_tunnel();
406 0 : if (pmsi) {
407 0 : leafad_routes_attr_received.push_back(
408 0 : pmsi->pmsi_tunnel().ToString());
409 : }
410 : }
411 0 : st->set_leafad_routes_attr_received(leafad_routes_attr_received);
412 0 : st->set_total_states(state->states()->size());
413 0 : st->set_project_manager(state->project_manager()->table()->name());
414 0 : st->set_refcount(state->refcount());
415 0 : }
416 :
417 0 : static void FillMvpnProjectPartitionInfo(MvpnProjectManagerDetailData *data,
418 : ErmVpnTable *table, int inst_id) {
419 0 : MvpnProjectManager *tm = table->mvpn_project_manager();
420 0 : if (!tm) return;
421 0 : MvpnProjectManagerPartition *partition = tm->GetPartition(inst_id);
422 0 : BOOST_FOREACH(MvpnState::StatesMap::value_type &val,
423 : partition->states()) {
424 0 : ShowMvpnState st;
425 0 : FillMvpnProjectStateInfo(val.second, &st);
426 0 : data->states.push_back(st);
427 0 : }
428 : }
429 :
430 0 : static bool CallbackS1(const Sandesh *sr,
431 : const RequestPipeline::PipeSpec ps,
432 : int stage, int instNum,
433 : RequestPipeline::InstData *data) {
434 0 : int inst_id = ps.stages_[stage].instances_[instNum];
435 :
436 0 : MvpnProjectManagerDetailData *mydata =
437 : static_cast<MvpnProjectManagerDetailData *>(data);
438 : const ShowMvpnProjectManagerDetailReq *req =
439 : static_cast<const ShowMvpnProjectManagerDetailReq *>(
440 0 : ps.snhRequest_.get());
441 : BgpSandeshContext *bsc =
442 0 : static_cast<BgpSandeshContext *>(req->client_context());
443 : DBTableBase *table =
444 0 : bsc->bgp_server->database()->FindTable(req->get_name());
445 0 : ErmVpnTable *ermvpn_table = dynamic_cast<ErmVpnTable *>(table);
446 0 : if (ermvpn_table && !ermvpn_table->IsVpnTable())
447 0 : FillMvpnProjectPartitionInfo(mydata, ermvpn_table, inst_id);
448 :
449 0 : return true;
450 : }
451 :
452 0 : static void CombineMvpnProjectPartitionInfo(
453 : const RequestPipeline::StageData *sd,
454 : vector<ShowMvpnState> *states) {
455 0 : for (size_t idx = 0; idx < sd->size(); idx++) {
456 : const MvpnProjectManagerDetailData &data =
457 0 : static_cast<const MvpnProjectManagerDetailData &>(sd->at(idx));
458 0 : states->insert(states->end(),
459 : data.states.begin(), data.states.end());
460 : }
461 0 : }
462 :
463 0 : static bool CallbackS2(const Sandesh *sr,
464 : const RequestPipeline::PipeSpec ps,
465 : int stage, int instNum,
466 : RequestPipeline::InstData *data) {
467 : const ShowMvpnProjectManagerReq *req =
468 : static_cast<const ShowMvpnProjectManagerReq *>(
469 0 : ps.snhRequest_.get());
470 0 : const RequestPipeline::StageData *sd = ps.GetStageData(0);
471 0 : vector<ShowMvpnState> states;
472 0 : CombineMvpnProjectPartitionInfo(sd, &states);
473 :
474 : ShowMvpnProjectManagerDetailResp *resp =
475 0 : new ShowMvpnProjectManagerDetailResp;
476 0 : resp->set_states(states);
477 0 : resp->set_context(req->context());
478 0 : resp->Response();
479 0 : return true;
480 0 : }
481 : };
482 :
483 :
484 0 : void ShowMvpnProjectManagerDetailReq::HandleRequest() const {
485 0 : RequestPipeline::PipeSpec ps(this);
486 :
487 : // Request pipeline has 2 stages.
488 : // First stage to collect multicast manager stats.
489 : // Second stage to fill stats from stage 1 and respond to the request.
490 0 : RequestPipeline::StageSpec s1, s2;
491 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
492 :
493 0 : s1.taskId_ = scheduler->GetTaskId("db::DBTable");
494 0 : s1.allocFn_ = ShowMvpnProjectManagerDetailHandler::CreateData;
495 0 : s1.cbFn_ = ShowMvpnProjectManagerDetailHandler::CallbackS1;
496 0 : for (int i = 0; i < ErmVpnTable::kPartitionCount; i++) {
497 0 : s1.instances_.push_back(i);
498 : }
499 :
500 0 : s2.taskId_ = scheduler->GetTaskId("bgp::ShowCommand");
501 0 : s2.cbFn_ = ShowMvpnProjectManagerDetailHandler::CallbackS2;
502 0 : s2.instances_.push_back(0);
503 :
504 0 : ps.stages_ = list_of(s1)(s2)
505 0 : .convert_to_container<vector<RequestPipeline::StageSpec> >();
506 0 : RequestPipeline rp(ps);
507 0 : }
508 :
509 : class ShowRouteVrfHandler {
510 : public:
511 : struct SearchRouteInVrfData : public RequestPipeline::InstData {
512 : vector<ShowRoute> routes;
513 : };
514 :
515 0 : static RequestPipeline::InstData *CreateData(int stage) {
516 0 : return (new SearchRouteInVrfData);
517 : }
518 :
519 0 : static bool CallbackS1(const Sandesh *sr,
520 : const RequestPipeline::PipeSpec ps,
521 : int stage, int instNum,
522 : RequestPipeline::InstData *data) {
523 0 : SearchRouteInVrfData *sdata = static_cast<SearchRouteInVrfData *>(data);
524 : const ShowRouteVrfReq *req =
525 0 : static_cast<const ShowRouteVrfReq *>(ps.snhRequest_.get());
526 : BgpSandeshContext *bsc =
527 0 : static_cast<BgpSandeshContext *>(req->client_context());
528 0 : RoutingInstanceMgr *rim = bsc->bgp_server->routing_instance_mgr();
529 0 : RoutingInstance *ri = rim->GetRoutingInstance(req->get_vrf());
530 0 : if (!ri) return true;
531 0 : BgpTable *table = ri->GetTable(Address::INET);
532 0 : if (!table) return true;
533 0 : Ip4Prefix prefix(Ip4Prefix::FromString(req->get_prefix()));
534 0 : InetTable::RequestKey key(prefix, NULL);
535 :
536 : // Find route from the calling task instance specific db partition.
537 0 : InetRoute *route = static_cast<InetRoute *>(table->Find(&key, instNum));
538 0 : if (!route) return true;
539 0 : ShowRoute show_route;
540 0 : show_route.set_prefix(route->ToString());
541 0 : show_route.set_last_modified(duration_usecs_to_string(
542 0 : UTCTimestampUsec() - route->last_change_at()));
543 0 : vector<ShowRoutePath> show_route_paths;
544 0 : for (Route::PathList::const_iterator it = route->GetPathList().begin();
545 0 : it != route->GetPathList().end(); it++) {
546 0 : const BgpPath *path = static_cast<const BgpPath *>(it.operator->());
547 0 : ShowRoutePath srp;
548 0 : srp.set_protocol("BGP");
549 0 : const BgpAttr *attr = path->GetAttr();
550 0 : if (attr->as_path() != NULL)
551 0 : srp.set_as_path(attr->as_path()->path().ToString());
552 0 : srp.set_local_preference(attr->local_pref());
553 0 : if (path->GetPeer()) srp.set_source(path->GetPeer()->ToString());
554 0 : srp.set_last_modified(duration_usecs_to_string(
555 0 : UTCTimestampUsec() - path->time_stamp_usecs()));
556 0 : srp.set_next_hop(attr->nexthop().to_string());
557 0 : srp.set_label(path->GetLabel());
558 0 : show_route_paths.push_back(srp);
559 0 : }
560 0 : show_route.set_paths(show_route_paths);
561 0 : sdata->routes.push_back(show_route);
562 0 : return true;
563 0 : }
564 :
565 0 : static bool CallbackS2(const Sandesh *sr,
566 : const RequestPipeline::PipeSpec ps,
567 : int stage, int instNum,
568 : RequestPipeline::InstData *data) {
569 0 : const RequestPipeline::StageData *sd = ps.GetStageData(0);
570 0 : ShowRoute route;
571 0 : for (size_t i = 0; i < sd->size(); i++) {
572 : const SearchRouteInVrfData &data =
573 0 : static_cast<const SearchRouteInVrfData &>(sd->at(i));
574 0 : if (data.routes.size()) {
575 0 : route = data.routes.front();
576 0 : break;
577 : }
578 : }
579 :
580 0 : ShowRouteVrfResp *resp = new ShowRouteVrfResp;
581 0 : resp->set_route(route);
582 : const ShowRouteVrfReq *req =
583 0 : static_cast<const ShowRouteVrfReq *>(ps.snhRequest_.get());
584 0 : resp->set_context(req->context());
585 0 : resp->Response();
586 0 : return true;
587 0 : }
588 : };
589 :
590 0 : void ShowRouteVrfReq::HandleRequest() const {
591 0 : RequestPipeline::PipeSpec ps(this);
592 0 : BgpSandeshContext *bsc = static_cast<BgpSandeshContext *>(client_context());
593 :
594 : // Request pipeline has 2 stages.
595 : // First stage to search in different partition
596 : // Second stage to fill stats from stage 1 and respond to the request.
597 0 : RequestPipeline::StageSpec s1, s2;
598 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
599 :
600 0 : s1.taskId_ = scheduler->GetTaskId("db::DBTable");
601 0 : s1.allocFn_ = ShowRouteVrfHandler::CreateData;
602 0 : s1.cbFn_ = ShowRouteVrfHandler::CallbackS1;
603 0 : for (int i = 0; i < bsc->bgp_server->database()->PartitionCount(); i++) {
604 0 : s1.instances_.push_back(i);
605 : }
606 :
607 0 : s2.taskId_ = scheduler->GetTaskId("bgp::ShowCommand");
608 0 : s2.cbFn_ = ShowRouteVrfHandler::CallbackS2;
609 0 : s2.instances_.push_back(0);
610 :
611 0 : ps.stages_ = list_of(s1)(s2)
612 0 : .convert_to_container<vector<RequestPipeline::StageSpec> >();
613 0 : RequestPipeline rp(ps);
614 0 : }
615 :
616 : class ShowBgpServerHandler {
617 : public:
618 0 : static bool CallbackS1(const Sandesh *sr,
619 : const RequestPipeline::PipeSpec ps, int stage, int instNum,
620 : RequestPipeline::InstData *data) {
621 : const ShowBgpServerReq *req =
622 0 : static_cast<const ShowBgpServerReq *>(ps.snhRequest_.get());
623 : BgpSandeshContext *bsc =
624 0 : static_cast<BgpSandeshContext *>(req->client_context());
625 :
626 0 : ShowBgpServerResp *resp = new ShowBgpServerResp;
627 0 : SocketIOStats peer_socket_stats;
628 0 : bsc->bgp_server->session_manager()->GetRxSocketStats(&peer_socket_stats);
629 0 : resp->set_rx_socket_stats(peer_socket_stats);
630 :
631 0 : bsc->bgp_server->session_manager()->GetTxSocketStats(&peer_socket_stats);
632 0 : resp->set_tx_socket_stats(peer_socket_stats);
633 :
634 0 : resp->set_context(req->context());
635 0 : resp->Response();
636 0 : return true;
637 0 : }
638 : };
639 :
640 0 : void ShowBgpServerReq::HandleRequest() const {
641 0 : RequestPipeline::PipeSpec ps(this);
642 :
643 : // Request pipeline has single stage to collect neighbor config info
644 : // and respond to the request
645 0 : RequestPipeline::StageSpec s1;
646 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
647 0 : s1.taskId_ = scheduler->GetTaskId("bgp::ShowCommand");
648 0 : s1.cbFn_ = ShowBgpServerHandler::CallbackS1;
649 0 : s1.instances_.push_back(0);
650 0 : ps.stages_ = list_of(s1)
651 0 : .convert_to_container<vector<RequestPipeline::StageSpec> >();
652 0 : RequestPipeline rp(ps);
653 0 : }
654 :
655 0 : BgpSandeshContext::BgpSandeshContext()
656 0 : : bgp_server(NULL),
657 0 : xmpp_peer_manager(NULL),
658 0 : test_mode_(false),
659 0 : page_limit_(0),
660 0 : iter_limit_(0) {
661 0 : }
662 :
663 0 : void BgpSandeshContext::SetNeighborShowExtensions(
664 : const NeighborListExtension &show_neighbor,
665 : const NeighborStatisticsExtension &show_neighbor_statistics) {
666 0 : show_neighbor_ext_ = show_neighbor;
667 0 : show_neighbor_statistics_ext_ = show_neighbor_statistics;
668 0 : }
669 :
670 0 : bool BgpSandeshContext::ShowNeighborExtension(const BgpSandeshContext *bsc,
671 : bool summary, uint32_t page_limit, uint32_t iter_limit,
672 : const string &start_neighbor, const string &search_string,
673 : vector<BgpNeighborResp> *list, string *next_neighbor) const {
674 0 : if (!show_neighbor_ext_)
675 0 : return true;
676 0 : bool done = show_neighbor_ext_(bsc, summary, page_limit, iter_limit,
677 : start_neighbor, search_string, list, next_neighbor);
678 0 : return done;
679 : }
680 :
681 0 : void BgpSandeshContext::ShowNeighborStatisticsExtension(
682 : size_t *count, const ShowNeighborStatisticsReq *req) const {
683 0 : if (!show_neighbor_statistics_ext_)
684 0 : return;
685 0 : show_neighbor_statistics_ext_(count, this, req);
686 : }
687 :
688 0 : void BgpSandeshContext::SetPeeringShowHandlers(
689 : const PeeringReqHandler &show_peering_req_handler,
690 : const PeeringReqIterateHandler &show_peering_req_iterate_handler) {
691 0 : show_peering_req_handler_ = show_peering_req_handler;
692 0 : show_peering_req_iterate_handler_ = show_peering_req_iterate_handler;
693 0 : }
694 :
695 0 : void BgpSandeshContext::PeeringShowReqHandler(
696 : const ShowBgpPeeringConfigReq *req) {
697 0 : if (show_peering_req_handler_) {
698 0 : show_peering_req_handler_(this, req);
699 : } else {
700 0 : ShowBgpPeeringConfigResp *resp = new ShowBgpPeeringConfigResp;
701 0 : resp->Response();
702 : }
703 0 : }
704 :
705 0 : void BgpSandeshContext::PeeringShowReqIterateHandler(
706 : const ShowBgpPeeringConfigReqIterate *req_iterate) {
707 0 : if (show_peering_req_iterate_handler_) {
708 0 : show_peering_req_iterate_handler_(this, req_iterate);
709 : } else {
710 0 : ShowBgpPeeringConfigResp *resp = new ShowBgpPeeringConfigResp;
711 0 : resp->Response();
712 : }
713 0 : }
|