blob: 219e53d0ab6fcb0f8d57e5b86b8f67c63b76bfe9 [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 Fan514ed5e2014-04-17 13:07:30 -0600402 std::cout << "<packetCounters>";
403 std::cout << "<incomingPackets>";
404 std::cout << "<nInterests>" << faceStatus.getNInInterests()
405 << "</nInterests>";
Chengyu Fan30aa2072014-07-20 13:52:32 -0600406 std::cout << "<nDatas>" << faceStatus.getNInDatas()
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600407 << "</nDatas>";
408 std::cout << "</incomingPackets>";
409 std::cout << "<outgoingPackets>";
410 std::cout << "<nInterests>" << faceStatus.getNOutInterests()
411 << "</nInterests>";
Chengyu Fan30aa2072014-07-20 13:52:32 -0600412 std::cout << "<nDatas>" << faceStatus.getNOutDatas()
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600413 << "</nDatas>";
414 std::cout << "</outgoingPackets>";
415 std::cout << "</packetCounters>";
Alexander Afanasyevd3967a22014-06-30 12:22:10 -0700416
Chengyu Fan3331cfa2014-07-25 17:36:31 -0600417 std::cout << "<byteCounters>";
418 std::cout << "<incomingBytes>" << faceStatus.getNInBytes()
419 << "</incomingBytes>";
420 std::cout << "<outgoingBytes>" << faceStatus.getNOutBytes()
421 << "</outgoingBytes>";
422 std::cout << "</byteCounters>";
423
Alexander Afanasyevd3967a22014-06-30 12:22:10 -0700424 if (faceStatus.getFlags() != 0) {
425 std::cout << "<flags>";
426 if (faceStatus.isLocal()) {
427 std::cout << "<local/>";
428 }
429 if (faceStatus.isOnDemand()) {
430 std::cout << "<on-demand/>";
431 }
432 std::cout << "</flags>";
433 }
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600434 std::cout << "</face>";
jeraldabrahamb6dde382014-03-19 18:58:09 -0700435 }
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600436 std::cout << "</faces>";
jeraldabrahamb6dde382014-03-19 18:58:09 -0700437 }
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600438 else
439 {
440 std::cout << "Faces:" << std::endl;
441
442 Block block;
443 size_t offset = 0;
444 while (offset < buf->size())
445 {
446 bool ok = Block::fromBuffer(buf, offset, block);
447 if (!ok)
448 {
449 std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
450 break;
451 }
452
453 offset += block.size();
454
455 nfd::FaceStatus faceStatus(block);
456
457 std::cout << " faceid=" << faceStatus.getFaceId()
458 << " remote=" << faceStatus.getRemoteUri()
Alexander Afanasyev40c61f72014-06-30 17:21:01 -0700459 << " local=" << faceStatus.getLocalUri();
460 if (faceStatus.hasExpirationPeriod()) {
461 std::cout << " expires="
462 << time::duration_cast<time::seconds>(faceStatus.getExpirationPeriod())
463 .count() << "s";
464 }
465 std::cout << " counters={"
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600466 << "in={" << faceStatus.getNInInterests() << "i "
Chengyu Fan3331cfa2014-07-25 17:36:31 -0600467 << faceStatus.getNInDatas() << "d "
468 << faceStatus.getNInBytes() << "B}"
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600469 << " out={" << faceStatus.getNOutInterests() << "i "
Chengyu Fan3331cfa2014-07-25 17:36:31 -0600470 << faceStatus.getNOutDatas() << "d "
471 << faceStatus.getNOutBytes() << "B}"
Alexander Afanasyevd3967a22014-06-30 12:22:10 -0700472 << "}";
473 if (faceStatus.isLocal())
474 std::cout << " local";
475 if (faceStatus.isOnDemand())
476 std::cout << " on-demand";
477 std::cout << std::endl;
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600478 }
479 }
jeraldabrahamb6dde382014-03-19 18:58:09 -0700480
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300481 runNextStep();
jeraldabrahamb6dde382014-03-19 18:58:09 -0700482 }
483
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300484 //////////////////////////////////////////////////////////////////////////////////
485 //////////////////////////////////////////////////////////////////////////////////
486
jeraldabrahamb6dde382014-03-19 18:58:09 -0700487 void
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300488 fetchFibEnumerationInformation()
jeraldabrahamb6dde382014-03-19 18:58:09 -0700489 {
490 m_buffer = make_shared<OBufferStream>();
491
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300492 Interest interest("/localhost/nfd/fib/list");
jeraldabrahamb6dde382014-03-19 18:58:09 -0700493 interest.setChildSelector(1);
494 interest.setMustBeFresh(true);
jeraldabrahamb6dde382014-03-19 18:58:09 -0700495 m_face.expressInterest(interest,
496 bind(&NfdStatus::fetchSegments, this, _2,
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300497 &NfdStatus::afterFetchedFibEnumerationInformation),
jeraldabrahamb6dde382014-03-19 18:58:09 -0700498 bind(&NfdStatus::onTimeout, this));
499 }
500
501 void
502 afterFetchedFibEnumerationInformation()
503 {
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700504 ConstBufferPtr buf = m_buffer->buf();
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300505 if (m_isOutputXml)
jeraldabrahamb6dde382014-03-19 18:58:09 -0700506 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600507 std::cout << "<fib>";
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700508
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600509 Block block;
510 size_t offset = 0;
511 while (offset < buf->size())
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700512 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600513 bool ok = Block::fromBuffer(buf, offset, block);
514 if (!ok)
515 {
516 std::cerr << "ERROR: cannot decode FibEntry TLV";
517 break;
518 }
519 offset += block.size();
520
521 nfd::FibEntry fibEntry(block);
522
523 std::cout << "<fibEntry>";
524 std::string prefix(fibEntry.getPrefix().toUri());
525 escapeSpecialCharacters(&prefix);
526 std::cout << "<prefix>" << prefix << "</prefix>";
527 std::cout << "<nextHops>";
528 for (std::list<nfd::NextHopRecord>::const_iterator
529 nextHop = fibEntry.getNextHopRecords().begin();
530 nextHop != fibEntry.getNextHopRecords().end();
531 ++nextHop)
532 {
533 std::cout << "<nextHop>" ;
534 std::cout << "<faceId>" << nextHop->getFaceId() << "</faceId>";
535 std::cout << "<cost>" << nextHop->getCost() << "</cost>";
536 std::cout << "</nextHop>";
537 }
538 std::cout << "</nextHops>";
539 std::cout << "</fibEntry>";
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700540 }
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600541
542 std::cout << "</fib>";
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600543 }
544 else
545 {
546 std::cout << "FIB:" << std::endl;
547
548 Block block;
549 size_t offset = 0;
550 while (offset < buf->size())
551 {
552 bool ok = Block::fromBuffer(buf, offset, block);
553 if (!ok)
554 {
555 std::cerr << "ERROR: cannot decode FibEntry TLV" << std::endl;
556 break;
557 }
558 offset += block.size();
559
560 nfd::FibEntry fibEntry(block);
561
562 std::cout << " " << fibEntry.getPrefix() << " nexthops={";
563 for (std::list<nfd::NextHopRecord>::const_iterator
564 nextHop = fibEntry.getNextHopRecords().begin();
565 nextHop != fibEntry.getNextHopRecords().end();
566 ++nextHop)
567 {
568 if (nextHop != fibEntry.getNextHopRecords().begin())
569 std::cout << ", ";
570 std::cout << "faceid=" << nextHop->getFaceId()
571 << " (cost=" << nextHop->getCost() << ")";
572 }
573 std::cout << "}" << std::endl;
574 }
jeraldabrahamb6dde382014-03-19 18:58:09 -0700575 }
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300576
577 runNextStep();
jeraldabrahamb6dde382014-03-19 18:58:09 -0700578 }
579
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300580 //////////////////////////////////////////////////////////////////////////////////
581 //////////////////////////////////////////////////////////////////////////////////
582
jeraldabrahamb6dde382014-03-19 18:58:09 -0700583 void
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300584 fetchStrategyChoiceInformation()
jeraldabrahamb6dde382014-03-19 18:58:09 -0700585 {
586 m_buffer = make_shared<OBufferStream>();
587
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300588 Interest interest("/localhost/nfd/strategy-choice/list");
jeraldabrahamb6dde382014-03-19 18:58:09 -0700589 interest.setChildSelector(1);
590 interest.setMustBeFresh(true);
591 m_face.expressInterest(interest,
592 bind(&NfdStatus::fetchSegments, this, _2,
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300593 &NfdStatus::afterFetchedStrategyChoiceInformationInformation),
jeraldabrahamb6dde382014-03-19 18:58:09 -0700594 bind(&NfdStatus::onTimeout, this));
595 }
596
597 void
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300598 afterFetchedStrategyChoiceInformationInformation()
599 {
600 ConstBufferPtr buf = m_buffer->buf();
601 if (m_isOutputXml)
602 {
603 std::cout << "<strategyChoices>";
604
605 Block block;
606 size_t offset = 0;
607 while (offset < buf->size())
608 {
609 bool ok = Block::fromBuffer(buf, offset, block);
610 if (!ok)
611 {
612 std::cerr << "ERROR: cannot decode StrategyChoice TLV";
613 break;
614 }
615 offset += block.size();
616
617 nfd::StrategyChoice strategyChoice(block);
618
619 std::cout << "<strategyChoice>";
620
621 std::string name(strategyChoice.getName().toUri());
622 escapeSpecialCharacters(&name);
623 std::cout << "<namespace>" << name << "</namespace>";
624 std::cout << "<strategy>";
625
626 std::string strategy(strategyChoice.getStrategy().toUri());
627 escapeSpecialCharacters(&strategy);
628
629 std::cout << "<name>" << strategy << "</name>";
630 std::cout << "</strategy>";
631 std::cout << "</strategyChoice>";
632 }
633
634 std::cout << "</strategyChoices>";
635 }
636 else
637 {
638 std::cout << "Strategy choices:" << std::endl;
639
640 Block block;
641 size_t offset = 0;
642 while (offset < buf->size())
643 {
644 bool ok = Block::fromBuffer(buf, offset, block);
645 if (!ok)
646 {
647 std::cerr << "ERROR: cannot decode StrategyChoice TLV" << std::endl;
648 break;
649 }
650 offset += block.size();
651
652 nfd::StrategyChoice strategyChoice(block);
653
654 std::cout << " " << strategyChoice.getName()
655 << " strategy=" << strategyChoice.getStrategy() << std::endl;
656 }
657 }
658
659 runNextStep();
660 }
661
662 void
Chengyu Fan30aa2072014-07-20 13:52:32 -0600663 fetchRibStatusInformation()
664 {
665 m_buffer = make_shared<OBufferStream>();
666
667 Interest interest("/localhost/nfd/rib/list");
668 interest.setChildSelector(1);
669 interest.setMustBeFresh(true);
670
671 m_face.expressInterest(interest,
672 bind(&NfdStatus::fetchSegments, this, _2,
673 &NfdStatus::afterFetchedRibStatusInformation),
674 bind(&NfdStatus::onTimeout, this));
675 }
676
677 void
678 afterFetchedRibStatusInformation()
679 {
680 ConstBufferPtr buf = m_buffer->buf();
681 if (m_isOutputXml)
682 {
683 std::cout << "<rib>";
684
685 Block block;
686 size_t offset = 0;
687 while (offset < buf->size())
688 {
689 bool ok = Block::fromBuffer(buf, offset, block);
690 if (!ok)
691 {
692 std::cerr << "ERROR: cannot decode RibEntry TLV";
693 break;
694 }
695 offset += block.size();
696
697 nfd::RibEntry ribEntry(block);
698
699 std::cout << "<ribEntry>";
700 std::string prefix(ribEntry.getName().toUri());
701 escapeSpecialCharacters(&prefix);
702 std::cout << "<prefix>" << prefix << "</prefix>";
703 std::cout << "<routes>";
704 for (std::list<nfd::Route>::const_iterator
705 nextRoute = ribEntry.begin();
706 nextRoute != ribEntry.end();
707 ++nextRoute)
708 {
709 std::cout << "<route>" ;
710 std::cout << "<faceId>" << nextRoute->getFaceId() << "</faceId>";
711 std::cout << "<origin>" << nextRoute->getOrigin() << "</origin>";
712 std::cout << "<cost>" << nextRoute->getCost() << "</cost>";
713 std::cout << "<flags>" << nextRoute->getFlags() << "</flags>";
714 if (!nextRoute->hasInfiniteExpirationPeriod()) {
715 std::cout << "<expirationPeriod>PT"
716 << time::duration_cast<time::seconds>(nextRoute->getExpirationPeriod())
717 .count() << "S"
718 << "</expirationPeriod>";
719 }
720 std::cout << "</route>";
721 }
722 std::cout << "</routes>";
723 std::cout << "</ribEntry>";
724 }
725
726 std::cout << "</rib>";
727 }
728 else
729 {
730 std::cout << "Rib:" << std::endl;
731
732 Block block;
733 size_t offset = 0;
734 while (offset < buf->size())
735 {
736 bool ok = Block::fromBuffer(buf, offset, block);
737 if (!ok)
738 {
739 std::cerr << "ERROR: cannot decode RibEntry TLV" << std::endl;
740 break;
741 }
742
743 offset += block.size();
744
745 nfd::RibEntry ribEntry(block);
746
747 std::cout << " " << ribEntry.getName().toUri() << " route={";
748 for (std::list<nfd::Route>::const_iterator
749 nextRoute = ribEntry.begin();
750 nextRoute != ribEntry.end();
751 ++nextRoute)
752 {
753 if (nextRoute != ribEntry.begin())
754 std::cout << ", ";
755 std::cout << "faceid=" << nextRoute->getFaceId()
756 << " (origin=" << nextRoute->getOrigin()
757 << " cost=" << nextRoute->getCost()
758 << " flags=" << nextRoute->getFlags();
759 if (!nextRoute->hasInfiniteExpirationPeriod()) {
760 std::cout << " expires="
761 << time::duration_cast<time::seconds>(nextRoute->getExpirationPeriod())
762 .count() << "s";
763 }
764 std::cout << ")";
765 }
766 std::cout << "}" << std::endl;
767 }
768 }
769
770 runNextStep();
771 }
772
773
774 void
jeraldabrahamb6dde382014-03-19 18:58:09 -0700775 fetchInformation()
776 {
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300777 if (m_isOutputXml ||
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600778 (!m_needVersionRetrieval &&
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300779 !m_needChannelStatusRetrieval &&
780 !m_needFaceStatusRetrieval &&
781 !m_needFibEnumerationRetrieval &&
Chengyu Fan30aa2072014-07-20 13:52:32 -0600782 !m_needRibStatusRetrieval &&
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300783 !m_needStrategyChoiceRetrieval))
jeraldabrahamb6dde382014-03-19 18:58:09 -0700784 {
785 enableVersionRetrieval();
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300786 enableChannelStatusRetrieval();
jeraldabrahamb6dde382014-03-19 18:58:09 -0700787 enableFaceStatusRetrieval();
788 enableFibEnumerationRetrieval();
Chengyu Fan30aa2072014-07-20 13:52:32 -0600789 enableRibStatusRetrieval();
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300790 enableStrategyChoiceRetrieval();
jeraldabrahamb6dde382014-03-19 18:58:09 -0700791 }
792
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300793 if (m_isOutputXml)
794 m_fetchSteps.push_back(bind(&NfdStatus::printXmlHeader, this));
795
jeraldabrahamb6dde382014-03-19 18:58:09 -0700796 if (m_needVersionRetrieval)
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300797 m_fetchSteps.push_back(bind(&NfdStatus::fetchVersionInformation, this));
jeraldabrahamb6dde382014-03-19 18:58:09 -0700798
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300799 if (m_needChannelStatusRetrieval)
800 m_fetchSteps.push_back(bind(&NfdStatus::fetchChannelStatusInformation, this));
801
802 if (m_needFaceStatusRetrieval)
803 m_fetchSteps.push_back(bind(&NfdStatus::fetchFaceStatusInformation, this));
804
805 if (m_needFibEnumerationRetrieval)
806 m_fetchSteps.push_back(bind(&NfdStatus::fetchFibEnumerationInformation, this));
807
Chengyu Fan30aa2072014-07-20 13:52:32 -0600808 if (m_needRibStatusRetrieval)
809 m_fetchSteps.push_back(bind(&NfdStatus::fetchRibStatusInformation, this));
810
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300811 if (m_needStrategyChoiceRetrieval)
812 m_fetchSteps.push_back(bind(&NfdStatus::fetchStrategyChoiceInformation, this));
813
814 if (m_isOutputXml)
815 m_fetchSteps.push_back(bind(&NfdStatus::printXmlFooter, this));
816
817 runNextStep();
jeraldabrahamb6dde382014-03-19 18:58:09 -0700818 m_face.processEvents();
819 }
820
821private:
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300822 void
823 printXmlHeader()
824 {
825 std::cout << "<?xml version=\"1.0\"?>";
826 std::cout << "<nfdStatus xmlns=\"ndn:/localhost/nfd/status/1\">";
827
828 runNextStep();
829 }
830
831 void
832 printXmlFooter()
833 {
834 std::cout << "</nfdStatus>";
835
836 runNextStep();
837 }
838
839 void
840 runNextStep()
841 {
842 if (m_fetchSteps.empty())
843 return;
844
845 function<void()> nextStep = m_fetchSteps.front();
846 m_fetchSteps.pop_front();
847 nextStep();
848 }
849
850private:
jeraldabrahamb6dde382014-03-19 18:58:09 -0700851 std::string m_toolName;
852 bool m_needVersionRetrieval;
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300853 bool m_needChannelStatusRetrieval;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700854 bool m_needFaceStatusRetrieval;
855 bool m_needFibEnumerationRetrieval;
Chengyu Fan30aa2072014-07-20 13:52:32 -0600856 bool m_needRibStatusRetrieval;
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300857 bool m_needStrategyChoiceRetrieval;
858 bool m_isOutputXml;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700859 Face m_face;
860
861 shared_ptr<OBufferStream> m_buffer;
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300862
863 std::deque<function<void()> > m_fetchSteps;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700864};
865
866}
867
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700868int main(int argc, char* argv[])
jeraldabrahamb6dde382014-03-19 18:58:09 -0700869{
870 int option;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700871 ndn::NfdStatus nfdStatus(argv[0]);
jeraldabrahamb6dde382014-03-19 18:58:09 -0700872
Chengyu Fan30aa2072014-07-20 13:52:32 -0600873 while ((option = getopt(argc, argv, "hvcfbrsxV")) != -1) {
jeraldabrahamb6dde382014-03-19 18:58:09 -0700874 switch (option) {
875 case 'h':
876 nfdStatus.usage();
Alexander Afanasyev60a7ba52014-03-23 11:23:06 -0700877 return 0;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700878 case 'v':
879 nfdStatus.enableVersionRetrieval();
880 break;
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300881 case 'c':
882 nfdStatus.enableChannelStatusRetrieval();
883 break;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700884 case 'f':
885 nfdStatus.enableFaceStatusRetrieval();
886 break;
887 case 'b':
888 nfdStatus.enableFibEnumerationRetrieval();
889 break;
Chengyu Fan30aa2072014-07-20 13:52:32 -0600890 case 'r':
891 nfdStatus.enableRibStatusRetrieval();
892 break;
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300893 case 's':
894 nfdStatus.enableStrategyChoiceRetrieval();
895 break;
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600896 case 'x':
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300897 nfdStatus.enableXmlOutput();
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600898 break;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700899 case 'V':
900 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
901 return 0;
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700902 default:
jeraldabrahamb6dde382014-03-19 18:58:09 -0700903 nfdStatus.usage();
904 return 1;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700905 }
906 }
907
908 try {
909 nfdStatus.fetchInformation();
910 }
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700911 catch (std::exception& e) {
jeraldabrahamb6dde382014-03-19 18:58:09 -0700912 std::cerr << "ERROR: " << e.what() << std::endl;
913 return 2;
914 }
915
916 return 0;
917}