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