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 "base/regex.h"
9 : #include "bgp/bgp_evpn.h"
10 : #include "bgp/bgp_peer_internal_types.h"
11 : #include "bgp/bgp_server.h"
12 : #include "bgp/evpn/evpn_table.h"
13 : #include "bgp/routing-instance/routing_instance.h"
14 :
15 : using contrail::regex;
16 : using contrail::regex_match;
17 : using contrail::regex_search;
18 : using std::string;
19 : using std::vector;
20 :
21 : //
22 : // Used by EvpnManager::FillShowInfo for sorting.
23 : // Note that the declaration is auto-generated by sandesh compiler.
24 : //
25 0 : bool ShowEvpnMcastLeaf::operator<(const ShowEvpnMcastLeaf &rhs) const {
26 0 : return get_address() < rhs.get_address();
27 : }
28 :
29 : //
30 : // Fill in information for an evpn table.
31 : //
32 420 : static void FillEvpnTableInfo(ShowEvpnTable *sevt,
33 : const BgpSandeshContext *bsc, const EvpnTable *table, bool summary) {
34 420 : sevt->set_name(table->name());
35 420 : sevt->set_deleted(table->IsDeleted());
36 420 : sevt->set_deleted_at(
37 840 : UTCUsecToString(table->deleter()->delete_time_stamp_usecs()));
38 420 : sevt->set_mac_routes(table->mac_route_count());
39 420 : sevt->set_unique_mac_routes(table->unique_mac_route_count());
40 420 : sevt->set_im_routes(table->im_route_count());
41 420 : sevt->set_ip_routes(table->ip_route_count());
42 :
43 420 : if (summary || table->IsVpnTable() || !table->GetEvpnManager())
44 230 : return;
45 190 : table->GetEvpnManager()->FillShowInfo(sevt);
46 : }
47 :
48 : //
49 : // Fill in information for list of evpn tables.
50 : //
51 : // Allows regular and summary introspect to share code.
52 : //
53 82 : static bool FillEvpnTableInfoList(const BgpSandeshContext *bsc,
54 : bool summary, uint32_t page_limit, uint32_t iter_limit,
55 : const string &start_instance, const string &search_string,
56 : vector<ShowEvpnTable> *sevt_list, string *next_instance) {
57 82 : regex search_expr(search_string);
58 82 : RoutingInstanceMgr *rim = bsc->bgp_server->routing_instance_mgr();
59 : RoutingInstanceMgr::const_name_iterator it =
60 82 : rim->name_clower_bound(start_instance);
61 612 : for (uint32_t iter_count = 0; it != rim->name_cend(); ++it, ++iter_count) {
62 580 : const RoutingInstance *rtinstance = it->second;
63 : const EvpnTable *table =
64 580 : static_cast<const EvpnTable *>(rtinstance->GetTable(Address::EVPN));
65 580 : if (!table)
66 160 : continue;
67 824 : if ((!regex_search(table->name(), search_expr)) &&
68 244 : (search_string != "deleted" || !table->IsDeleted())) {
69 160 : continue;
70 : }
71 420 : ShowEvpnTable sevt;
72 420 : FillEvpnTableInfo(&sevt, bsc, table, summary);
73 420 : sevt_list->push_back(sevt);
74 420 : if (sevt_list->size() >= page_limit)
75 26 : break;
76 394 : if (iter_count >= iter_limit)
77 24 : break;
78 420 : }
79 :
80 : // All done if we've looked at all instances.
81 82 : if (it == rim->name_cend() || ++it == rim->name_end())
82 38 : return true;
83 :
84 : // Return true if we've reached the page limit, false if we've reached the
85 : // iteration limit.
86 44 : bool done = sevt_list->size() >= page_limit;
87 44 : *next_instance = it->second->name();
88 44 : return done;
89 82 : }
90 :
91 : //
92 : // Specialization of BgpShowHandler<>::CallbackCommon for regular introspect.
93 : //
94 : template <>
95 41 : bool BgpShowHandler<ShowEvpnTableReq, ShowEvpnTableReqIterate,
96 : ShowEvpnTableResp, ShowEvpnTable>::CallbackCommon(
97 : const BgpSandeshContext *bsc, Data *data) {
98 41 : uint32_t page_limit = bsc->page_limit() ? bsc->page_limit() : kPageLimit;
99 41 : uint32_t iter_limit = bsc->iter_limit() ? bsc->iter_limit() : kIterLimit;
100 41 : string next_instance;
101 82 : bool done = FillEvpnTableInfoList(bsc, false, page_limit, iter_limit,
102 41 : data->next_entry, data->search_string, &data->show_list,
103 : &next_instance);
104 41 : if (!next_instance.empty())
105 22 : SaveContextToData(next_instance, done, data);
106 41 : return done;
107 41 : }
108 :
109 : //
110 : // Specialization of BgpShowHandler<>::FillShowList for regular introspect.
111 : //
112 : template <>
113 24 : void BgpShowHandler<ShowEvpnTableReq, ShowEvpnTableReqIterate,
114 : ShowEvpnTableResp, ShowEvpnTable>::FillShowList(
115 : ShowEvpnTableResp *resp, const vector<ShowEvpnTable> &show_list) {
116 24 : resp->set_tables(show_list);
117 24 : }
118 :
119 : //
120 : // Specialization of BgpShowHandler<>::CallbackCommon for summary introspect.
121 : //
122 : template <>
123 41 : bool BgpShowHandler<ShowEvpnTableSummaryReq, ShowEvpnTableSummaryReqIterate,
124 : ShowEvpnTableSummaryResp, ShowEvpnTable>::CallbackCommon(
125 : const BgpSandeshContext *bsc, Data *data) {
126 41 : uint32_t page_limit = bsc->page_limit() ? bsc->page_limit() : kPageLimit;
127 41 : uint32_t iter_limit = bsc->iter_limit() ? bsc->iter_limit() : kIterLimit;
128 41 : string next_instance;
129 82 : bool done = FillEvpnTableInfoList(bsc, true, page_limit, iter_limit,
130 41 : data->next_entry, data->search_string, &data->show_list,
131 : &next_instance);
132 41 : if (!next_instance.empty())
133 22 : SaveContextToData(next_instance, done, data);
134 41 : return done;
135 41 : }
136 :
137 : //
138 : // Specialization of BgpShowHandler<>::FillShowList for summary introspect.
139 : //
140 : template <>
141 24 : void BgpShowHandler<ShowEvpnTableSummaryReq, ShowEvpnTableSummaryReqIterate,
142 : ShowEvpnTableSummaryResp, ShowEvpnTable>::FillShowList(
143 : ShowEvpnTableSummaryResp *resp, const vector<ShowEvpnTable> &show_list) {
144 24 : resp->set_tables(show_list);
145 24 : }
146 :
147 : //
148 : // Handler for ShowEvpnTableReq.
149 : // Schedules the callback to run in Task ("db::DBTable", 0) so that multicast
150 : // data structures in EvpnManager can be accessed safely.
151 : //
152 16 : void ShowEvpnTableReq::HandleRequest() const {
153 16 : RequestPipeline::PipeSpec ps(this);
154 16 : RequestPipeline::StageSpec s1;
155 16 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
156 :
157 16 : s1.taskId_ = scheduler->GetTaskId("db::DBTable");
158 : s1.cbFn_ = boost::bind(&BgpShowHandler<
159 : ShowEvpnTableReq,
160 : ShowEvpnTableReqIterate,
161 : ShowEvpnTableResp,
162 16 : ShowEvpnTable>::Callback, _1, _2, _3, _4, _5);
163 : s1.allocFn_ = BgpShowHandler<
164 : ShowEvpnTableReq,
165 : ShowEvpnTableReqIterate,
166 : ShowEvpnTableResp,
167 16 : ShowEvpnTable>::CreateData;
168 16 : s1.instances_.push_back(0);
169 16 : ps.stages_.push_back(s1);
170 16 : RequestPipeline rp(ps);
171 16 : }
172 :
173 : //
174 : // Handler for ShowEvpnTableReqIterate.
175 : // Schedules the callback to run in Task ("db::DBTable", 0) so that multicast
176 : // data structures in EvpnManager can be accessed safely.
177 : //
178 16 : void ShowEvpnTableReqIterate::HandleRequest() const {
179 16 : RequestPipeline::PipeSpec ps(this);
180 16 : RequestPipeline::StageSpec s1;
181 16 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
182 :
183 16 : s1.taskId_ = scheduler->GetTaskId("db::DBTable");
184 : s1.cbFn_ = boost::bind(&BgpShowHandler<
185 : ShowEvpnTableReq,
186 : ShowEvpnTableReqIterate,
187 : ShowEvpnTableResp,
188 16 : ShowEvpnTable>::CallbackIterate, _1, _2, _3, _4, _5);
189 : s1.allocFn_ = BgpShowHandler<
190 : ShowEvpnTableReq,
191 : ShowEvpnTableReqIterate,
192 : ShowEvpnTableResp,
193 16 : ShowEvpnTable>::CreateData;
194 16 : s1.instances_.push_back(0);
195 16 : ps.stages_.push_back(s1);
196 16 : RequestPipeline rp(ps);
197 16 : }
198 :
199 : //
200 : // Handler for ShowEvpnTableSummaryReq.
201 : // Schedules the callback to run in Task ("db::DBTable", 0) so that multicast
202 : // data structures in EvpnManager can be accessed safely. This is not really
203 : // necessary for summary requests, but we do this for consistency with regular
204 : // requests.
205 : //
206 16 : void ShowEvpnTableSummaryReq::HandleRequest() const {
207 16 : RequestPipeline::PipeSpec ps(this);
208 16 : RequestPipeline::StageSpec s1;
209 16 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
210 :
211 16 : s1.taskId_ = scheduler->GetTaskId("db::DBTable");
212 : s1.cbFn_ = boost::bind(&BgpShowHandler<
213 : ShowEvpnTableSummaryReq,
214 : ShowEvpnTableSummaryReqIterate,
215 : ShowEvpnTableSummaryResp,
216 16 : ShowEvpnTable>::Callback, _1, _2, _3, _4, _5);
217 : s1.allocFn_ = BgpShowHandler<
218 : ShowEvpnTableSummaryReq,
219 : ShowEvpnTableSummaryReqIterate,
220 : ShowEvpnTableSummaryResp,
221 16 : ShowEvpnTable>::CreateData;
222 16 : s1.instances_.push_back(0);
223 16 : ps.stages_.push_back(s1);
224 16 : RequestPipeline rp(ps);
225 16 : }
226 :
227 : //
228 : // Handler for ShowEvpnTableSummaryReqIterate.
229 : // Schedules the callback to run in Task ("db::DBTable", 0) so that multicast
230 : // data structures in EvpnManager can be accessed safely. This is not really
231 : // necessary for summary requests, but we do this for consistency with regular
232 : // requests.
233 : //
234 16 : void ShowEvpnTableSummaryReqIterate::HandleRequest() const {
235 16 : RequestPipeline::PipeSpec ps(this);
236 16 : RequestPipeline::StageSpec s1;
237 16 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
238 :
239 16 : s1.taskId_ = scheduler->GetTaskId("db::DBTable");
240 : s1.cbFn_ = boost::bind(&BgpShowHandler<
241 : ShowEvpnTableSummaryReq,
242 : ShowEvpnTableSummaryReqIterate,
243 : ShowEvpnTableSummaryResp,
244 16 : ShowEvpnTable>::CallbackIterate, _1, _2, _3, _4, _5);
245 : s1.allocFn_ = BgpShowHandler<
246 : ShowEvpnTableSummaryReq,
247 : ShowEvpnTableSummaryReqIterate,
248 : ShowEvpnTableSummaryResp,
249 16 : ShowEvpnTable>::CreateData;
250 16 : s1.instances_.push_back(0);
251 16 : ps.stages_.push_back(s1);
252 16 : RequestPipeline rp(ps);
253 16 : }
|