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