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