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