blob: 57930e0cbdab578fc98299f7f07e079816bf09ea [file] [log] [blame]
Alexander Afanasyev4a771362014-04-24 21:29:33 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
jeraldabrahamb6dde382014-03-19 18:58:09 -07002/**
Alexander Afanasyev4a771362014-04-24 21:29:33 -07003 * Copyright (c) 2014, Regents of the University of California,
4 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis
jeraldabrahamb6dde382014-03-19 18:58:09 -070010 *
Alexander Afanasyev4a771362014-04-24 21:29:33 -070011 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24 *
25 * @author Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
jeraldabrahamb6dde382014-03-19 18:58:09 -070026 */
27
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070028#include "version.hpp"
29
Alexander Afanasyev4a771362014-04-24 21:29:33 -070030#include <ndn-cxx/face.hpp>
31#include <ndn-cxx/name.hpp>
32#include <ndn-cxx/interest.hpp>
Alexander Afanasyevb3893c92014-05-15 01:49:54 -070033#include <ndn-cxx/encoding/buffer-stream.hpp>
jeraldabrahamb6dde382014-03-19 18:58:09 -070034
Alexander Afanasyev4a771362014-04-24 21:29:33 -070035#include <ndn-cxx/management/nfd-fib-entry.hpp>
36#include <ndn-cxx/management/nfd-face-status.hpp>
37#include <ndn-cxx/management/nfd-forwarder-status.hpp>
jeraldabrahamb6dde382014-03-19 18:58:09 -070038
Alexander Afanasyevb3893c92014-05-15 01:49:54 -070039#include <boost/algorithm/string/replace.hpp>
40
jeraldabrahamb6dde382014-03-19 18:58:09 -070041namespace ndn {
42
43class NfdStatus
44{
45public:
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -070046 explicit
jeraldabrahamb6dde382014-03-19 18:58:09 -070047 NfdStatus(char* toolName)
48 : m_toolName(toolName)
49 , m_needVersionRetrieval(false)
50 , m_needFaceStatusRetrieval(false)
51 , m_needFibEnumerationRetrieval(false)
Chengyu Fan514ed5e2014-04-17 13:07:30 -060052 , m_needXmlDataRetrieval(false)
jeraldabrahamb6dde382014-03-19 18:58:09 -070053 {
54 }
55
56 void
57 usage()
58 {
Alexander Afanasyev60a7ba52014-03-23 11:23:06 -070059 std::cout << "Usage: \n " << m_toolName << " [options]\n\n"
60 "Show NFD version and status information\n\n"
61 "Options:\n"
62 " [-h] - print this help message\n"
jeraldabrahamb6dde382014-03-19 18:58:09 -070063 " [-v] - retrieve version information\n"
64 " [-f] - retrieve face status information\n"
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070065 " [-b] - retrieve FIB information\n"
Chengyu Fan514ed5e2014-04-17 13:07:30 -060066 " [-x] - retrieve NFD status information in XML format\n"
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070067 "\n"
68 " [-V] - show version information of nfd-status and exit\n"
69 "\n"
Alexander Afanasyev60a7ba52014-03-23 11:23:06 -070070 "If no options are provided, all information is retrieved.\n"
Chengyu Fan514ed5e2014-04-17 13:07:30 -060071 "If -x is provided, other options(v, f and b) are ignored, and all information is retrieved in XML format.\n"
Alexander Afanasyev60a7ba52014-03-23 11:23:06 -070072 ;
jeraldabrahamb6dde382014-03-19 18:58:09 -070073 }
74
75 void
76 enableVersionRetrieval()
77 {
78 m_needVersionRetrieval = true;
79 }
80
81 void
82 enableFaceStatusRetrieval()
83 {
84 m_needFaceStatusRetrieval = true;
85 }
86
87 void
88 enableFibEnumerationRetrieval()
89 {
90 m_needFibEnumerationRetrieval = true;
91 }
92
93 void
Chengyu Fan514ed5e2014-04-17 13:07:30 -060094 enableXmlDataRetrieval()
95 {
96 m_needXmlDataRetrieval = true;
97 }
98
99 void
jeraldabrahamb6dde382014-03-19 18:58:09 -0700100 onTimeout()
101 {
102 std::cerr << "Request timed out" << std::endl;
103 }
104
105 void
106 fetchSegments(const Data& data, void (NfdStatus::*onDone)())
107 {
108 m_buffer->write((const char*)data.getContent().value(),
109 data.getContent().value_size());
110
111 uint64_t currentSegment = data.getName().get(-1).toSegment();
112
113 const name::Component& finalBlockId = data.getMetaInfo().getFinalBlockId();
114 if (finalBlockId.empty() ||
115 finalBlockId.toSegment() > currentSegment)
116 {
117 m_face.expressInterest(data.getName().getPrefix(-1).appendSegment(currentSegment+1),
118 bind(&NfdStatus::fetchSegments, this, _2, onDone),
119 bind(&NfdStatus::onTimeout, this));
120 }
121 else
122 {
123 return (this->*onDone)();
124 }
125 }
126
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600127 void escapeSpecialCharacters(std::string *data)
128 {
129 using boost::algorithm::replace_all;
130 replace_all(*data, "&", "&amp;");
131 replace_all(*data, "\"", "&quot;");
132 replace_all(*data, "\'", "&apos;");
133 replace_all(*data, "<", "&lt;");
134 replace_all(*data, ">", "&gt;");
135 }
136
jeraldabrahamb6dde382014-03-19 18:58:09 -0700137 void
138 afterFetchedVersionInformation(const Data& data)
139 {
Junxiao Shi88d69372014-03-28 11:52:39 -0700140 nfd::ForwarderStatus status(data.getContent());
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600141 if (m_needXmlDataRetrieval)
142 {
143 std::cout << "<?xml version=\"1.0\"?>";
144 std::cout << "<nfdStatus xmlns=\"ndn:/localhost/nfd/status/1\">";
145 std::cout << "<generalStatus>";
146 std::cout << "<version>"
147 << status.getNfdVersion() << "</version>";
148 std::cout << "<startTime>"
149 << time::toString(status.getStartTimestamp(), "%Y-%m-%dT%H:%M:%S%F")
150 << "</startTime>";
151 std::cout << "<currentTime>"
152 << time::toString(status.getCurrentTimestamp(), "%Y-%m-%dT%H:%M:%S%F")
153 << "</currentTime>";
154 std::cout << "<uptime>PT"
155 << time::duration_cast<time::seconds>(status.getCurrentTimestamp()
156 - status.getStartTimestamp()).count()
157 << "S</uptime>";
158 std::cout << "<nNameTreeEntries>" << status.getNNameTreeEntries()
159 << "</nNameTreeEntries>";
160 std::cout << "<nFibEntries>" << status.getNFibEntries()
161 << "</nFibEntries>";
162 std::cout << "<nPitEntries>" << status.getNPitEntries()
163 << "</nPitEntries>";
164 std::cout << "<nMeasurementsEntries>" << status.getNMeasurementsEntries()
165 << "</nMeasurementsEntries>";
166 std::cout << "<nCsEntries>" << status.getNCsEntries()
167 << "</nCsEntries>";
168 std::cout << "<packetCounters>";
169 std::cout << "<incomingPackets>";
170 std::cout << "<nInterests>" << status.getNInInterests()
171 << "</nInterests>";
172 std::cout << "<nDatas>" << status.getNInDatas()
173 << "</nDatas>";
174 std::cout << "</incomingPackets>";
175 std::cout << "<outgoingPackets>";
176 std::cout << "<nInterests>" << status.getNOutInterests()
177 << "</nInterests>";
178 std::cout << "<nDatas>" << status.getNOutDatas()
179 << "</nDatas>";
180 std::cout << "</outgoingPackets>";
181 std::cout << "</packetCounters>";
182 std::cout << "</generalStatus>";
183 }
184 else
185 {
186 std::cout << "General NFD status:" << std::endl;
187 std::cout << " version="
188 << status.getNfdVersion() << std::endl;
189 std::cout << " startTime="
190 << time::toIsoString(status.getStartTimestamp()) << std::endl;
191 std::cout << " currentTime="
192 << time::toIsoString(status.getCurrentTimestamp()) << std::endl;
193 std::cout << " uptime="
194 << time::duration_cast<time::seconds>(status.getCurrentTimestamp()
195 - status.getStartTimestamp()) << std::endl;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700196
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600197 std::cout << " nNameTreeEntries=" << status.getNNameTreeEntries() << std::endl;
198 std::cout << " nFibEntries=" << status.getNFibEntries() << std::endl;
199 std::cout << " nPitEntries=" << status.getNPitEntries() << std::endl;
200 std::cout << " nMeasurementsEntries=" << status.getNMeasurementsEntries() << std::endl;
201 std::cout << " nCsEntries=" << status.getNCsEntries() << std::endl;
202 std::cout << " nInInterests=" << status.getNInInterests() << std::endl;
203 std::cout << " nOutInterests=" << status.getNOutInterests() << std::endl;
204 std::cout << " nInDatas=" << status.getNInDatas() << std::endl;
205 std::cout << " nOutDatas=" << status.getNOutDatas() << std::endl;
206 }
jeraldabrahamb6dde382014-03-19 18:58:09 -0700207 if (m_needFaceStatusRetrieval)
208 {
209 fetchFaceStatusInformation();
210 }
211 else if (m_needFibEnumerationRetrieval)
212 {
213 fetchFibEnumerationInformation();
214 }
215 }
216
217 void
218 fetchVersionInformation()
219 {
220 Interest interest("/localhost/nfd/status");
221 interest.setChildSelector(1);
222 interest.setMustBeFresh(true);
223 m_face.expressInterest(
224 interest,
225 bind(&NfdStatus::afterFetchedVersionInformation, this, _2),
226 bind(&NfdStatus::onTimeout, this));
227 }
228
229 void
230 afterFetchedFaceStatusInformation()
231 {
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700232 ConstBufferPtr buf = m_buffer->buf();
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600233 if (m_needXmlDataRetrieval)
jeraldabrahamb6dde382014-03-19 18:58:09 -0700234 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600235 std::cout << "<faces>";
236
237 Block block;
238 size_t offset = 0;
239 while (offset < buf->size())
jeraldabrahamb6dde382014-03-19 18:58:09 -0700240 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600241 bool ok = Block::fromBuffer(buf, offset, block);
242 if (!ok)
243 {
244 std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
245 break;
246 }
247
248 offset += block.size();
249
250 nfd::FaceStatus faceStatus(block);
251
252 std::cout << "<face>";
253 std::cout << "<faceId>" << faceStatus.getFaceId() << "</faceId>";
254
255 std::string remoteUri(faceStatus.getRemoteUri());
256 escapeSpecialCharacters(&remoteUri);
257 std::cout << "<remoteUri>" << remoteUri << "</remoteUri>";
258
259 std::string localUri(faceStatus.getLocalUri());
260 escapeSpecialCharacters(&localUri);
261 std::cout << "<localUri>" << localUri << "</localUri>";
262 std::cout << "<packetCounters>";
263 std::cout << "<incomingPackets>";
264 std::cout << "<nInterests>" << faceStatus.getNInInterests()
265 << "</nInterests>";
266 std::cout << "<nDatas>" << faceStatus.getNInInterests()
267 << "</nDatas>";
268 std::cout << "</incomingPackets>";
269 std::cout << "<outgoingPackets>";
270 std::cout << "<nInterests>" << faceStatus.getNOutInterests()
271 << "</nInterests>";
272 std::cout << "<nDatas>" << faceStatus.getNOutInterests()
273 << "</nDatas>";
274 std::cout << "</outgoingPackets>";
275 std::cout << "</packetCounters>";
276 std::cout << "</face>";
jeraldabrahamb6dde382014-03-19 18:58:09 -0700277 }
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600278 std::cout << "</faces>";
jeraldabrahamb6dde382014-03-19 18:58:09 -0700279 }
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600280 else
281 {
282 std::cout << "Faces:" << std::endl;
283
284 Block block;
285 size_t offset = 0;
286 while (offset < buf->size())
287 {
288 bool ok = Block::fromBuffer(buf, offset, block);
289 if (!ok)
290 {
291 std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
292 break;
293 }
294
295 offset += block.size();
296
297 nfd::FaceStatus faceStatus(block);
298
299 std::cout << " faceid=" << faceStatus.getFaceId()
300 << " remote=" << faceStatus.getRemoteUri()
301 << " local=" << faceStatus.getLocalUri()
302 << " counters={"
303 << "in={" << faceStatus.getNInInterests() << "i "
304 << faceStatus.getNInDatas() << "d}"
305 << " out={" << faceStatus.getNOutInterests() << "i "
306 << faceStatus.getNOutDatas() << "d}"
307 << "}" << std::endl;
308 }
309 }
jeraldabrahamb6dde382014-03-19 18:58:09 -0700310
311 if (m_needFibEnumerationRetrieval)
312 {
313 fetchFibEnumerationInformation();
314 }
315 }
316
317 void
318 fetchFaceStatusInformation()
319 {
320 m_buffer = make_shared<OBufferStream>();
321
322 Interest interest("/localhost/nfd/faces/list");
323 interest.setChildSelector(1);
324 interest.setMustBeFresh(true);
325
326 m_face.expressInterest(interest,
327 bind(&NfdStatus::fetchSegments, this, _2,
328 &NfdStatus::afterFetchedFaceStatusInformation),
329 bind(&NfdStatus::onTimeout, this));
330 }
331
332 void
333 afterFetchedFibEnumerationInformation()
334 {
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700335 ConstBufferPtr buf = m_buffer->buf();
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600336 if (m_needXmlDataRetrieval)
jeraldabrahamb6dde382014-03-19 18:58:09 -0700337 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600338 std::cout << "<fib>";
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700339
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600340 Block block;
341 size_t offset = 0;
342 while (offset < buf->size())
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700343 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600344 bool ok = Block::fromBuffer(buf, offset, block);
345 if (!ok)
346 {
347 std::cerr << "ERROR: cannot decode FibEntry TLV";
348 break;
349 }
350 offset += block.size();
351
352 nfd::FibEntry fibEntry(block);
353
354 std::cout << "<fibEntry>";
355 std::string prefix(fibEntry.getPrefix().toUri());
356 escapeSpecialCharacters(&prefix);
357 std::cout << "<prefix>" << prefix << "</prefix>";
358 std::cout << "<nextHops>";
359 for (std::list<nfd::NextHopRecord>::const_iterator
360 nextHop = fibEntry.getNextHopRecords().begin();
361 nextHop != fibEntry.getNextHopRecords().end();
362 ++nextHop)
363 {
364 std::cout << "<nextHop>" ;
365 std::cout << "<faceId>" << nextHop->getFaceId() << "</faceId>";
366 std::cout << "<cost>" << nextHop->getCost() << "</cost>";
367 std::cout << "</nextHop>";
368 }
369 std::cout << "</nextHops>";
370 std::cout << "</fibEntry>";
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700371 }
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600372
373 std::cout << "</fib>";
374 std::cout << "</nfdStatus>";
375 }
376 else
377 {
378 std::cout << "FIB:" << std::endl;
379
380 Block block;
381 size_t offset = 0;
382 while (offset < buf->size())
383 {
384 bool ok = Block::fromBuffer(buf, offset, block);
385 if (!ok)
386 {
387 std::cerr << "ERROR: cannot decode FibEntry TLV" << std::endl;
388 break;
389 }
390 offset += block.size();
391
392 nfd::FibEntry fibEntry(block);
393
394 std::cout << " " << fibEntry.getPrefix() << " nexthops={";
395 for (std::list<nfd::NextHopRecord>::const_iterator
396 nextHop = fibEntry.getNextHopRecords().begin();
397 nextHop != fibEntry.getNextHopRecords().end();
398 ++nextHop)
399 {
400 if (nextHop != fibEntry.getNextHopRecords().begin())
401 std::cout << ", ";
402 std::cout << "faceid=" << nextHop->getFaceId()
403 << " (cost=" << nextHop->getCost() << ")";
404 }
405 std::cout << "}" << std::endl;
406 }
jeraldabrahamb6dde382014-03-19 18:58:09 -0700407 }
408 }
409
410 void
411 fetchFibEnumerationInformation()
412 {
413 m_buffer = make_shared<OBufferStream>();
414
415 Interest interest("/localhost/nfd/fib/list");
416 interest.setChildSelector(1);
417 interest.setMustBeFresh(true);
418 m_face.expressInterest(interest,
419 bind(&NfdStatus::fetchSegments, this, _2,
420 &NfdStatus::afterFetchedFibEnumerationInformation),
421 bind(&NfdStatus::onTimeout, this));
422 }
423
424 void
425 fetchInformation()
426 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600427 if (m_needXmlDataRetrieval ||
428 (!m_needVersionRetrieval &&
jeraldabrahamb6dde382014-03-19 18:58:09 -0700429 !m_needFaceStatusRetrieval &&
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600430 !m_needFibEnumerationRetrieval))
jeraldabrahamb6dde382014-03-19 18:58:09 -0700431 {
432 enableVersionRetrieval();
433 enableFaceStatusRetrieval();
434 enableFibEnumerationRetrieval();
435 }
436
437 if (m_needVersionRetrieval)
438 {
439 fetchVersionInformation();
440 }
441 else if (m_needFaceStatusRetrieval)
442 {
443 fetchFaceStatusInformation();
444 }
445 else if (m_needFibEnumerationRetrieval)
446 {
447 fetchFibEnumerationInformation();
448 }
449
450 m_face.processEvents();
451 }
452
453private:
454 std::string m_toolName;
455 bool m_needVersionRetrieval;
456 bool m_needFaceStatusRetrieval;
457 bool m_needFibEnumerationRetrieval;
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600458 bool m_needXmlDataRetrieval;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700459 Face m_face;
460
461 shared_ptr<OBufferStream> m_buffer;
462};
463
464}
465
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700466int main(int argc, char* argv[])
jeraldabrahamb6dde382014-03-19 18:58:09 -0700467{
468 int option;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700469 ndn::NfdStatus nfdStatus(argv[0]);
jeraldabrahamb6dde382014-03-19 18:58:09 -0700470
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600471 while ((option = getopt(argc, argv, "hvfbxV")) != -1) {
jeraldabrahamb6dde382014-03-19 18:58:09 -0700472 switch (option) {
473 case 'h':
474 nfdStatus.usage();
Alexander Afanasyev60a7ba52014-03-23 11:23:06 -0700475 return 0;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700476 case 'v':
477 nfdStatus.enableVersionRetrieval();
478 break;
479 case 'f':
480 nfdStatus.enableFaceStatusRetrieval();
481 break;
482 case 'b':
483 nfdStatus.enableFibEnumerationRetrieval();
484 break;
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600485 case 'x':
486 nfdStatus.enableXmlDataRetrieval();
487 break;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700488 case 'V':
489 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
490 return 0;
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700491 default:
jeraldabrahamb6dde382014-03-19 18:58:09 -0700492 nfdStatus.usage();
493 return 1;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700494 }
495 }
496
497 try {
498 nfdStatus.fetchInformation();
499 }
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700500 catch (std::exception& e) {
jeraldabrahamb6dde382014-03-19 18:58:09 -0700501 std::cerr << "ERROR: " << e.what() << std::endl;
502 return 2;
503 }
504
505 return 0;
506}