blob: affd2d84ff2b907ed4dd96454fc1dafe8eea4506 [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-forwarder-status.hpp>
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +030036#include <ndn-cxx/management/nfd-channel-status.hpp>
37#include <ndn-cxx/management/nfd-face-status.hpp>
38#include <ndn-cxx/management/nfd-fib-entry.hpp>
Chengyu Fan30aa2072014-07-20 13:52:32 -060039#include <ndn-cxx/management/nfd-rib-entry.hpp>
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +030040#include <ndn-cxx/management/nfd-strategy-choice.hpp>
jeraldabrahamb6dde382014-03-19 18:58:09 -070041
Alexander Afanasyevb3893c92014-05-15 01:49:54 -070042#include <boost/algorithm/string/replace.hpp>
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +030043#include <list>
Alexander Afanasyevb3893c92014-05-15 01:49:54 -070044
jeraldabrahamb6dde382014-03-19 18:58:09 -070045namespace ndn {
46
47class NfdStatus
48{
49public:
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -070050 explicit
jeraldabrahamb6dde382014-03-19 18:58:09 -070051 NfdStatus(char* toolName)
52 : m_toolName(toolName)
53 , m_needVersionRetrieval(false)
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +030054 , m_needChannelStatusRetrieval(false)
jeraldabrahamb6dde382014-03-19 18:58:09 -070055 , m_needFaceStatusRetrieval(false)
56 , m_needFibEnumerationRetrieval(false)
Chengyu Fan30aa2072014-07-20 13:52:32 -060057 , m_needRibStatusRetrieval(false)
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +030058 , m_needStrategyChoiceRetrieval(false)
59 , m_isOutputXml(false)
jeraldabrahamb6dde382014-03-19 18:58:09 -070060 {
61 }
62
63 void
64 usage()
65 {
Alexander Afanasyev60a7ba52014-03-23 11:23:06 -070066 std::cout << "Usage: \n " << m_toolName << " [options]\n\n"
67 "Show NFD version and status information\n\n"
68 "Options:\n"
69 " [-h] - print this help message\n"
jeraldabrahamb6dde382014-03-19 18:58:09 -070070 " [-v] - retrieve version information\n"
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +030071 " [-c] - retrieve channel status information\n"
jeraldabrahamb6dde382014-03-19 18:58:09 -070072 " [-f] - retrieve face status information\n"
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070073 " [-b] - retrieve FIB information\n"
Chengyu Fan30aa2072014-07-20 13:52:32 -060074 " [-r] - retrieve RIB information\n"
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +030075 " [-s] - retrieve configured strategy choice for NDN namespaces\n"
Chengyu Fanee92fc72014-06-21 14:58:19 -060076 " [-x] - output NFD status information in XML format\n"
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070077 "\n"
78 " [-V] - show version information of nfd-status and exit\n"
79 "\n"
Alexander Afanasyev60a7ba52014-03-23 11:23:06 -070080 "If no options are provided, all information is retrieved.\n"
Chengyu Fanee92fc72014-06-21 14:58:19 -060081 "If -x is provided, other options(-v, -c, etc.) are ignored, and all information is printed in XML format.\n"
Alexander Afanasyev60a7ba52014-03-23 11:23:06 -070082 ;
jeraldabrahamb6dde382014-03-19 18:58:09 -070083 }
84
85 void
86 enableVersionRetrieval()
87 {
88 m_needVersionRetrieval = true;
89 }
90
91 void
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +030092 enableChannelStatusRetrieval()
93 {
94 m_needChannelStatusRetrieval = true;
95 }
96
97 void
jeraldabrahamb6dde382014-03-19 18:58:09 -070098 enableFaceStatusRetrieval()
99 {
100 m_needFaceStatusRetrieval = true;
101 }
102
103 void
104 enableFibEnumerationRetrieval()
105 {
106 m_needFibEnumerationRetrieval = true;
107 }
108
109 void
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300110 enableStrategyChoiceRetrieval()
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600111 {
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300112 m_needStrategyChoiceRetrieval = true;
113 }
114
115 void
Chengyu Fan30aa2072014-07-20 13:52:32 -0600116 enableRibStatusRetrieval()
117 {
118 m_needRibStatusRetrieval = true;
119 }
120
121 void
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300122 enableXmlOutput()
123 {
124 m_isOutputXml = true;
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600125 }
126
127 void
jeraldabrahamb6dde382014-03-19 18:58:09 -0700128 onTimeout()
129 {
130 std::cerr << "Request timed out" << std::endl;
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300131
132 runNextStep();
jeraldabrahamb6dde382014-03-19 18:58:09 -0700133 }
134
135 void
136 fetchSegments(const Data& data, void (NfdStatus::*onDone)())
137 {
138 m_buffer->write((const char*)data.getContent().value(),
139 data.getContent().value_size());
140
141 uint64_t currentSegment = data.getName().get(-1).toSegment();
142
143 const name::Component& finalBlockId = data.getMetaInfo().getFinalBlockId();
144 if (finalBlockId.empty() ||
145 finalBlockId.toSegment() > currentSegment)
146 {
147 m_face.expressInterest(data.getName().getPrefix(-1).appendSegment(currentSegment+1),
148 bind(&NfdStatus::fetchSegments, this, _2, onDone),
149 bind(&NfdStatus::onTimeout, this));
150 }
151 else
152 {
153 return (this->*onDone)();
154 }
155 }
156
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300157 void
158 escapeSpecialCharacters(std::string *data)
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600159 {
160 using boost::algorithm::replace_all;
161 replace_all(*data, "&", "&amp;");
162 replace_all(*data, "\"", "&quot;");
163 replace_all(*data, "\'", "&apos;");
164 replace_all(*data, "<", "&lt;");
165 replace_all(*data, ">", "&gt;");
166 }
167
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300168 //////////////////////////////////////////////////////////////////////////////////
169 //////////////////////////////////////////////////////////////////////////////////
170
171 void
172 fetchVersionInformation()
173 {
174 Interest interest("/localhost/nfd/status");
175 interest.setChildSelector(1);
176 interest.setMustBeFresh(true);
177 m_face.expressInterest(
178 interest,
179 bind(&NfdStatus::afterFetchedVersionInformation, this, _2),
180 bind(&NfdStatus::onTimeout, this));
181 }
182
jeraldabrahamb6dde382014-03-19 18:58:09 -0700183 void
184 afterFetchedVersionInformation(const Data& data)
185 {
Junxiao Shi88d69372014-03-28 11:52:39 -0700186 nfd::ForwarderStatus status(data.getContent());
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300187 if (m_isOutputXml)
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600188 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600189 std::cout << "<generalStatus>";
190 std::cout << "<version>"
191 << status.getNfdVersion() << "</version>";
192 std::cout << "<startTime>"
193 << time::toString(status.getStartTimestamp(), "%Y-%m-%dT%H:%M:%S%F")
194 << "</startTime>";
195 std::cout << "<currentTime>"
196 << time::toString(status.getCurrentTimestamp(), "%Y-%m-%dT%H:%M:%S%F")
197 << "</currentTime>";
198 std::cout << "<uptime>PT"
199 << time::duration_cast<time::seconds>(status.getCurrentTimestamp()
200 - status.getStartTimestamp()).count()
201 << "S</uptime>";
202 std::cout << "<nNameTreeEntries>" << status.getNNameTreeEntries()
203 << "</nNameTreeEntries>";
204 std::cout << "<nFibEntries>" << status.getNFibEntries()
205 << "</nFibEntries>";
206 std::cout << "<nPitEntries>" << status.getNPitEntries()
207 << "</nPitEntries>";
208 std::cout << "<nMeasurementsEntries>" << status.getNMeasurementsEntries()
209 << "</nMeasurementsEntries>";
210 std::cout << "<nCsEntries>" << status.getNCsEntries()
211 << "</nCsEntries>";
212 std::cout << "<packetCounters>";
213 std::cout << "<incomingPackets>";
214 std::cout << "<nInterests>" << status.getNInInterests()
215 << "</nInterests>";
216 std::cout << "<nDatas>" << status.getNInDatas()
217 << "</nDatas>";
218 std::cout << "</incomingPackets>";
219 std::cout << "<outgoingPackets>";
220 std::cout << "<nInterests>" << status.getNOutInterests()
221 << "</nInterests>";
222 std::cout << "<nDatas>" << status.getNOutDatas()
223 << "</nDatas>";
224 std::cout << "</outgoingPackets>";
225 std::cout << "</packetCounters>";
226 std::cout << "</generalStatus>";
227 }
228 else
229 {
230 std::cout << "General NFD status:" << std::endl;
231 std::cout << " version="
232 << status.getNfdVersion() << std::endl;
233 std::cout << " startTime="
234 << time::toIsoString(status.getStartTimestamp()) << std::endl;
235 std::cout << " currentTime="
236 << time::toIsoString(status.getCurrentTimestamp()) << std::endl;
237 std::cout << " uptime="
238 << time::duration_cast<time::seconds>(status.getCurrentTimestamp()
239 - status.getStartTimestamp()) << std::endl;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700240
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600241 std::cout << " nNameTreeEntries=" << status.getNNameTreeEntries() << std::endl;
242 std::cout << " nFibEntries=" << status.getNFibEntries() << std::endl;
243 std::cout << " nPitEntries=" << status.getNPitEntries() << std::endl;
244 std::cout << " nMeasurementsEntries=" << status.getNMeasurementsEntries() << std::endl;
245 std::cout << " nCsEntries=" << status.getNCsEntries() << std::endl;
246 std::cout << " nInInterests=" << status.getNInInterests() << std::endl;
247 std::cout << " nOutInterests=" << status.getNOutInterests() << std::endl;
248 std::cout << " nInDatas=" << status.getNInDatas() << std::endl;
249 std::cout << " nOutDatas=" << status.getNOutDatas() << std::endl;
250 }
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300251
252 runNextStep();
253 }
254
255 //////////////////////////////////////////////////////////////////////////////////
256 //////////////////////////////////////////////////////////////////////////////////
257
258 void
259 fetchChannelStatusInformation()
260 {
261 m_buffer = make_shared<OBufferStream>();
262
263 Interest interest("/localhost/nfd/faces/channels");
264 interest.setChildSelector(1);
265 interest.setMustBeFresh(true);
266
267 m_face.expressInterest(interest,
268 bind(&NfdStatus::fetchSegments, this, _2,
269 &NfdStatus::afterFetchedChannelStatusInformation),
270 bind(&NfdStatus::onTimeout, this));
jeraldabrahamb6dde382014-03-19 18:58:09 -0700271 }
272
273 void
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300274 afterFetchedChannelStatusInformation()
jeraldabrahamb6dde382014-03-19 18:58:09 -0700275 {
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300276 ConstBufferPtr buf = m_buffer->buf();
277 if (m_isOutputXml)
278 {
279 std::cout << "<channels>";
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 ChannelStatus TLV" << std::endl;
289 break;
290 }
291
292 offset += block.size();
293
294 nfd::ChannelStatus channelStatus(block);
295
296 std::cout << "<channel>";
297
298 std::string localUri(channelStatus.getLocalUri());
299 escapeSpecialCharacters(&localUri);
300 std::cout << "<localUri>" << localUri << "</localUri>";
301 std::cout << "</channel>";
302 }
303 std::cout << "</channels>";
304 }
305 else
306 {
307 std::cout << "Channels:" << std::endl;
308
309 Block block;
310 size_t offset = 0;
311 while (offset < buf->size())
312 {
313 bool ok = Block::fromBuffer(buf, offset, block);
314 if (!ok)
315 {
316 std::cerr << "ERROR: cannot decode ChannelStatus TLV" << std::endl;
317 break;
318 }
319
320 offset += block.size();
321
322 nfd::ChannelStatus channelStatus(block);
323 std::cout << " " << channelStatus.getLocalUri() << std::endl;
324 }
325 }
326
327 runNextStep();
328 }
329
330 //////////////////////////////////////////////////////////////////////////////////
331 //////////////////////////////////////////////////////////////////////////////////
332
333 void
334 fetchFaceStatusInformation()
335 {
336 m_buffer = make_shared<OBufferStream>();
337
338 Interest interest("/localhost/nfd/faces/list");
jeraldabrahamb6dde382014-03-19 18:58:09 -0700339 interest.setChildSelector(1);
340 interest.setMustBeFresh(true);
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300341
342 m_face.expressInterest(interest,
343 bind(&NfdStatus::fetchSegments, this, _2,
344 &NfdStatus::afterFetchedFaceStatusInformation),
jeraldabrahamb6dde382014-03-19 18:58:09 -0700345 bind(&NfdStatus::onTimeout, this));
346 }
347
348 void
349 afterFetchedFaceStatusInformation()
350 {
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700351 ConstBufferPtr buf = m_buffer->buf();
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300352 if (m_isOutputXml)
jeraldabrahamb6dde382014-03-19 18:58:09 -0700353 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600354 std::cout << "<faces>";
355
356 Block block;
357 size_t offset = 0;
358 while (offset < buf->size())
jeraldabrahamb6dde382014-03-19 18:58:09 -0700359 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600360 bool ok = Block::fromBuffer(buf, offset, block);
361 if (!ok)
362 {
363 std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
364 break;
365 }
366
367 offset += block.size();
368
369 nfd::FaceStatus faceStatus(block);
370
371 std::cout << "<face>";
372 std::cout << "<faceId>" << faceStatus.getFaceId() << "</faceId>";
373
374 std::string remoteUri(faceStatus.getRemoteUri());
375 escapeSpecialCharacters(&remoteUri);
376 std::cout << "<remoteUri>" << remoteUri << "</remoteUri>";
377
378 std::string localUri(faceStatus.getLocalUri());
379 escapeSpecialCharacters(&localUri);
380 std::cout << "<localUri>" << localUri << "</localUri>";
Alexander Afanasyev40c61f72014-06-30 17:21:01 -0700381
382 if (faceStatus.hasExpirationPeriod()) {
383 std::cout << "<expirationPeriod>PT"
384 << time::duration_cast<time::seconds>(faceStatus.getExpirationPeriod())
385 .count() << "S"
386 << "</expirationPeriod>";
387 }
388
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600389 std::cout << "<packetCounters>";
390 std::cout << "<incomingPackets>";
391 std::cout << "<nInterests>" << faceStatus.getNInInterests()
392 << "</nInterests>";
Chengyu Fan30aa2072014-07-20 13:52:32 -0600393 std::cout << "<nDatas>" << faceStatus.getNInDatas()
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600394 << "</nDatas>";
395 std::cout << "</incomingPackets>";
396 std::cout << "<outgoingPackets>";
397 std::cout << "<nInterests>" << faceStatus.getNOutInterests()
398 << "</nInterests>";
Chengyu Fan30aa2072014-07-20 13:52:32 -0600399 std::cout << "<nDatas>" << faceStatus.getNOutDatas()
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600400 << "</nDatas>";
401 std::cout << "</outgoingPackets>";
402 std::cout << "</packetCounters>";
Alexander Afanasyevd3967a22014-06-30 12:22:10 -0700403
404 if (faceStatus.getFlags() != 0) {
405 std::cout << "<flags>";
406 if (faceStatus.isLocal()) {
407 std::cout << "<local/>";
408 }
409 if (faceStatus.isOnDemand()) {
410 std::cout << "<on-demand/>";
411 }
412 std::cout << "</flags>";
413 }
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600414 std::cout << "</face>";
jeraldabrahamb6dde382014-03-19 18:58:09 -0700415 }
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600416 std::cout << "</faces>";
jeraldabrahamb6dde382014-03-19 18:58:09 -0700417 }
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600418 else
419 {
420 std::cout << "Faces:" << std::endl;
421
422 Block block;
423 size_t offset = 0;
424 while (offset < buf->size())
425 {
426 bool ok = Block::fromBuffer(buf, offset, block);
427 if (!ok)
428 {
429 std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
430 break;
431 }
432
433 offset += block.size();
434
435 nfd::FaceStatus faceStatus(block);
436
437 std::cout << " faceid=" << faceStatus.getFaceId()
438 << " remote=" << faceStatus.getRemoteUri()
Alexander Afanasyev40c61f72014-06-30 17:21:01 -0700439 << " local=" << faceStatus.getLocalUri();
440 if (faceStatus.hasExpirationPeriod()) {
441 std::cout << " expires="
442 << time::duration_cast<time::seconds>(faceStatus.getExpirationPeriod())
443 .count() << "s";
444 }
445 std::cout << " counters={"
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600446 << "in={" << faceStatus.getNInInterests() << "i "
447 << faceStatus.getNInDatas() << "d}"
448 << " out={" << faceStatus.getNOutInterests() << "i "
449 << faceStatus.getNOutDatas() << "d}"
Alexander Afanasyevd3967a22014-06-30 12:22:10 -0700450 << "}";
451 if (faceStatus.isLocal())
452 std::cout << " local";
453 if (faceStatus.isOnDemand())
454 std::cout << " on-demand";
455 std::cout << std::endl;
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600456 }
457 }
jeraldabrahamb6dde382014-03-19 18:58:09 -0700458
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300459 runNextStep();
jeraldabrahamb6dde382014-03-19 18:58:09 -0700460 }
461
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300462 //////////////////////////////////////////////////////////////////////////////////
463 //////////////////////////////////////////////////////////////////////////////////
464
jeraldabrahamb6dde382014-03-19 18:58:09 -0700465 void
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300466 fetchFibEnumerationInformation()
jeraldabrahamb6dde382014-03-19 18:58:09 -0700467 {
468 m_buffer = make_shared<OBufferStream>();
469
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300470 Interest interest("/localhost/nfd/fib/list");
jeraldabrahamb6dde382014-03-19 18:58:09 -0700471 interest.setChildSelector(1);
472 interest.setMustBeFresh(true);
jeraldabrahamb6dde382014-03-19 18:58:09 -0700473 m_face.expressInterest(interest,
474 bind(&NfdStatus::fetchSegments, this, _2,
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300475 &NfdStatus::afterFetchedFibEnumerationInformation),
jeraldabrahamb6dde382014-03-19 18:58:09 -0700476 bind(&NfdStatus::onTimeout, this));
477 }
478
479 void
480 afterFetchedFibEnumerationInformation()
481 {
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700482 ConstBufferPtr buf = m_buffer->buf();
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300483 if (m_isOutputXml)
jeraldabrahamb6dde382014-03-19 18:58:09 -0700484 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600485 std::cout << "<fib>";
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700486
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600487 Block block;
488 size_t offset = 0;
489 while (offset < buf->size())
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700490 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600491 bool ok = Block::fromBuffer(buf, offset, block);
492 if (!ok)
493 {
494 std::cerr << "ERROR: cannot decode FibEntry TLV";
495 break;
496 }
497 offset += block.size();
498
499 nfd::FibEntry fibEntry(block);
500
501 std::cout << "<fibEntry>";
502 std::string prefix(fibEntry.getPrefix().toUri());
503 escapeSpecialCharacters(&prefix);
504 std::cout << "<prefix>" << prefix << "</prefix>";
505 std::cout << "<nextHops>";
506 for (std::list<nfd::NextHopRecord>::const_iterator
507 nextHop = fibEntry.getNextHopRecords().begin();
508 nextHop != fibEntry.getNextHopRecords().end();
509 ++nextHop)
510 {
511 std::cout << "<nextHop>" ;
512 std::cout << "<faceId>" << nextHop->getFaceId() << "</faceId>";
513 std::cout << "<cost>" << nextHop->getCost() << "</cost>";
514 std::cout << "</nextHop>";
515 }
516 std::cout << "</nextHops>";
517 std::cout << "</fibEntry>";
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700518 }
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600519
520 std::cout << "</fib>";
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600521 }
522 else
523 {
524 std::cout << "FIB:" << std::endl;
525
526 Block block;
527 size_t offset = 0;
528 while (offset < buf->size())
529 {
530 bool ok = Block::fromBuffer(buf, offset, block);
531 if (!ok)
532 {
533 std::cerr << "ERROR: cannot decode FibEntry TLV" << std::endl;
534 break;
535 }
536 offset += block.size();
537
538 nfd::FibEntry fibEntry(block);
539
540 std::cout << " " << fibEntry.getPrefix() << " nexthops={";
541 for (std::list<nfd::NextHopRecord>::const_iterator
542 nextHop = fibEntry.getNextHopRecords().begin();
543 nextHop != fibEntry.getNextHopRecords().end();
544 ++nextHop)
545 {
546 if (nextHop != fibEntry.getNextHopRecords().begin())
547 std::cout << ", ";
548 std::cout << "faceid=" << nextHop->getFaceId()
549 << " (cost=" << nextHop->getCost() << ")";
550 }
551 std::cout << "}" << std::endl;
552 }
jeraldabrahamb6dde382014-03-19 18:58:09 -0700553 }
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300554
555 runNextStep();
jeraldabrahamb6dde382014-03-19 18:58:09 -0700556 }
557
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300558 //////////////////////////////////////////////////////////////////////////////////
559 //////////////////////////////////////////////////////////////////////////////////
560
jeraldabrahamb6dde382014-03-19 18:58:09 -0700561 void
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300562 fetchStrategyChoiceInformation()
jeraldabrahamb6dde382014-03-19 18:58:09 -0700563 {
564 m_buffer = make_shared<OBufferStream>();
565
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300566 Interest interest("/localhost/nfd/strategy-choice/list");
jeraldabrahamb6dde382014-03-19 18:58:09 -0700567 interest.setChildSelector(1);
568 interest.setMustBeFresh(true);
569 m_face.expressInterest(interest,
570 bind(&NfdStatus::fetchSegments, this, _2,
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300571 &NfdStatus::afterFetchedStrategyChoiceInformationInformation),
jeraldabrahamb6dde382014-03-19 18:58:09 -0700572 bind(&NfdStatus::onTimeout, this));
573 }
574
575 void
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300576 afterFetchedStrategyChoiceInformationInformation()
577 {
578 ConstBufferPtr buf = m_buffer->buf();
579 if (m_isOutputXml)
580 {
581 std::cout << "<strategyChoices>";
582
583 Block block;
584 size_t offset = 0;
585 while (offset < buf->size())
586 {
587 bool ok = Block::fromBuffer(buf, offset, block);
588 if (!ok)
589 {
590 std::cerr << "ERROR: cannot decode StrategyChoice TLV";
591 break;
592 }
593 offset += block.size();
594
595 nfd::StrategyChoice strategyChoice(block);
596
597 std::cout << "<strategyChoice>";
598
599 std::string name(strategyChoice.getName().toUri());
600 escapeSpecialCharacters(&name);
601 std::cout << "<namespace>" << name << "</namespace>";
602 std::cout << "<strategy>";
603
604 std::string strategy(strategyChoice.getStrategy().toUri());
605 escapeSpecialCharacters(&strategy);
606
607 std::cout << "<name>" << strategy << "</name>";
608 std::cout << "</strategy>";
609 std::cout << "</strategyChoice>";
610 }
611
612 std::cout << "</strategyChoices>";
613 }
614 else
615 {
616 std::cout << "Strategy choices:" << std::endl;
617
618 Block block;
619 size_t offset = 0;
620 while (offset < buf->size())
621 {
622 bool ok = Block::fromBuffer(buf, offset, block);
623 if (!ok)
624 {
625 std::cerr << "ERROR: cannot decode StrategyChoice TLV" << std::endl;
626 break;
627 }
628 offset += block.size();
629
630 nfd::StrategyChoice strategyChoice(block);
631
632 std::cout << " " << strategyChoice.getName()
633 << " strategy=" << strategyChoice.getStrategy() << std::endl;
634 }
635 }
636
637 runNextStep();
638 }
639
640 void
Chengyu Fan30aa2072014-07-20 13:52:32 -0600641 fetchRibStatusInformation()
642 {
643 m_buffer = make_shared<OBufferStream>();
644
645 Interest interest("/localhost/nfd/rib/list");
646 interest.setChildSelector(1);
647 interest.setMustBeFresh(true);
648
649 m_face.expressInterest(interest,
650 bind(&NfdStatus::fetchSegments, this, _2,
651 &NfdStatus::afterFetchedRibStatusInformation),
652 bind(&NfdStatus::onTimeout, this));
653 }
654
655 void
656 afterFetchedRibStatusInformation()
657 {
658 ConstBufferPtr buf = m_buffer->buf();
659 if (m_isOutputXml)
660 {
661 std::cout << "<rib>";
662
663 Block block;
664 size_t offset = 0;
665 while (offset < buf->size())
666 {
667 bool ok = Block::fromBuffer(buf, offset, block);
668 if (!ok)
669 {
670 std::cerr << "ERROR: cannot decode RibEntry TLV";
671 break;
672 }
673 offset += block.size();
674
675 nfd::RibEntry ribEntry(block);
676
677 std::cout << "<ribEntry>";
678 std::string prefix(ribEntry.getName().toUri());
679 escapeSpecialCharacters(&prefix);
680 std::cout << "<prefix>" << prefix << "</prefix>";
681 std::cout << "<routes>";
682 for (std::list<nfd::Route>::const_iterator
683 nextRoute = ribEntry.begin();
684 nextRoute != ribEntry.end();
685 ++nextRoute)
686 {
687 std::cout << "<route>" ;
688 std::cout << "<faceId>" << nextRoute->getFaceId() << "</faceId>";
689 std::cout << "<origin>" << nextRoute->getOrigin() << "</origin>";
690 std::cout << "<cost>" << nextRoute->getCost() << "</cost>";
691 std::cout << "<flags>" << nextRoute->getFlags() << "</flags>";
692 if (!nextRoute->hasInfiniteExpirationPeriod()) {
693 std::cout << "<expirationPeriod>PT"
694 << time::duration_cast<time::seconds>(nextRoute->getExpirationPeriod())
695 .count() << "S"
696 << "</expirationPeriod>";
697 }
698 std::cout << "</route>";
699 }
700 std::cout << "</routes>";
701 std::cout << "</ribEntry>";
702 }
703
704 std::cout << "</rib>";
705 }
706 else
707 {
708 std::cout << "Rib:" << std::endl;
709
710 Block block;
711 size_t offset = 0;
712 while (offset < buf->size())
713 {
714 bool ok = Block::fromBuffer(buf, offset, block);
715 if (!ok)
716 {
717 std::cerr << "ERROR: cannot decode RibEntry TLV" << std::endl;
718 break;
719 }
720
721 offset += block.size();
722
723 nfd::RibEntry ribEntry(block);
724
725 std::cout << " " << ribEntry.getName().toUri() << " route={";
726 for (std::list<nfd::Route>::const_iterator
727 nextRoute = ribEntry.begin();
728 nextRoute != ribEntry.end();
729 ++nextRoute)
730 {
731 if (nextRoute != ribEntry.begin())
732 std::cout << ", ";
733 std::cout << "faceid=" << nextRoute->getFaceId()
734 << " (origin=" << nextRoute->getOrigin()
735 << " cost=" << nextRoute->getCost()
736 << " flags=" << nextRoute->getFlags();
737 if (!nextRoute->hasInfiniteExpirationPeriod()) {
738 std::cout << " expires="
739 << time::duration_cast<time::seconds>(nextRoute->getExpirationPeriod())
740 .count() << "s";
741 }
742 std::cout << ")";
743 }
744 std::cout << "}" << std::endl;
745 }
746 }
747
748 runNextStep();
749 }
750
751
752 void
jeraldabrahamb6dde382014-03-19 18:58:09 -0700753 fetchInformation()
754 {
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300755 if (m_isOutputXml ||
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600756 (!m_needVersionRetrieval &&
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300757 !m_needChannelStatusRetrieval &&
758 !m_needFaceStatusRetrieval &&
759 !m_needFibEnumerationRetrieval &&
Chengyu Fan30aa2072014-07-20 13:52:32 -0600760 !m_needRibStatusRetrieval &&
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300761 !m_needStrategyChoiceRetrieval))
jeraldabrahamb6dde382014-03-19 18:58:09 -0700762 {
763 enableVersionRetrieval();
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300764 enableChannelStatusRetrieval();
jeraldabrahamb6dde382014-03-19 18:58:09 -0700765 enableFaceStatusRetrieval();
766 enableFibEnumerationRetrieval();
Chengyu Fan30aa2072014-07-20 13:52:32 -0600767 enableRibStatusRetrieval();
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300768 enableStrategyChoiceRetrieval();
jeraldabrahamb6dde382014-03-19 18:58:09 -0700769 }
770
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300771 if (m_isOutputXml)
772 m_fetchSteps.push_back(bind(&NfdStatus::printXmlHeader, this));
773
jeraldabrahamb6dde382014-03-19 18:58:09 -0700774 if (m_needVersionRetrieval)
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300775 m_fetchSteps.push_back(bind(&NfdStatus::fetchVersionInformation, this));
jeraldabrahamb6dde382014-03-19 18:58:09 -0700776
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300777 if (m_needChannelStatusRetrieval)
778 m_fetchSteps.push_back(bind(&NfdStatus::fetchChannelStatusInformation, this));
779
780 if (m_needFaceStatusRetrieval)
781 m_fetchSteps.push_back(bind(&NfdStatus::fetchFaceStatusInformation, this));
782
783 if (m_needFibEnumerationRetrieval)
784 m_fetchSteps.push_back(bind(&NfdStatus::fetchFibEnumerationInformation, this));
785
Chengyu Fan30aa2072014-07-20 13:52:32 -0600786 if (m_needRibStatusRetrieval)
787 m_fetchSteps.push_back(bind(&NfdStatus::fetchRibStatusInformation, this));
788
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300789 if (m_needStrategyChoiceRetrieval)
790 m_fetchSteps.push_back(bind(&NfdStatus::fetchStrategyChoiceInformation, this));
791
792 if (m_isOutputXml)
793 m_fetchSteps.push_back(bind(&NfdStatus::printXmlFooter, this));
794
795 runNextStep();
jeraldabrahamb6dde382014-03-19 18:58:09 -0700796 m_face.processEvents();
797 }
798
799private:
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300800 void
801 printXmlHeader()
802 {
803 std::cout << "<?xml version=\"1.0\"?>";
804 std::cout << "<nfdStatus xmlns=\"ndn:/localhost/nfd/status/1\">";
805
806 runNextStep();
807 }
808
809 void
810 printXmlFooter()
811 {
812 std::cout << "</nfdStatus>";
813
814 runNextStep();
815 }
816
817 void
818 runNextStep()
819 {
820 if (m_fetchSteps.empty())
821 return;
822
823 function<void()> nextStep = m_fetchSteps.front();
824 m_fetchSteps.pop_front();
825 nextStep();
826 }
827
828private:
jeraldabrahamb6dde382014-03-19 18:58:09 -0700829 std::string m_toolName;
830 bool m_needVersionRetrieval;
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300831 bool m_needChannelStatusRetrieval;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700832 bool m_needFaceStatusRetrieval;
833 bool m_needFibEnumerationRetrieval;
Chengyu Fan30aa2072014-07-20 13:52:32 -0600834 bool m_needRibStatusRetrieval;
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300835 bool m_needStrategyChoiceRetrieval;
836 bool m_isOutputXml;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700837 Face m_face;
838
839 shared_ptr<OBufferStream> m_buffer;
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300840
841 std::deque<function<void()> > m_fetchSteps;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700842};
843
844}
845
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700846int main(int argc, char* argv[])
jeraldabrahamb6dde382014-03-19 18:58:09 -0700847{
848 int option;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700849 ndn::NfdStatus nfdStatus(argv[0]);
jeraldabrahamb6dde382014-03-19 18:58:09 -0700850
Chengyu Fan30aa2072014-07-20 13:52:32 -0600851 while ((option = getopt(argc, argv, "hvcfbrsxV")) != -1) {
jeraldabrahamb6dde382014-03-19 18:58:09 -0700852 switch (option) {
853 case 'h':
854 nfdStatus.usage();
Alexander Afanasyev60a7ba52014-03-23 11:23:06 -0700855 return 0;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700856 case 'v':
857 nfdStatus.enableVersionRetrieval();
858 break;
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300859 case 'c':
860 nfdStatus.enableChannelStatusRetrieval();
861 break;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700862 case 'f':
863 nfdStatus.enableFaceStatusRetrieval();
864 break;
865 case 'b':
866 nfdStatus.enableFibEnumerationRetrieval();
867 break;
Chengyu Fan30aa2072014-07-20 13:52:32 -0600868 case 'r':
869 nfdStatus.enableRibStatusRetrieval();
870 break;
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300871 case 's':
872 nfdStatus.enableStrategyChoiceRetrieval();
873 break;
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600874 case 'x':
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300875 nfdStatus.enableXmlOutput();
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600876 break;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700877 case 'V':
878 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
879 return 0;
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700880 default:
jeraldabrahamb6dde382014-03-19 18:58:09 -0700881 nfdStatus.usage();
882 return 1;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700883 }
884 }
885
886 try {
887 nfdStatus.fetchInformation();
888 }
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700889 catch (std::exception& e) {
jeraldabrahamb6dde382014-03-19 18:58:09 -0700890 std::cerr << "ERROR: " << e.what() << std::endl;
891 return 2;
892 }
893
894 return 0;
895}