Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include "bgp/bgp_show_handler.h"
6 :
7 : #include <boost/foreach.hpp>
8 :
9 : #include "base/regex.h"
10 : #include "bgp/bgp_membership.h"
11 : #include "bgp/bgp_peer.h"
12 : #include "bgp/bgp_peer_internal_types.h"
13 : #include "bgp/bgp_server.h"
14 : #include "bgp/bgp_table.h"
15 : #include "bgp/routing-instance/peer_manager.h"
16 : #include "bgp/routing-instance/routing_instance.h"
17 : #include "bgp/routing-policy/routing_policy.h"
18 :
19 : using contrail::regex;
20 : using contrail::regex_match;
21 : using contrail::regex_search;
22 : using std::string;
23 : using std::vector;
24 :
25 : //
26 : // Fill in information for a table.
27 : //
28 1093 : static void FillRoutingInstanceTableInfo(ShowRoutingInstanceTable *srit,
29 : const BgpSandeshContext *bsc, const BgpTable *table) {
30 1093 : srit->set_name(table->name());
31 1093 : srit->set_deleted(table->IsDeleted());
32 1093 : srit->set_walk_requests(table->walk_request_count());
33 1093 : srit->set_walk_completes(table->walk_complete_count());
34 1093 : srit->set_walk_cancels(table->walk_cancel_count());
35 1093 : size_t markers = 0;
36 1093 : srit->set_pending_updates(table->GetPendingRiboutsCount(&markers));
37 1093 : srit->set_markers(markers);
38 1093 : srit->set_listeners(table->GetListenerCount());
39 1093 : srit->set_walkers(table->walker_count());
40 1093 : srit->set_prefixes(table->Size());
41 1093 : srit->set_primary_paths(table->GetPrimaryPathCount());
42 1093 : srit->set_secondary_paths(table->GetSecondaryPathCount());
43 1093 : srit->set_infeasible_paths(table->GetInfeasiblePathCount());
44 1093 : srit->set_stale_paths(table->GetStalePathCount());
45 1093 : srit->set_llgr_stale_paths(table->GetLlgrStalePathCount());
46 1093 : srit->set_paths(srit->get_primary_paths() + srit->get_secondary_paths());
47 1093 : }
48 :
49 : //
50 : // Fill in information for an instance.
51 : //
52 423 : static void FillRoutingInstanceInfo(ShowRoutingInstance *sri,
53 : const BgpSandeshContext *bsc, const RoutingInstance *rtinstance,
54 : bool summary) {
55 423 : sri->set_name(rtinstance->name());
56 423 : sri->set_virtual_network(rtinstance->GetVirtualNetworkName());
57 423 : sri->set_vn_index(rtinstance->virtual_network_index());
58 423 : sri->set_vxlan_id(rtinstance->vxlan_id());
59 423 : sri->set_deleted(rtinstance->deleted());
60 423 : sri->set_deleted_at(
61 846 : UTCUsecToString(rtinstance->deleter()->delete_time_stamp_usecs()));
62 423 : vector<string> import_rt;
63 1572 : for (auto rt : rtinstance->GetImportList()) {
64 1149 : import_rt.push_back(rt.ToString());
65 : }
66 423 : sri->set_import_target(import_rt);
67 423 : vector<string> export_rt;
68 806 : for (auto rt : rtinstance->GetExportList()) {
69 383 : export_rt.push_back(rt.ToString());
70 : }
71 423 : sri->set_export_target(export_rt);
72 423 : sri->set_always_subscribe(rtinstance->always_subscribe());
73 423 : sri->set_allow_transit(rtinstance->virtual_network_allow_transit());
74 423 : sri->set_pbb_evpn_enable(rtinstance->virtual_network_pbb_evpn_enable());
75 :
76 423 : if (summary)
77 210 : return;
78 :
79 213 : const BgpMembershipManager *bmm = bsc->bgp_server->membership_mgr();
80 213 : vector<ShowRoutingInstanceTable> srit_list;
81 213 : const RoutingInstance::RouteTableList &tables = rtinstance->GetTables();
82 213 : for (RoutingInstance::RouteTableList::const_iterator it =
83 1519 : tables.begin(); it != tables.end(); ++it) {
84 1093 : ShowRoutingInstanceTable srit;
85 1093 : FillRoutingInstanceTableInfo(&srit, bsc, it->second);
86 1093 : bmm->FillRoutingInstanceTableInfo(&srit, it->second);
87 1093 : srit_list.push_back(srit);
88 1093 : }
89 213 : sri->set_tables(srit_list);
90 :
91 213 : vector<ShowInstanceRoutingPolicyInfo> policy_list;
92 217 : for (auto info : rtinstance->routing_policies()) {
93 4 : ShowInstanceRoutingPolicyInfo show_policy_info;
94 4 : RoutingPolicyPtr policy = info.first;
95 4 : show_policy_info.set_policy_name(policy->name());
96 4 : show_policy_info.set_generation(info.second);
97 4 : policy_list.push_back(show_policy_info);
98 4 : }
99 213 : sri->set_routing_policies(policy_list);
100 :
101 213 : const PeerManager *peer_manager = rtinstance->peer_manager();
102 213 : if (peer_manager) {
103 7 : vector<string> neighbors;
104 7 : for (const BgpPeer *peer = peer_manager->NextPeer(BgpPeerKey());
105 7 : peer != NULL; peer = peer_manager->NextPeer(peer->peer_key())) {
106 0 : neighbors.push_back(peer->peer_name());
107 : }
108 7 : sri->set_neighbors(neighbors);
109 7 : }
110 633 : }
111 :
112 : //
113 : // Fill in information for list of instances.
114 : //
115 : // Allows regular and summary introspect to share code.
116 : //
117 85 : static bool FillRoutingInstanceInfoList(const BgpSandeshContext *bsc,
118 : bool summary, uint32_t page_limit, uint32_t iter_limit,
119 : const string &start_instance, const string &search_string,
120 : vector<ShowRoutingInstance> *sri_list, string *next_instance) {
121 85 : regex search_expr(search_string);
122 85 : RoutingInstanceMgr *rim = bsc->bgp_server->routing_instance_mgr();
123 : RoutingInstanceMgr::const_name_iterator it =
124 85 : rim->name_clower_bound(start_instance);
125 621 : for (uint32_t iter_count = 0; it != rim->name_cend(); ++it, ++iter_count) {
126 586 : const RoutingInstance *rtinstance = it->second;
127 586 : if (!search_string.empty() &&
128 833 : (!regex_search(rtinstance->name(), search_expr)) &&
129 247 : (search_string != "deleted" || !rtinstance->deleted())) {
130 163 : continue;
131 : }
132 423 : ShowRoutingInstance sri;
133 423 : FillRoutingInstanceInfo(&sri, bsc, rtinstance, summary);
134 423 : sri_list->push_back(sri);
135 423 : if (sri_list->size() >= page_limit)
136 26 : break;
137 397 : if (iter_count >= iter_limit)
138 24 : break;
139 423 : }
140 :
141 : // All done if we've looked at all instances.
142 85 : if (it == rim->name_cend() || ++it == rim->name_end())
143 41 : return true;
144 :
145 : // Return true if we've reached the page limit, false if we've reached the
146 : // iteration limit.
147 44 : bool done = sri_list->size() >= page_limit;
148 44 : *next_instance = it->second->name();
149 44 : return done;
150 85 : }
151 :
152 : //
153 : // Specialization of BgpShowHandler<>::CallbackCommon for regular introspect.
154 : //
155 : template <>
156 44 : bool BgpShowHandler<ShowRoutingInstanceReq, ShowRoutingInstanceReqIterate,
157 : ShowRoutingInstanceResp, ShowRoutingInstance>::CallbackCommon(
158 : const BgpSandeshContext *bsc, Data *data) {
159 44 : uint32_t page_limit = bsc->page_limit() ? bsc->page_limit() : kPageLimit;
160 44 : uint32_t iter_limit = bsc->iter_limit() ? bsc->iter_limit() : kIterLimit;
161 44 : string next_instance;
162 88 : bool done = FillRoutingInstanceInfoList(bsc, false, page_limit, iter_limit,
163 44 : data->next_entry, data->search_string, &data->show_list,
164 : &next_instance);
165 44 : if (!next_instance.empty())
166 22 : SaveContextToData(next_instance, done, data);
167 44 : return done;
168 44 : }
169 :
170 : //
171 : // Specialization of BgpShowHandler<>::FillShowList for regular introspect.
172 : //
173 : template <>
174 27 : void BgpShowHandler<ShowRoutingInstanceReq, ShowRoutingInstanceReqIterate,
175 : ShowRoutingInstanceResp, ShowRoutingInstance>::FillShowList(
176 : ShowRoutingInstanceResp *resp,
177 : const vector<ShowRoutingInstance> &show_list) {
178 27 : resp->set_instances(show_list);
179 27 : }
180 :
181 : //
182 : // Specialization of BgpShowHandler<>::CallbackCommon for summary introspect.
183 : //
184 : template <>
185 41 : bool BgpShowHandler<ShowRoutingInstanceSummaryReq,
186 : ShowRoutingInstanceSummaryReqIterate,
187 : ShowRoutingInstanceSummaryResp, ShowRoutingInstance>::CallbackCommon(
188 : const BgpSandeshContext *bsc, Data *data) {
189 41 : uint32_t page_limit = bsc->page_limit() ? bsc->page_limit() : kPageLimit;
190 41 : uint32_t iter_limit = bsc->iter_limit() ? bsc->iter_limit() : kIterLimit;
191 41 : string next_instance;
192 82 : bool done = FillRoutingInstanceInfoList(bsc, true, page_limit, iter_limit,
193 41 : data->next_entry, data->search_string, &data->show_list,
194 : &next_instance);
195 41 : if (!next_instance.empty())
196 22 : SaveContextToData(next_instance, done, data);
197 41 : return done;
198 41 : }
199 :
200 : //
201 : // Specialization of BgpShowHandler<>::FillShowList for summary introspect.
202 : //
203 : template <>
204 24 : void BgpShowHandler<ShowRoutingInstanceSummaryReq,
205 : ShowRoutingInstanceSummaryReqIterate,
206 : ShowRoutingInstanceSummaryResp, ShowRoutingInstance>::FillShowList(
207 : ShowRoutingInstanceSummaryResp *resp,
208 : const vector<ShowRoutingInstance> &show_list) {
209 24 : resp->set_instances(show_list);
210 24 : }
211 :
212 : //
213 : // Handler for ShowRoutingInstanceReq.
214 : //
215 19 : void ShowRoutingInstanceReq::HandleRequest() const {
216 19 : RequestPipeline::PipeSpec ps(this);
217 19 : RequestPipeline::StageSpec s1;
218 19 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
219 :
220 19 : s1.taskId_ = scheduler->GetTaskId("bgp::ShowCommand");
221 : s1.cbFn_ = boost::bind(&BgpShowHandler<
222 : ShowRoutingInstanceReq,
223 : ShowRoutingInstanceReqIterate,
224 : ShowRoutingInstanceResp,
225 19 : ShowRoutingInstance>::Callback, _1, _2, _3, _4, _5);
226 : s1.allocFn_ = BgpShowHandler<
227 : ShowRoutingInstanceReq,
228 : ShowRoutingInstanceReqIterate,
229 : ShowRoutingInstanceResp,
230 19 : ShowRoutingInstance>::CreateData;
231 19 : s1.instances_.push_back(0);
232 19 : ps.stages_.push_back(s1);
233 19 : RequestPipeline rp(ps);
234 19 : }
235 :
236 : //
237 : // Handler for ShowRoutingInstanceReqIterate.
238 : //
239 16 : void ShowRoutingInstanceReqIterate::HandleRequest() const {
240 16 : RequestPipeline::PipeSpec ps(this);
241 16 : RequestPipeline::StageSpec s1;
242 16 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
243 :
244 16 : s1.taskId_ = scheduler->GetTaskId("bgp::ShowCommand");
245 : s1.cbFn_ = boost::bind(&BgpShowHandler<
246 : ShowRoutingInstanceReq,
247 : ShowRoutingInstanceReqIterate,
248 : ShowRoutingInstanceResp,
249 16 : ShowRoutingInstance>::CallbackIterate, _1, _2, _3, _4, _5);
250 : s1.allocFn_ = BgpShowHandler<
251 : ShowRoutingInstanceReq,
252 : ShowRoutingInstanceReqIterate,
253 : ShowRoutingInstanceResp,
254 16 : ShowRoutingInstance>::CreateData;
255 16 : s1.instances_.push_back(0);
256 16 : ps.stages_.push_back(s1);
257 16 : RequestPipeline rp(ps);
258 16 : }
259 :
260 : //
261 : // Handler for ShowRoutingInstanceSummaryReq.
262 : //
263 16 : void ShowRoutingInstanceSummaryReq::HandleRequest() const {
264 16 : RequestPipeline::PipeSpec ps(this);
265 16 : RequestPipeline::StageSpec s1;
266 16 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
267 :
268 16 : s1.taskId_ = scheduler->GetTaskId("bgp::ShowCommand");
269 : s1.cbFn_ = boost::bind(&BgpShowHandler<
270 : ShowRoutingInstanceSummaryReq,
271 : ShowRoutingInstanceSummaryReqIterate,
272 : ShowRoutingInstanceSummaryResp,
273 16 : ShowRoutingInstance>::Callback, _1, _2, _3, _4, _5);
274 : s1.allocFn_ = BgpShowHandler<
275 : ShowRoutingInstanceSummaryReq,
276 : ShowRoutingInstanceSummaryReqIterate,
277 : ShowRoutingInstanceSummaryResp,
278 16 : ShowRoutingInstance>::CreateData;
279 16 : s1.instances_.push_back(0);
280 16 : ps.stages_.push_back(s1);
281 16 : RequestPipeline rp(ps);
282 16 : }
283 :
284 : //
285 : // Handler for ShowRoutingInstanceSummaryReqIterate.
286 : //
287 16 : void ShowRoutingInstanceSummaryReqIterate::HandleRequest() const {
288 16 : RequestPipeline::PipeSpec ps(this);
289 16 : RequestPipeline::StageSpec s1;
290 16 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
291 :
292 16 : s1.taskId_ = scheduler->GetTaskId("bgp::ShowCommand");
293 : s1.cbFn_ = boost::bind(&BgpShowHandler<
294 : ShowRoutingInstanceSummaryReq,
295 : ShowRoutingInstanceSummaryReqIterate,
296 : ShowRoutingInstanceSummaryResp,
297 16 : ShowRoutingInstance>::CallbackIterate, _1, _2, _3, _4, _5);
298 : s1.allocFn_ = BgpShowHandler<
299 : ShowRoutingInstanceSummaryReq,
300 : ShowRoutingInstanceSummaryReqIterate,
301 : ShowRoutingInstanceSummaryResp,
302 16 : ShowRoutingInstance>::CreateData;
303 16 : s1.instances_.push_back(0);
304 16 : ps.stages_.push_back(s1);
305 16 : RequestPipeline rp(ps);
306 16 : }
|