blob: 42a35be69c6043f1c92599c5b6bcfc430c10d9f0 [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());
Chengyu Fan8a53caf2014-08-01 14:08:37 -0600187 std::string nfdId;
188 if (data.getSignature().hasKeyLocator())
189 {
190 const ndn::KeyLocator& locator = data.getSignature().getKeyLocator();
191 if (locator.getType() == KeyLocator::KeyLocator_Name)
192 nfdId = locator.getName().toUri();
193 //todo: KeyDigest supporting
194 }
195
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300196 if (m_isOutputXml)
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600197 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600198 std::cout << "<generalStatus>";
Chengyu Fan8a53caf2014-08-01 14:08:37 -0600199 std::cout << "<nfdId>"
200 << nfdId << "</nfdId>";
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600201 std::cout << "<version>"
202 << status.getNfdVersion() << "</version>";
203 std::cout << "<startTime>"
204 << time::toString(status.getStartTimestamp(), "%Y-%m-%dT%H:%M:%S%F")
205 << "</startTime>";
206 std::cout << "<currentTime>"
207 << time::toString(status.getCurrentTimestamp(), "%Y-%m-%dT%H:%M:%S%F")
208 << "</currentTime>";
209 std::cout << "<uptime>PT"
210 << time::duration_cast<time::seconds>(status.getCurrentTimestamp()
211 - status.getStartTimestamp()).count()
212 << "S</uptime>";
213 std::cout << "<nNameTreeEntries>" << status.getNNameTreeEntries()
214 << "</nNameTreeEntries>";
215 std::cout << "<nFibEntries>" << status.getNFibEntries()
216 << "</nFibEntries>";
217 std::cout << "<nPitEntries>" << status.getNPitEntries()
218 << "</nPitEntries>";
219 std::cout << "<nMeasurementsEntries>" << status.getNMeasurementsEntries()
220 << "</nMeasurementsEntries>";
221 std::cout << "<nCsEntries>" << status.getNCsEntries()
222 << "</nCsEntries>";
223 std::cout << "<packetCounters>";
224 std::cout << "<incomingPackets>";
225 std::cout << "<nInterests>" << status.getNInInterests()
226 << "</nInterests>";
227 std::cout << "<nDatas>" << status.getNInDatas()
228 << "</nDatas>";
229 std::cout << "</incomingPackets>";
230 std::cout << "<outgoingPackets>";
231 std::cout << "<nInterests>" << status.getNOutInterests()
232 << "</nInterests>";
233 std::cout << "<nDatas>" << status.getNOutDatas()
234 << "</nDatas>";
235 std::cout << "</outgoingPackets>";
236 std::cout << "</packetCounters>";
237 std::cout << "</generalStatus>";
238 }
239 else
240 {
241 std::cout << "General NFD status:" << std::endl;
Chengyu Fan8a53caf2014-08-01 14:08:37 -0600242 std::cout << " nfdId="
243 << nfdId << std::endl;
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600244 std::cout << " version="
245 << status.getNfdVersion() << std::endl;
246 std::cout << " startTime="
247 << time::toIsoString(status.getStartTimestamp()) << std::endl;
248 std::cout << " currentTime="
249 << time::toIsoString(status.getCurrentTimestamp()) << std::endl;
250 std::cout << " uptime="
251 << time::duration_cast<time::seconds>(status.getCurrentTimestamp()
252 - status.getStartTimestamp()) << std::endl;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700253
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600254 std::cout << " nNameTreeEntries=" << status.getNNameTreeEntries() << std::endl;
255 std::cout << " nFibEntries=" << status.getNFibEntries() << std::endl;
256 std::cout << " nPitEntries=" << status.getNPitEntries() << std::endl;
257 std::cout << " nMeasurementsEntries=" << status.getNMeasurementsEntries() << std::endl;
258 std::cout << " nCsEntries=" << status.getNCsEntries() << std::endl;
259 std::cout << " nInInterests=" << status.getNInInterests() << std::endl;
260 std::cout << " nOutInterests=" << status.getNOutInterests() << std::endl;
261 std::cout << " nInDatas=" << status.getNInDatas() << std::endl;
262 std::cout << " nOutDatas=" << status.getNOutDatas() << std::endl;
263 }
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300264
265 runNextStep();
266 }
267
268 //////////////////////////////////////////////////////////////////////////////////
269 //////////////////////////////////////////////////////////////////////////////////
270
271 void
272 fetchChannelStatusInformation()
273 {
274 m_buffer = make_shared<OBufferStream>();
275
276 Interest interest("/localhost/nfd/faces/channels");
277 interest.setChildSelector(1);
278 interest.setMustBeFresh(true);
279
280 m_face.expressInterest(interest,
281 bind(&NfdStatus::fetchSegments, this, _2,
282 &NfdStatus::afterFetchedChannelStatusInformation),
283 bind(&NfdStatus::onTimeout, this));
jeraldabrahamb6dde382014-03-19 18:58:09 -0700284 }
285
286 void
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300287 afterFetchedChannelStatusInformation()
jeraldabrahamb6dde382014-03-19 18:58:09 -0700288 {
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300289 ConstBufferPtr buf = m_buffer->buf();
290 if (m_isOutputXml)
291 {
292 std::cout << "<channels>";
293
294 Block block;
295 size_t offset = 0;
296 while (offset < buf->size())
297 {
298 bool ok = Block::fromBuffer(buf, offset, block);
299 if (!ok)
300 {
301 std::cerr << "ERROR: cannot decode ChannelStatus TLV" << std::endl;
302 break;
303 }
304
305 offset += block.size();
306
307 nfd::ChannelStatus channelStatus(block);
308
309 std::cout << "<channel>";
310
311 std::string localUri(channelStatus.getLocalUri());
312 escapeSpecialCharacters(&localUri);
313 std::cout << "<localUri>" << localUri << "</localUri>";
314 std::cout << "</channel>";
315 }
316 std::cout << "</channels>";
317 }
318 else
319 {
320 std::cout << "Channels:" << std::endl;
321
322 Block block;
323 size_t offset = 0;
324 while (offset < buf->size())
325 {
326 bool ok = Block::fromBuffer(buf, offset, block);
327 if (!ok)
328 {
329 std::cerr << "ERROR: cannot decode ChannelStatus TLV" << std::endl;
330 break;
331 }
332
333 offset += block.size();
334
335 nfd::ChannelStatus channelStatus(block);
336 std::cout << " " << channelStatus.getLocalUri() << std::endl;
337 }
338 }
339
340 runNextStep();
341 }
342
343 //////////////////////////////////////////////////////////////////////////////////
344 //////////////////////////////////////////////////////////////////////////////////
345
346 void
347 fetchFaceStatusInformation()
348 {
349 m_buffer = make_shared<OBufferStream>();
350
351 Interest interest("/localhost/nfd/faces/list");
jeraldabrahamb6dde382014-03-19 18:58:09 -0700352 interest.setChildSelector(1);
353 interest.setMustBeFresh(true);
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300354
355 m_face.expressInterest(interest,
356 bind(&NfdStatus::fetchSegments, this, _2,
357 &NfdStatus::afterFetchedFaceStatusInformation),
jeraldabrahamb6dde382014-03-19 18:58:09 -0700358 bind(&NfdStatus::onTimeout, this));
359 }
360
361 void
362 afterFetchedFaceStatusInformation()
363 {
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700364 ConstBufferPtr buf = m_buffer->buf();
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300365 if (m_isOutputXml)
jeraldabrahamb6dde382014-03-19 18:58:09 -0700366 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600367 std::cout << "<faces>";
368
369 Block block;
370 size_t offset = 0;
371 while (offset < buf->size())
jeraldabrahamb6dde382014-03-19 18:58:09 -0700372 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600373 bool ok = Block::fromBuffer(buf, offset, block);
374 if (!ok)
375 {
376 std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
377 break;
378 }
379
380 offset += block.size();
381
382 nfd::FaceStatus faceStatus(block);
383
384 std::cout << "<face>";
385 std::cout << "<faceId>" << faceStatus.getFaceId() << "</faceId>";
386
387 std::string remoteUri(faceStatus.getRemoteUri());
388 escapeSpecialCharacters(&remoteUri);
389 std::cout << "<remoteUri>" << remoteUri << "</remoteUri>";
390
391 std::string localUri(faceStatus.getLocalUri());
392 escapeSpecialCharacters(&localUri);
393 std::cout << "<localUri>" << localUri << "</localUri>";
Alexander Afanasyev40c61f72014-06-30 17:21:01 -0700394
395 if (faceStatus.hasExpirationPeriod()) {
396 std::cout << "<expirationPeriod>PT"
397 << time::duration_cast<time::seconds>(faceStatus.getExpirationPeriod())
398 .count() << "S"
399 << "</expirationPeriod>";
400 }
401
Chengyu Fan27d570a2014-10-09 11:52:17 -0600402 std::cout << "<faceScope>" << faceStatus.getFaceScope()
403 << "</faceScope>";
404 std::cout << "<facePersistency>" << faceStatus.getFacePersistency()
405 << "</facePersistency>";
406 std::cout << "<linkType>" << faceStatus.getLinkType()
407 << "</linkType>";
408
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600409 std::cout << "<packetCounters>";
410 std::cout << "<incomingPackets>";
411 std::cout << "<nInterests>" << faceStatus.getNInInterests()
412 << "</nInterests>";
Chengyu Fan30aa2072014-07-20 13:52:32 -0600413 std::cout << "<nDatas>" << faceStatus.getNInDatas()
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600414 << "</nDatas>";
415 std::cout << "</incomingPackets>";
416 std::cout << "<outgoingPackets>";
417 std::cout << "<nInterests>" << faceStatus.getNOutInterests()
418 << "</nInterests>";
Chengyu Fan30aa2072014-07-20 13:52:32 -0600419 std::cout << "<nDatas>" << faceStatus.getNOutDatas()
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600420 << "</nDatas>";
421 std::cout << "</outgoingPackets>";
422 std::cout << "</packetCounters>";
Alexander Afanasyevd3967a22014-06-30 12:22:10 -0700423
Chengyu Fan3331cfa2014-07-25 17:36:31 -0600424 std::cout << "<byteCounters>";
425 std::cout << "<incomingBytes>" << faceStatus.getNInBytes()
426 << "</incomingBytes>";
427 std::cout << "<outgoingBytes>" << faceStatus.getNOutBytes()
428 << "</outgoingBytes>";
429 std::cout << "</byteCounters>";
430
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600431 std::cout << "</face>";
jeraldabrahamb6dde382014-03-19 18:58:09 -0700432 }
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600433 std::cout << "</faces>";
jeraldabrahamb6dde382014-03-19 18:58:09 -0700434 }
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600435 else
436 {
437 std::cout << "Faces:" << std::endl;
438
439 Block block;
440 size_t offset = 0;
441 while (offset < buf->size())
442 {
443 bool ok = Block::fromBuffer(buf, offset, block);
444 if (!ok)
445 {
446 std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
447 break;
448 }
449
450 offset += block.size();
451
452 nfd::FaceStatus faceStatus(block);
453
454 std::cout << " faceid=" << faceStatus.getFaceId()
455 << " remote=" << faceStatus.getRemoteUri()
Alexander Afanasyev40c61f72014-06-30 17:21:01 -0700456 << " local=" << faceStatus.getLocalUri();
457 if (faceStatus.hasExpirationPeriod()) {
458 std::cout << " expires="
459 << time::duration_cast<time::seconds>(faceStatus.getExpirationPeriod())
460 .count() << "s";
461 }
462 std::cout << " counters={"
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600463 << "in={" << faceStatus.getNInInterests() << "i "
Chengyu Fan3331cfa2014-07-25 17:36:31 -0600464 << faceStatus.getNInDatas() << "d "
465 << faceStatus.getNInBytes() << "B}"
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600466 << " out={" << faceStatus.getNOutInterests() << "i "
Chengyu Fan3331cfa2014-07-25 17:36:31 -0600467 << faceStatus.getNOutDatas() << "d "
468 << faceStatus.getNOutBytes() << "B}"
Alexander Afanasyevd3967a22014-06-30 12:22:10 -0700469 << "}";
Chengyu Fan27d570a2014-10-09 11:52:17 -0600470 std::cout << " " << faceStatus.getFaceScope()
471 << " " << faceStatus.getFacePersistency()
472 << " " << faceStatus.getLinkType();
Alexander Afanasyevd3967a22014-06-30 12:22:10 -0700473 std::cout << std::endl;
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600474 }
475 }
jeraldabrahamb6dde382014-03-19 18:58:09 -0700476
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300477 runNextStep();
jeraldabrahamb6dde382014-03-19 18:58:09 -0700478 }
479
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300480 //////////////////////////////////////////////////////////////////////////////////
481 //////////////////////////////////////////////////////////////////////////////////
482
jeraldabrahamb6dde382014-03-19 18:58:09 -0700483 void
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300484 fetchFibEnumerationInformation()
jeraldabrahamb6dde382014-03-19 18:58:09 -0700485 {
486 m_buffer = make_shared<OBufferStream>();
487
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300488 Interest interest("/localhost/nfd/fib/list");
jeraldabrahamb6dde382014-03-19 18:58:09 -0700489 interest.setChildSelector(1);
490 interest.setMustBeFresh(true);
jeraldabrahamb6dde382014-03-19 18:58:09 -0700491 m_face.expressInterest(interest,
492 bind(&NfdStatus::fetchSegments, this, _2,
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300493 &NfdStatus::afterFetchedFibEnumerationInformation),
jeraldabrahamb6dde382014-03-19 18:58:09 -0700494 bind(&NfdStatus::onTimeout, this));
495 }
496
497 void
498 afterFetchedFibEnumerationInformation()
499 {
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700500 ConstBufferPtr buf = m_buffer->buf();
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300501 if (m_isOutputXml)
jeraldabrahamb6dde382014-03-19 18:58:09 -0700502 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600503 std::cout << "<fib>";
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700504
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600505 Block block;
506 size_t offset = 0;
507 while (offset < buf->size())
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700508 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600509 bool ok = Block::fromBuffer(buf, offset, block);
510 if (!ok)
511 {
512 std::cerr << "ERROR: cannot decode FibEntry TLV";
513 break;
514 }
515 offset += block.size();
516
517 nfd::FibEntry fibEntry(block);
518
519 std::cout << "<fibEntry>";
520 std::string prefix(fibEntry.getPrefix().toUri());
521 escapeSpecialCharacters(&prefix);
522 std::cout << "<prefix>" << prefix << "</prefix>";
523 std::cout << "<nextHops>";
524 for (std::list<nfd::NextHopRecord>::const_iterator
525 nextHop = fibEntry.getNextHopRecords().begin();
526 nextHop != fibEntry.getNextHopRecords().end();
527 ++nextHop)
528 {
529 std::cout << "<nextHop>" ;
530 std::cout << "<faceId>" << nextHop->getFaceId() << "</faceId>";
531 std::cout << "<cost>" << nextHop->getCost() << "</cost>";
532 std::cout << "</nextHop>";
533 }
534 std::cout << "</nextHops>";
535 std::cout << "</fibEntry>";
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700536 }
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600537
538 std::cout << "</fib>";
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600539 }
540 else
541 {
542 std::cout << "FIB:" << std::endl;
543
544 Block block;
545 size_t offset = 0;
546 while (offset < buf->size())
547 {
548 bool ok = Block::fromBuffer(buf, offset, block);
549 if (!ok)
550 {
551 std::cerr << "ERROR: cannot decode FibEntry TLV" << std::endl;
552 break;
553 }
554 offset += block.size();
555
556 nfd::FibEntry fibEntry(block);
557
558 std::cout << " " << fibEntry.getPrefix() << " nexthops={";
559 for (std::list<nfd::NextHopRecord>::const_iterator
560 nextHop = fibEntry.getNextHopRecords().begin();
561 nextHop != fibEntry.getNextHopRecords().end();
562 ++nextHop)
563 {
564 if (nextHop != fibEntry.getNextHopRecords().begin())
565 std::cout << ", ";
566 std::cout << "faceid=" << nextHop->getFaceId()
567 << " (cost=" << nextHop->getCost() << ")";
568 }
569 std::cout << "}" << std::endl;
570 }
jeraldabrahamb6dde382014-03-19 18:58:09 -0700571 }
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300572
573 runNextStep();
jeraldabrahamb6dde382014-03-19 18:58:09 -0700574 }
575
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300576 //////////////////////////////////////////////////////////////////////////////////
577 //////////////////////////////////////////////////////////////////////////////////
578
jeraldabrahamb6dde382014-03-19 18:58:09 -0700579 void
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300580 fetchStrategyChoiceInformation()
jeraldabrahamb6dde382014-03-19 18:58:09 -0700581 {
582 m_buffer = make_shared<OBufferStream>();
583
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300584 Interest interest("/localhost/nfd/strategy-choice/list");
jeraldabrahamb6dde382014-03-19 18:58:09 -0700585 interest.setChildSelector(1);
586 interest.setMustBeFresh(true);
587 m_face.expressInterest(interest,
588 bind(&NfdStatus::fetchSegments, this, _2,
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300589 &NfdStatus::afterFetchedStrategyChoiceInformationInformation),
jeraldabrahamb6dde382014-03-19 18:58:09 -0700590 bind(&NfdStatus::onTimeout, this));
591 }
592
593 void
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300594 afterFetchedStrategyChoiceInformationInformation()
595 {
596 ConstBufferPtr buf = m_buffer->buf();
597 if (m_isOutputXml)
598 {
599 std::cout << "<strategyChoices>";
600
601 Block block;
602 size_t offset = 0;
603 while (offset < buf->size())
604 {
605 bool ok = Block::fromBuffer(buf, offset, block);
606 if (!ok)
607 {
608 std::cerr << "ERROR: cannot decode StrategyChoice TLV";
609 break;
610 }
611 offset += block.size();
612
613 nfd::StrategyChoice strategyChoice(block);
614
615 std::cout << "<strategyChoice>";
616
617 std::string name(strategyChoice.getName().toUri());
618 escapeSpecialCharacters(&name);
619 std::cout << "<namespace>" << name << "</namespace>";
620 std::cout << "<strategy>";
621
622 std::string strategy(strategyChoice.getStrategy().toUri());
623 escapeSpecialCharacters(&strategy);
624
625 std::cout << "<name>" << strategy << "</name>";
626 std::cout << "</strategy>";
627 std::cout << "</strategyChoice>";
628 }
629
630 std::cout << "</strategyChoices>";
631 }
632 else
633 {
634 std::cout << "Strategy choices:" << std::endl;
635
636 Block block;
637 size_t offset = 0;
638 while (offset < buf->size())
639 {
640 bool ok = Block::fromBuffer(buf, offset, block);
641 if (!ok)
642 {
643 std::cerr << "ERROR: cannot decode StrategyChoice TLV" << std::endl;
644 break;
645 }
646 offset += block.size();
647
648 nfd::StrategyChoice strategyChoice(block);
649
650 std::cout << " " << strategyChoice.getName()
651 << " strategy=" << strategyChoice.getStrategy() << std::endl;
652 }
653 }
654
655 runNextStep();
656 }
657
658 void
Chengyu Fan30aa2072014-07-20 13:52:32 -0600659 fetchRibStatusInformation()
660 {
661 m_buffer = make_shared<OBufferStream>();
662
663 Interest interest("/localhost/nfd/rib/list");
664 interest.setChildSelector(1);
665 interest.setMustBeFresh(true);
666
667 m_face.expressInterest(interest,
668 bind(&NfdStatus::fetchSegments, this, _2,
669 &NfdStatus::afterFetchedRibStatusInformation),
670 bind(&NfdStatus::onTimeout, this));
671 }
672
673 void
674 afterFetchedRibStatusInformation()
675 {
676 ConstBufferPtr buf = m_buffer->buf();
677 if (m_isOutputXml)
678 {
679 std::cout << "<rib>";
680
681 Block block;
682 size_t offset = 0;
683 while (offset < buf->size())
684 {
685 bool ok = Block::fromBuffer(buf, offset, block);
686 if (!ok)
687 {
688 std::cerr << "ERROR: cannot decode RibEntry TLV";
689 break;
690 }
691 offset += block.size();
692
693 nfd::RibEntry ribEntry(block);
694
695 std::cout << "<ribEntry>";
696 std::string prefix(ribEntry.getName().toUri());
697 escapeSpecialCharacters(&prefix);
698 std::cout << "<prefix>" << prefix << "</prefix>";
699 std::cout << "<routes>";
700 for (std::list<nfd::Route>::const_iterator
701 nextRoute = ribEntry.begin();
702 nextRoute != ribEntry.end();
703 ++nextRoute)
704 {
705 std::cout << "<route>" ;
706 std::cout << "<faceId>" << nextRoute->getFaceId() << "</faceId>";
707 std::cout << "<origin>" << nextRoute->getOrigin() << "</origin>";
708 std::cout << "<cost>" << nextRoute->getCost() << "</cost>";
Chengyu Fan1c630ba2014-08-20 13:27:58 -0500709
710 std::cout << "<flags>";
711 if (nextRoute->isChildInherit())
712 std::cout << "<childInherit/>";
713 if (nextRoute->isRibCapture())
714 std::cout << "<ribCapture/>";
715 std::cout << "</flags>";
716
Chengyu Fan30aa2072014-07-20 13:52:32 -0600717 if (!nextRoute->hasInfiniteExpirationPeriod()) {
718 std::cout << "<expirationPeriod>PT"
719 << time::duration_cast<time::seconds>(nextRoute->getExpirationPeriod())
720 .count() << "S"
721 << "</expirationPeriod>";
722 }
723 std::cout << "</route>";
724 }
725 std::cout << "</routes>";
726 std::cout << "</ribEntry>";
727 }
728
729 std::cout << "</rib>";
730 }
731 else
732 {
Alexander Afanasyevc2642ca2014-09-01 15:57:35 -0700733 std::cout << "RIB:" << std::endl;
Chengyu Fan30aa2072014-07-20 13:52:32 -0600734
735 Block block;
736 size_t offset = 0;
737 while (offset < buf->size())
738 {
739 bool ok = Block::fromBuffer(buf, offset, block);
740 if (!ok)
741 {
742 std::cerr << "ERROR: cannot decode RibEntry TLV" << std::endl;
743 break;
744 }
745
746 offset += block.size();
747
748 nfd::RibEntry ribEntry(block);
749
Alexander Afanasyevc2642ca2014-09-01 15:57:35 -0700750 std::cout << " " << ribEntry.getName().toUri() << " route={";
Chengyu Fan30aa2072014-07-20 13:52:32 -0600751 for (std::list<nfd::Route>::const_iterator
752 nextRoute = ribEntry.begin();
753 nextRoute != ribEntry.end();
754 ++nextRoute)
755 {
756 if (nextRoute != ribEntry.begin())
757 std::cout << ", ";
758 std::cout << "faceid=" << nextRoute->getFaceId()
759 << " (origin=" << nextRoute->getOrigin()
Chengyu Fan1c630ba2014-08-20 13:27:58 -0500760 << " cost=" << nextRoute->getCost();
Chengyu Fan30aa2072014-07-20 13:52:32 -0600761 if (!nextRoute->hasInfiniteExpirationPeriod()) {
762 std::cout << " expires="
763 << time::duration_cast<time::seconds>(nextRoute->getExpirationPeriod())
764 .count() << "s";
765 }
Chengyu Fan1c630ba2014-08-20 13:27:58 -0500766
767 if (nextRoute->isChildInherit())
768 std::cout << " ChildInherit";
769 if (nextRoute->isRibCapture())
770 std::cout << " RibCapture";
771
Chengyu Fan30aa2072014-07-20 13:52:32 -0600772 std::cout << ")";
773 }
774 std::cout << "}" << std::endl;
775 }
776 }
777
778 runNextStep();
779 }
780
781
782 void
jeraldabrahamb6dde382014-03-19 18:58:09 -0700783 fetchInformation()
784 {
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300785 if (m_isOutputXml ||
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600786 (!m_needVersionRetrieval &&
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300787 !m_needChannelStatusRetrieval &&
788 !m_needFaceStatusRetrieval &&
789 !m_needFibEnumerationRetrieval &&
Chengyu Fan30aa2072014-07-20 13:52:32 -0600790 !m_needRibStatusRetrieval &&
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300791 !m_needStrategyChoiceRetrieval))
jeraldabrahamb6dde382014-03-19 18:58:09 -0700792 {
793 enableVersionRetrieval();
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300794 enableChannelStatusRetrieval();
jeraldabrahamb6dde382014-03-19 18:58:09 -0700795 enableFaceStatusRetrieval();
796 enableFibEnumerationRetrieval();
Chengyu Fan30aa2072014-07-20 13:52:32 -0600797 enableRibStatusRetrieval();
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300798 enableStrategyChoiceRetrieval();
jeraldabrahamb6dde382014-03-19 18:58:09 -0700799 }
800
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300801 if (m_isOutputXml)
802 m_fetchSteps.push_back(bind(&NfdStatus::printXmlHeader, this));
803
jeraldabrahamb6dde382014-03-19 18:58:09 -0700804 if (m_needVersionRetrieval)
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300805 m_fetchSteps.push_back(bind(&NfdStatus::fetchVersionInformation, this));
jeraldabrahamb6dde382014-03-19 18:58:09 -0700806
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300807 if (m_needChannelStatusRetrieval)
808 m_fetchSteps.push_back(bind(&NfdStatus::fetchChannelStatusInformation, this));
809
810 if (m_needFaceStatusRetrieval)
811 m_fetchSteps.push_back(bind(&NfdStatus::fetchFaceStatusInformation, this));
812
813 if (m_needFibEnumerationRetrieval)
814 m_fetchSteps.push_back(bind(&NfdStatus::fetchFibEnumerationInformation, this));
815
Chengyu Fan30aa2072014-07-20 13:52:32 -0600816 if (m_needRibStatusRetrieval)
817 m_fetchSteps.push_back(bind(&NfdStatus::fetchRibStatusInformation, this));
818
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300819 if (m_needStrategyChoiceRetrieval)
820 m_fetchSteps.push_back(bind(&NfdStatus::fetchStrategyChoiceInformation, this));
821
822 if (m_isOutputXml)
823 m_fetchSteps.push_back(bind(&NfdStatus::printXmlFooter, this));
824
825 runNextStep();
jeraldabrahamb6dde382014-03-19 18:58:09 -0700826 m_face.processEvents();
827 }
828
829private:
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300830 void
831 printXmlHeader()
832 {
833 std::cout << "<?xml version=\"1.0\"?>";
834 std::cout << "<nfdStatus xmlns=\"ndn:/localhost/nfd/status/1\">";
835
836 runNextStep();
837 }
838
839 void
840 printXmlFooter()
841 {
842 std::cout << "</nfdStatus>";
843
844 runNextStep();
845 }
846
847 void
848 runNextStep()
849 {
850 if (m_fetchSteps.empty())
851 return;
852
853 function<void()> nextStep = m_fetchSteps.front();
854 m_fetchSteps.pop_front();
855 nextStep();
856 }
857
858private:
jeraldabrahamb6dde382014-03-19 18:58:09 -0700859 std::string m_toolName;
860 bool m_needVersionRetrieval;
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300861 bool m_needChannelStatusRetrieval;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700862 bool m_needFaceStatusRetrieval;
863 bool m_needFibEnumerationRetrieval;
Chengyu Fan30aa2072014-07-20 13:52:32 -0600864 bool m_needRibStatusRetrieval;
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300865 bool m_needStrategyChoiceRetrieval;
866 bool m_isOutputXml;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700867 Face m_face;
868
869 shared_ptr<OBufferStream> m_buffer;
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300870
871 std::deque<function<void()> > m_fetchSteps;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700872};
873
874}
875
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700876int main(int argc, char* argv[])
jeraldabrahamb6dde382014-03-19 18:58:09 -0700877{
878 int option;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700879 ndn::NfdStatus nfdStatus(argv[0]);
jeraldabrahamb6dde382014-03-19 18:58:09 -0700880
Chengyu Fan30aa2072014-07-20 13:52:32 -0600881 while ((option = getopt(argc, argv, "hvcfbrsxV")) != -1) {
jeraldabrahamb6dde382014-03-19 18:58:09 -0700882 switch (option) {
883 case 'h':
884 nfdStatus.usage();
Alexander Afanasyev60a7ba52014-03-23 11:23:06 -0700885 return 0;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700886 case 'v':
887 nfdStatus.enableVersionRetrieval();
888 break;
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300889 case 'c':
890 nfdStatus.enableChannelStatusRetrieval();
891 break;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700892 case 'f':
893 nfdStatus.enableFaceStatusRetrieval();
894 break;
895 case 'b':
896 nfdStatus.enableFibEnumerationRetrieval();
897 break;
Chengyu Fan30aa2072014-07-20 13:52:32 -0600898 case 'r':
899 nfdStatus.enableRibStatusRetrieval();
900 break;
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300901 case 's':
902 nfdStatus.enableStrategyChoiceRetrieval();
903 break;
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600904 case 'x':
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300905 nfdStatus.enableXmlOutput();
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600906 break;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700907 case 'V':
908 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
909 return 0;
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700910 default:
jeraldabrahamb6dde382014-03-19 18:58:09 -0700911 nfdStatus.usage();
912 return 1;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700913 }
914 }
915
916 try {
917 nfdStatus.fetchInformation();
918 }
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700919 catch (std::exception& e) {
jeraldabrahamb6dde382014-03-19 18:58:09 -0700920 std::cerr << "ERROR: " << e.what() << std::endl;
921 return 2;
922 }
923
924 return 0;
925}