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 <sandesh/request_pipeline.h>
7 :
8 : #include <boost/bind/bind.hpp>
9 : #include <boost/assign/list_of.hpp>
10 : #include <boost/uuid/uuid_io.hpp>
11 : #include <boost/algorithm/string/trim.hpp>
12 :
13 : #include "base/logging.h"
14 : #include "db/db.h"
15 : #include "db/db_table_partition.h"
16 : #include "base/bitset.h"
17 :
18 : #include <ifmap/ifmap_update.h>
19 : #include <ifmap/ifmap_table.h>
20 : #include <ifmap/ifmap_agent_table.h>
21 : #include <ifmap/ifmap_node.h>
22 : #include <ifmap/ifmap_agent_types.h>
23 : #include <ifmap/ifmap_agent_parser.h>
24 : #include <pugixml/pugixml.hpp>
25 :
26 : using namespace boost::assign;
27 : using namespace std;
28 : using namespace boost::placeholders;
29 :
30 : class ShowIFMapAgentTable {
31 : public:
32 : static DB *db_;
33 : static IFMapAgentParser *parser_;
34 : struct ShowData : public RequestPipeline::InstData {
35 : vector<string> send_buffer;
36 : };
37 :
38 0 : RequestPipeline::InstData *AllocData(int stage) {
39 0 : return static_cast<RequestPipeline::InstData *>(new ShowData);
40 : }
41 :
42 : void MakeNode(const string &name_sub_string,
43 : const string &link_type_sub_string,
44 : const string &link_node_sub_string,
45 : string &dst, DBEntryBase *src);
46 :
47 : bool BufferStage(const Sandesh *sr, const RequestPipeline::PipeSpec ps,
48 : int stage, int instNum, RequestPipeline::InstData *data);
49 : bool SendStage(const Sandesh *sr, const RequestPipeline::PipeSpec ps,
50 : int stage, int instNum, RequestPipeline::InstData *data);
51 : void TableToBuffer(const ShowIFMapAgentReq *request, IFMapTable *table,
52 : ShowData *show_data);
53 :
54 : bool BufferAllTables(const RequestPipeline::PipeSpec ps,
55 : RequestPipeline::InstData *data);
56 : bool BufferSomeTables(const RequestPipeline::PipeSpec ps,
57 : RequestPipeline::InstData *data);
58 : };
59 :
60 : DB* ShowIFMapAgentTable::db_;
61 : IFMapAgentParser* ShowIFMapAgentTable::parser_;
62 :
63 0 : static inline void to_uuid(uint64_t ms_long, uint64_t ls_long,
64 : boost::uuids::uuid &u) {
65 0 : for (int i = 0; i < 8; i++) {
66 0 : u.data[7 - i] = ms_long & 0xFF;
67 0 : ms_long = ms_long >> 8;
68 : }
69 :
70 0 : for (int i = 0; i < 8; i++) {
71 0 : u.data[15 - i] = ls_long & 0xFF;
72 0 : ls_long = ls_long >> 8;
73 : }
74 0 : }
75 :
76 :
77 0 : void xml_parse(pugi::xml_node &node, string &s, int n) {
78 : int child;
79 0 : pugi::xml_node chld;
80 0 : pugi::xml_node fchld;
81 0 : string t(n, '\t');
82 : static uint64_t uuid_ms;
83 : static uint64_t uuid_ls;
84 : static int ls_set = 0;
85 : static int ms_set = 0;
86 :
87 0 : switch(node.type()) {
88 0 : case pugi::node_element:
89 0 : child = 0;
90 0 : for(chld = node.first_child(); chld; chld = chld.next_sibling()) {
91 0 : child++;
92 0 : fchld = chld;
93 : }
94 :
95 0 : if (strlen(node.child_value()) == 0) {
96 0 : if (!child) {
97 0 : break;
98 : }
99 0 : if ((child == 1) && (fchld.type() == pugi::node_pcdata) && (strlen(fchld.child_value()) == 0)) {
100 0 : break;
101 : }
102 : }
103 :
104 0 : if (strcmp(node.name(), "uuid-mslong") == 0) {
105 0 : string value(node.child_value());
106 0 : boost::trim(value);
107 0 : uuid_ms = strtoull(value.c_str(), NULL, 10);
108 0 : ms_set = 1;
109 0 : }
110 :
111 0 : if (strcmp(node.name(), "uuid-lslong") == 0) {
112 0 : string value(node.child_value());
113 0 : boost::trim(value);
114 0 : uuid_ls = strtoull(value.c_str(), NULL, 10);
115 0 : ls_set = 1;
116 0 : }
117 :
118 0 : if (strcmp(node.name(), "config") && strcmp(node.name(), "node")) {
119 :
120 0 : if (strlen(node.child_value())) {
121 0 : s = s + t + node.name() + ":" + node.child_value() + "\n";
122 : } else {
123 0 : s = s + t + node.name() + "\n";
124 : }
125 : }
126 :
127 0 : if (ms_set && ls_set) {
128 : boost::uuids::uuid u;
129 0 : to_uuid(uuid_ms, uuid_ls, u);
130 0 : string tmp = UuidToString(u);
131 0 : s = s + t + "Uuid : " + tmp + "\n";
132 0 : ms_set = ls_set = 0;
133 0 : }
134 :
135 0 : for (pugi::xml_attribute_iterator ait = node.attributes_begin(); ait != node.attributes_end(); ++ait) {
136 0 : s = s + t + ait->name() + ":" + ait->value() + "\n";
137 : }
138 :
139 0 : for(pugi::xml_node chld = node.first_child(); chld; chld = chld.next_sibling()) {
140 0 : xml_parse(chld, s, n + 1);
141 : }
142 0 : break;
143 :
144 0 : case pugi::node_pcdata:
145 0 : s = s + node.child_value() + "\n";
146 0 : break;
147 :
148 0 : default:
149 0 : break;
150 : }
151 0 : }
152 0 : void ShowIFMapAgentTable::MakeNode(const string &name_sub_string,
153 : const string &link_node_sub_string,
154 : const string &link_type_sub_string,
155 : string &dst, DBEntryBase *src) {
156 0 : IFMapNode *node = static_cast<IFMapNode *>(src);
157 0 : pugi::xml_document doc;
158 0 : pugi::xml_node config;
159 :
160 0 : if (name_sub_string.empty() == false) {
161 0 : if (node->name().find(name_sub_string) == string::npos)
162 0 : return;
163 : }
164 :
165 0 : dst += "\n";
166 0 : if (!node->IsDeleted()) {
167 0 : config = doc.append_child("config");
168 : } else {
169 0 : config = doc.append_child("Delete Marked config");
170 : }
171 :
172 0 : node->EncodeNodeDetail(&config);
173 0 : xml_parse(config, dst, 1);
174 :
175 0 : if (node->IsDeleted()) {
176 0 : return;
177 : }
178 :
179 : // Display its adjacencies
180 0 : dst = dst + "Adjacencies:\n";
181 0 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
182 0 : for (DBGraphVertex::adjacency_iterator
183 0 : iter = node->begin(table->GetGraph());
184 0 : iter != node->end(table->GetGraph()); ++iter) {
185 0 : IFMapNode *adj_node = static_cast<IFMapNode *>(iter.operator->());
186 :
187 0 : if (link_type_sub_string.empty() == false) {
188 : // Check if filter passes the table-name for the adjacency
189 0 : if (strstr(adj_node->table()->Typename(),
190 0 : link_type_sub_string.c_str()) == NULL)
191 0 : continue;
192 : }
193 :
194 0 : if (link_node_sub_string.empty() == false) {
195 : // Check if filter passes the node-name for the adjacency
196 0 : if (adj_node->name().find(link_node_sub_string) == string::npos)
197 0 : continue;
198 : }
199 :
200 0 : dst = dst + "\t" + adj_node->table()->Typename() + " " +
201 0 : adj_node->name() +"\n";
202 : }
203 0 : }
204 :
205 0 : void ShowIFMapAgentTable::TableToBuffer(const ShowIFMapAgentReq *request,
206 : IFMapTable *table,
207 : ShowData *show_data) {
208 0 : for (int i = 0; i < IFMapTable::kPartitionCount; i++) {
209 0 : DBTablePartBase *partition = table->GetTablePartition(i);
210 0 : DBEntryBase *src = partition->GetFirst();
211 0 : while (src) {
212 0 : string dst;
213 0 : MakeNode(request->get_node_sub_string(),
214 : request->get_link_node_sub_string(),
215 : request->get_link_type_sub_string(),
216 : dst, src);
217 0 : if (dst.empty() == false)
218 0 : show_data->send_buffer.push_back(dst);
219 0 : src = partition->GetNext(src);
220 0 : }
221 : }
222 0 : }
223 :
224 0 : bool ShowIFMapAgentTable::BufferSomeTables(const RequestPipeline::PipeSpec ps,
225 : RequestPipeline::InstData *data) {
226 : const ShowIFMapAgentReq *request =
227 0 : static_cast<const ShowIFMapAgentReq *>(ps.snhRequest_.get());
228 :
229 0 : IFMapTable *table = IFMapTable::FindTable(db_, request->get_table_name());
230 0 : if (table == NULL) {
231 0 : LOG(DEBUG, "Invalid table name: " << request->get_table_name());
232 0 : return true;
233 : }
234 :
235 0 : if (table->name().find("__ifmap__.") != 0) {
236 0 : LOG(DEBUG, "Invalid table name: " << request->get_table_name());
237 0 : return true;
238 : }
239 :
240 0 : ShowData *show_data = static_cast<ShowData *>(data);
241 0 : TableToBuffer(request, table, show_data);
242 0 : return true;
243 : }
244 :
245 0 : bool ShowIFMapAgentTable::BufferAllTables(const RequestPipeline::PipeSpec ps,
246 : RequestPipeline::InstData *data) {
247 :
248 : const ShowIFMapAgentReq *request =
249 0 : static_cast<const ShowIFMapAgentReq *>(ps.snhRequest_.get());
250 0 : for (DB::iterator iter = db_->lower_bound("__ifmap__.");
251 0 : iter != db_->end(); ++iter) {
252 0 : if (iter->first.find("__ifmap__.") != 0) {
253 0 : break;
254 : }
255 0 : IFMapTable *table = static_cast<IFMapTable *>(iter->second);
256 0 : ShowData *show_data = static_cast<ShowData *>(data);
257 0 : TableToBuffer(request, table, show_data);
258 : }
259 :
260 0 : return true;
261 : }
262 :
263 0 : bool ShowIFMapAgentTable::BufferStage(const Sandesh *sr,
264 : const RequestPipeline::PipeSpec ps,
265 : int stage, int instNum,
266 : RequestPipeline::InstData *data) {
267 :
268 : const ShowIFMapAgentReq *request =
269 0 : static_cast<const ShowIFMapAgentReq *>(ps.snhRequest_.get());
270 : // If table name has not been passed, print all tables
271 0 : if (request->get_table_name().length()) {
272 0 : return BufferSomeTables(ps, data);
273 : } else {
274 0 : return BufferAllTables(ps, data);
275 : }
276 : }
277 :
278 0 : bool ShowIFMapAgentTable::SendStage(const Sandesh *sr,
279 : const RequestPipeline::PipeSpec ps,
280 : int stage, int instNum,
281 : RequestPipeline::InstData *data) {
282 0 : const RequestPipeline::StageData *stage_data = ps.GetStageData(0);
283 : const ShowIFMapAgentTable::ShowData &show_data =
284 0 : static_cast<const ShowIFMapAgentTable::ShowData &> (stage_data->at(0));
285 : const ShowIFMapAgentReq *request =
286 0 : static_cast<const ShowIFMapAgentReq *>(ps.snhRequest_.get());
287 0 : ShowIFMapAgentResp *response = new ShowIFMapAgentResp();
288 0 : response->set_table_data(show_data.send_buffer);
289 0 : response->set_context(request->context());
290 0 : response->set_more(false);
291 0 : response->Response();
292 0 : return true;
293 : }
294 :
295 0 : void ShowIFMapAgentReq::HandleRequest() const {
296 : ShowIFMapAgentTable show_table;
297 :
298 0 : RequestPipeline::StageSpec s0, s1;
299 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
300 :
301 : // 2 stages - first: gather/read, second: send
302 :
303 0 : s0.taskId_ = scheduler->GetTaskId("db::DBTable");
304 0 : s0.allocFn_ = boost::bind(&ShowIFMapAgentTable::AllocData, &show_table, _1);
305 : s0.cbFn_ = boost::bind(&ShowIFMapAgentTable::BufferStage, &show_table,
306 0 : _1, _2, _3, _4, _5);
307 0 : s0.instances_.push_back(0);
308 :
309 : // Agent ifmap show command task
310 0 : s1.taskId_ = scheduler->GetTaskId("agent_ifmap::ShowCommand");
311 0 : s1.allocFn_ = boost::bind(&ShowIFMapAgentTable::AllocData, &show_table, _1);
312 : s1.cbFn_ = boost::bind(&ShowIFMapAgentTable::SendStage, &show_table,
313 0 : _1, _2, _3, _4, _5);
314 0 : s1.instances_.push_back(0);
315 :
316 0 : RequestPipeline::PipeSpec ps(this);
317 0 : ps.stages_= list_of(s0)(s1)
318 0 : .convert_to_container<vector<RequestPipeline::StageSpec> >();
319 0 : RequestPipeline rp(ps);
320 0 : }
321 :
322 0 : void ShowIFMapAgentDefLinkReq::HandleRequest() const {
323 : ShowIFMapAgentDefLinkResp *resp;
324 0 : resp = new ShowIFMapAgentDefLinkResp();
325 :
326 : //Get link table
327 : IFMapAgentLinkTable *link_table = static_cast<IFMapAgentLinkTable *>(
328 0 : ShowIFMapAgentTable::db_->FindTable(IFMAP_AGENT_LINK_DB_NAME));
329 :
330 0 : IFMapAgentLinkTable::LinkDefMap::const_iterator dlist_it;
331 : std::list<IFMapAgentLinkTable::DeferredNode> *ent;
332 0 : std::list<IFMapAgentLinkTable::DeferredNode>::iterator it;
333 :
334 : //Get linktables's deferred list
335 0 : const IFMapAgentLinkTable::LinkDefMap &def_list = link_table->GetLinkDefMap();
336 :
337 : //Get Sandesh response's output list
338 : std::vector<IFMapAgentDefLink> &list =
339 0 : const_cast<std::vector<IFMapAgentDefLink>&>(resp->get_def_list());
340 :
341 : //Iterate left node list
342 0 : for(dlist_it = def_list.begin(); dlist_it != def_list.end(); dlist_it++) {
343 0 : const IFMapTable::RequestKey &temp = dlist_it->first;
344 0 : ent = dlist_it->second;
345 :
346 : //Iterate the right nodes corresponding to above left node
347 0 : for(it = ent->begin(); it != ent->end(); it++) {
348 0 : IFMapAgentDefLink data;
349 0 : data.set_seq_num((*it).node_key.id_seq_num);
350 0 : data.set_left_node(temp.id_type + ":" +
351 0 : temp.id_name);
352 0 : data.set_metadata((*it).link_metadata);
353 0 : data.set_right_node((*it).node_key.id_type + ":" +
354 0 : (*it).node_key.id_name);
355 0 : list.push_back(data);
356 0 : }
357 : }
358 0 : resp->set_context(context());
359 0 : resp->Response();
360 0 : return;
361 : }
362 :
363 0 : void ShowIFMapAgentStatsReq::HandleRequest() const {
364 :
365 0 : IFMapAgentParser *parser = ShowIFMapAgentTable::parser_;
366 :
367 0 : if (!parser)
368 0 : return;
369 :
370 : ShowIFMapAgentStatsResp *resp;
371 0 : resp = new ShowIFMapAgentStatsResp();
372 :
373 0 : resp->set_node_updates_processed(parser->node_updates());
374 0 : resp->set_node_deletes_processed(parser->node_deletes());
375 0 : resp->set_link_updates_processed(parser->link_updates());
376 0 : resp->set_link_deletes_processed(parser->link_deletes());
377 0 : resp->set_node_update_parse_errors(parser->node_update_parse_errors());
378 0 : resp->set_link_update_parse_errors(parser->link_update_parse_errors());
379 0 : resp->set_node_delete_parse_errors(parser->node_delete_parse_errors());
380 0 : resp->set_link_delete_parse_errors(parser->link_delete_parse_errors());
381 :
382 0 : resp->set_context(context());
383 0 : resp->Response();
384 0 : return;
385 : }
386 :
387 2 : void IFMapAgentSandeshInit(DB *db, IFMapAgentParser *parser) {
388 2 : ShowIFMapAgentTable::db_ = db;
389 2 : ShowIFMapAgentTable::parser_ = parser;
390 2 : }
|