blob: 179296172286d12aa90e2d1a82ea9f76a9a68534 [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>
jeraldabrahamb6dde382014-03-19 18:58:09 -070033
Alexander Afanasyev4a771362014-04-24 21:29:33 -070034#include <ndn-cxx/management/nfd-fib-entry.hpp>
35#include <ndn-cxx/management/nfd-face-status.hpp>
36#include <ndn-cxx/management/nfd-forwarder-status.hpp>
jeraldabrahamb6dde382014-03-19 18:58:09 -070037
38namespace ndn {
39
40class NfdStatus
41{
42public:
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -070043 explicit
jeraldabrahamb6dde382014-03-19 18:58:09 -070044 NfdStatus(char* toolName)
45 : m_toolName(toolName)
46 , m_needVersionRetrieval(false)
47 , m_needFaceStatusRetrieval(false)
48 , m_needFibEnumerationRetrieval(false)
Chengyu Fan514ed5e2014-04-17 13:07:30 -060049 , m_needXmlDataRetrieval(false)
jeraldabrahamb6dde382014-03-19 18:58:09 -070050 {
51 }
52
53 void
54 usage()
55 {
Alexander Afanasyev60a7ba52014-03-23 11:23:06 -070056 std::cout << "Usage: \n " << m_toolName << " [options]\n\n"
57 "Show NFD version and status information\n\n"
58 "Options:\n"
59 " [-h] - print this help message\n"
jeraldabrahamb6dde382014-03-19 18:58:09 -070060 " [-v] - retrieve version information\n"
61 " [-f] - retrieve face status information\n"
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070062 " [-b] - retrieve FIB information\n"
Chengyu Fan514ed5e2014-04-17 13:07:30 -060063 " [-x] - retrieve NFD status information in XML format\n"
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070064 "\n"
65 " [-V] - show version information of nfd-status and exit\n"
66 "\n"
Alexander Afanasyev60a7ba52014-03-23 11:23:06 -070067 "If no options are provided, all information is retrieved.\n"
Chengyu Fan514ed5e2014-04-17 13:07:30 -060068 "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 -070069 ;
jeraldabrahamb6dde382014-03-19 18:58:09 -070070 }
71
72 void
73 enableVersionRetrieval()
74 {
75 m_needVersionRetrieval = true;
76 }
77
78 void
79 enableFaceStatusRetrieval()
80 {
81 m_needFaceStatusRetrieval = true;
82 }
83
84 void
85 enableFibEnumerationRetrieval()
86 {
87 m_needFibEnumerationRetrieval = true;
88 }
89
90 void
Chengyu Fan514ed5e2014-04-17 13:07:30 -060091 enableXmlDataRetrieval()
92 {
93 m_needXmlDataRetrieval = true;
94 }
95
96 void
jeraldabrahamb6dde382014-03-19 18:58:09 -070097 onTimeout()
98 {
99 std::cerr << "Request timed out" << std::endl;
100 }
101
102 void
103 fetchSegments(const Data& data, void (NfdStatus::*onDone)())
104 {
105 m_buffer->write((const char*)data.getContent().value(),
106 data.getContent().value_size());
107
108 uint64_t currentSegment = data.getName().get(-1).toSegment();
109
110 const name::Component& finalBlockId = data.getMetaInfo().getFinalBlockId();
111 if (finalBlockId.empty() ||
112 finalBlockId.toSegment() > currentSegment)
113 {
114 m_face.expressInterest(data.getName().getPrefix(-1).appendSegment(currentSegment+1),
115 bind(&NfdStatus::fetchSegments, this, _2, onDone),
116 bind(&NfdStatus::onTimeout, this));
117 }
118 else
119 {
120 return (this->*onDone)();
121 }
122 }
123
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600124 void escapeSpecialCharacters(std::string *data)
125 {
126 using boost::algorithm::replace_all;
127 replace_all(*data, "&", "&amp;");
128 replace_all(*data, "\"", "&quot;");
129 replace_all(*data, "\'", "&apos;");
130 replace_all(*data, "<", "&lt;");
131 replace_all(*data, ">", "&gt;");
132 }
133
jeraldabrahamb6dde382014-03-19 18:58:09 -0700134 void
135 afterFetchedVersionInformation(const Data& data)
136 {
Junxiao Shi88d69372014-03-28 11:52:39 -0700137 nfd::ForwarderStatus status(data.getContent());
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600138 if (m_needXmlDataRetrieval)
139 {
140 std::cout << "<?xml version=\"1.0\"?>";
141 std::cout << "<nfdStatus xmlns=\"ndn:/localhost/nfd/status/1\">";
142 std::cout << "<generalStatus>";
143 std::cout << "<version>"
144 << status.getNfdVersion() << "</version>";
145 std::cout << "<startTime>"
146 << time::toString(status.getStartTimestamp(), "%Y-%m-%dT%H:%M:%S%F")
147 << "</startTime>";
148 std::cout << "<currentTime>"
149 << time::toString(status.getCurrentTimestamp(), "%Y-%m-%dT%H:%M:%S%F")
150 << "</currentTime>";
151 std::cout << "<uptime>PT"
152 << time::duration_cast<time::seconds>(status.getCurrentTimestamp()
153 - status.getStartTimestamp()).count()
154 << "S</uptime>";
155 std::cout << "<nNameTreeEntries>" << status.getNNameTreeEntries()
156 << "</nNameTreeEntries>";
157 std::cout << "<nFibEntries>" << status.getNFibEntries()
158 << "</nFibEntries>";
159 std::cout << "<nPitEntries>" << status.getNPitEntries()
160 << "</nPitEntries>";
161 std::cout << "<nMeasurementsEntries>" << status.getNMeasurementsEntries()
162 << "</nMeasurementsEntries>";
163 std::cout << "<nCsEntries>" << status.getNCsEntries()
164 << "</nCsEntries>";
165 std::cout << "<packetCounters>";
166 std::cout << "<incomingPackets>";
167 std::cout << "<nInterests>" << status.getNInInterests()
168 << "</nInterests>";
169 std::cout << "<nDatas>" << status.getNInDatas()
170 << "</nDatas>";
171 std::cout << "</incomingPackets>";
172 std::cout << "<outgoingPackets>";
173 std::cout << "<nInterests>" << status.getNOutInterests()
174 << "</nInterests>";
175 std::cout << "<nDatas>" << status.getNOutDatas()
176 << "</nDatas>";
177 std::cout << "</outgoingPackets>";
178 std::cout << "</packetCounters>";
179 std::cout << "</generalStatus>";
180 }
181 else
182 {
183 std::cout << "General NFD status:" << std::endl;
184 std::cout << " version="
185 << status.getNfdVersion() << std::endl;
186 std::cout << " startTime="
187 << time::toIsoString(status.getStartTimestamp()) << std::endl;
188 std::cout << " currentTime="
189 << time::toIsoString(status.getCurrentTimestamp()) << std::endl;
190 std::cout << " uptime="
191 << time::duration_cast<time::seconds>(status.getCurrentTimestamp()
192 - status.getStartTimestamp()) << std::endl;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700193
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600194 std::cout << " nNameTreeEntries=" << status.getNNameTreeEntries() << std::endl;
195 std::cout << " nFibEntries=" << status.getNFibEntries() << std::endl;
196 std::cout << " nPitEntries=" << status.getNPitEntries() << std::endl;
197 std::cout << " nMeasurementsEntries=" << status.getNMeasurementsEntries() << std::endl;
198 std::cout << " nCsEntries=" << status.getNCsEntries() << std::endl;
199 std::cout << " nInInterests=" << status.getNInInterests() << std::endl;
200 std::cout << " nOutInterests=" << status.getNOutInterests() << std::endl;
201 std::cout << " nInDatas=" << status.getNInDatas() << std::endl;
202 std::cout << " nOutDatas=" << status.getNOutDatas() << std::endl;
203 }
jeraldabrahamb6dde382014-03-19 18:58:09 -0700204 if (m_needFaceStatusRetrieval)
205 {
206 fetchFaceStatusInformation();
207 }
208 else if (m_needFibEnumerationRetrieval)
209 {
210 fetchFibEnumerationInformation();
211 }
212 }
213
214 void
215 fetchVersionInformation()
216 {
217 Interest interest("/localhost/nfd/status");
218 interest.setChildSelector(1);
219 interest.setMustBeFresh(true);
220 m_face.expressInterest(
221 interest,
222 bind(&NfdStatus::afterFetchedVersionInformation, this, _2),
223 bind(&NfdStatus::onTimeout, this));
224 }
225
226 void
227 afterFetchedFaceStatusInformation()
228 {
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700229 ConstBufferPtr buf = m_buffer->buf();
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600230 if (m_needXmlDataRetrieval)
jeraldabrahamb6dde382014-03-19 18:58:09 -0700231 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600232 std::cout << "<faces>";
233
234 Block block;
235 size_t offset = 0;
236 while (offset < buf->size())
jeraldabrahamb6dde382014-03-19 18:58:09 -0700237 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600238 bool ok = Block::fromBuffer(buf, offset, block);
239 if (!ok)
240 {
241 std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
242 break;
243 }
244
245 offset += block.size();
246
247 nfd::FaceStatus faceStatus(block);
248
249 std::cout << "<face>";
250 std::cout << "<faceId>" << faceStatus.getFaceId() << "</faceId>";
251
252 std::string remoteUri(faceStatus.getRemoteUri());
253 escapeSpecialCharacters(&remoteUri);
254 std::cout << "<remoteUri>" << remoteUri << "</remoteUri>";
255
256 std::string localUri(faceStatus.getLocalUri());
257 escapeSpecialCharacters(&localUri);
258 std::cout << "<localUri>" << localUri << "</localUri>";
259 std::cout << "<packetCounters>";
260 std::cout << "<incomingPackets>";
261 std::cout << "<nInterests>" << faceStatus.getNInInterests()
262 << "</nInterests>";
263 std::cout << "<nDatas>" << faceStatus.getNInInterests()
264 << "</nDatas>";
265 std::cout << "</incomingPackets>";
266 std::cout << "<outgoingPackets>";
267 std::cout << "<nInterests>" << faceStatus.getNOutInterests()
268 << "</nInterests>";
269 std::cout << "<nDatas>" << faceStatus.getNOutInterests()
270 << "</nDatas>";
271 std::cout << "</outgoingPackets>";
272 std::cout << "</packetCounters>";
273 std::cout << "</face>";
jeraldabrahamb6dde382014-03-19 18:58:09 -0700274 }
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600275 std::cout << "</faces>";
jeraldabrahamb6dde382014-03-19 18:58:09 -0700276 }
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600277 else
278 {
279 std::cout << "Faces:" << std::endl;
280
281 Block block;
282 size_t offset = 0;
283 while (offset < buf->size())
284 {
285 bool ok = Block::fromBuffer(buf, offset, block);
286 if (!ok)
287 {
288 std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
289 break;
290 }
291
292 offset += block.size();
293
294 nfd::FaceStatus faceStatus(block);
295
296 std::cout << " faceid=" << faceStatus.getFaceId()
297 << " remote=" << faceStatus.getRemoteUri()
298 << " local=" << faceStatus.getLocalUri()
299 << " counters={"
300 << "in={" << faceStatus.getNInInterests() << "i "
301 << faceStatus.getNInDatas() << "d}"
302 << " out={" << faceStatus.getNOutInterests() << "i "
303 << faceStatus.getNOutDatas() << "d}"
304 << "}" << std::endl;
305 }
306 }
jeraldabrahamb6dde382014-03-19 18:58:09 -0700307
308 if (m_needFibEnumerationRetrieval)
309 {
310 fetchFibEnumerationInformation();
311 }
312 }
313
314 void
315 fetchFaceStatusInformation()
316 {
317 m_buffer = make_shared<OBufferStream>();
318
319 Interest interest("/localhost/nfd/faces/list");
320 interest.setChildSelector(1);
321 interest.setMustBeFresh(true);
322
323 m_face.expressInterest(interest,
324 bind(&NfdStatus::fetchSegments, this, _2,
325 &NfdStatus::afterFetchedFaceStatusInformation),
326 bind(&NfdStatus::onTimeout, this));
327 }
328
329 void
330 afterFetchedFibEnumerationInformation()
331 {
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700332 ConstBufferPtr buf = m_buffer->buf();
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600333 if (m_needXmlDataRetrieval)
jeraldabrahamb6dde382014-03-19 18:58:09 -0700334 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600335 std::cout << "<fib>";
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700336
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600337 Block block;
338 size_t offset = 0;
339 while (offset < buf->size())
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700340 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600341 bool ok = Block::fromBuffer(buf, offset, block);
342 if (!ok)
343 {
344 std::cerr << "ERROR: cannot decode FibEntry TLV";
345 break;
346 }
347 offset += block.size();
348
349 nfd::FibEntry fibEntry(block);
350
351 std::cout << "<fibEntry>";
352 std::string prefix(fibEntry.getPrefix().toUri());
353 escapeSpecialCharacters(&prefix);
354 std::cout << "<prefix>" << prefix << "</prefix>";
355 std::cout << "<nextHops>";
356 for (std::list<nfd::NextHopRecord>::const_iterator
357 nextHop = fibEntry.getNextHopRecords().begin();
358 nextHop != fibEntry.getNextHopRecords().end();
359 ++nextHop)
360 {
361 std::cout << "<nextHop>" ;
362 std::cout << "<faceId>" << nextHop->getFaceId() << "</faceId>";
363 std::cout << "<cost>" << nextHop->getCost() << "</cost>";
364 std::cout << "</nextHop>";
365 }
366 std::cout << "</nextHops>";
367 std::cout << "</fibEntry>";
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700368 }
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600369
370 std::cout << "</fib>";
371 std::cout << "</nfdStatus>";
372 }
373 else
374 {
375 std::cout << "FIB:" << std::endl;
376
377 Block block;
378 size_t offset = 0;
379 while (offset < buf->size())
380 {
381 bool ok = Block::fromBuffer(buf, offset, block);
382 if (!ok)
383 {
384 std::cerr << "ERROR: cannot decode FibEntry TLV" << std::endl;
385 break;
386 }
387 offset += block.size();
388
389 nfd::FibEntry fibEntry(block);
390
391 std::cout << " " << fibEntry.getPrefix() << " nexthops={";
392 for (std::list<nfd::NextHopRecord>::const_iterator
393 nextHop = fibEntry.getNextHopRecords().begin();
394 nextHop != fibEntry.getNextHopRecords().end();
395 ++nextHop)
396 {
397 if (nextHop != fibEntry.getNextHopRecords().begin())
398 std::cout << ", ";
399 std::cout << "faceid=" << nextHop->getFaceId()
400 << " (cost=" << nextHop->getCost() << ")";
401 }
402 std::cout << "}" << std::endl;
403 }
jeraldabrahamb6dde382014-03-19 18:58:09 -0700404 }
405 }
406
407 void
408 fetchFibEnumerationInformation()
409 {
410 m_buffer = make_shared<OBufferStream>();
411
412 Interest interest("/localhost/nfd/fib/list");
413 interest.setChildSelector(1);
414 interest.setMustBeFresh(true);
415 m_face.expressInterest(interest,
416 bind(&NfdStatus::fetchSegments, this, _2,
417 &NfdStatus::afterFetchedFibEnumerationInformation),
418 bind(&NfdStatus::onTimeout, this));
419 }
420
421 void
422 fetchInformation()
423 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600424 if (m_needXmlDataRetrieval ||
425 (!m_needVersionRetrieval &&
jeraldabrahamb6dde382014-03-19 18:58:09 -0700426 !m_needFaceStatusRetrieval &&
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600427 !m_needFibEnumerationRetrieval))
jeraldabrahamb6dde382014-03-19 18:58:09 -0700428 {
429 enableVersionRetrieval();
430 enableFaceStatusRetrieval();
431 enableFibEnumerationRetrieval();
432 }
433
434 if (m_needVersionRetrieval)
435 {
436 fetchVersionInformation();
437 }
438 else if (m_needFaceStatusRetrieval)
439 {
440 fetchFaceStatusInformation();
441 }
442 else if (m_needFibEnumerationRetrieval)
443 {
444 fetchFibEnumerationInformation();
445 }
446
447 m_face.processEvents();
448 }
449
450private:
451 std::string m_toolName;
452 bool m_needVersionRetrieval;
453 bool m_needFaceStatusRetrieval;
454 bool m_needFibEnumerationRetrieval;
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600455 bool m_needXmlDataRetrieval;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700456 Face m_face;
457
458 shared_ptr<OBufferStream> m_buffer;
459};
460
461}
462
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700463int main(int argc, char* argv[])
jeraldabrahamb6dde382014-03-19 18:58:09 -0700464{
465 int option;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700466 ndn::NfdStatus nfdStatus(argv[0]);
jeraldabrahamb6dde382014-03-19 18:58:09 -0700467
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600468 while ((option = getopt(argc, argv, "hvfbxV")) != -1) {
jeraldabrahamb6dde382014-03-19 18:58:09 -0700469 switch (option) {
470 case 'h':
471 nfdStatus.usage();
Alexander Afanasyev60a7ba52014-03-23 11:23:06 -0700472 return 0;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700473 case 'v':
474 nfdStatus.enableVersionRetrieval();
475 break;
476 case 'f':
477 nfdStatus.enableFaceStatusRetrieval();
478 break;
479 case 'b':
480 nfdStatus.enableFibEnumerationRetrieval();
481 break;
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600482 case 'x':
483 nfdStatus.enableXmlDataRetrieval();
484 break;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700485 case 'V':
486 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
487 return 0;
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700488 default:
jeraldabrahamb6dde382014-03-19 18:58:09 -0700489 nfdStatus.usage();
490 return 1;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700491 }
492 }
493
494 try {
495 nfdStatus.fetchInformation();
496 }
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700497 catch (std::exception& e) {
jeraldabrahamb6dde382014-03-19 18:58:09 -0700498 std::cerr << "ERROR: " << e.what() << std::endl;
499 return 2;
500 }
501
502 return 0;
503}