blob: 3262a2804a4f29983a64a9e2f17ac0645eddc01c [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
Chengyu Fan3331cfa2014-07-25 17:36:31 -0600404 std::cout << "<byteCounters>";
405 std::cout << "<incomingBytes>" << faceStatus.getNInBytes()
406 << "</incomingBytes>";
407 std::cout << "<outgoingBytes>" << faceStatus.getNOutBytes()
408 << "</outgoingBytes>";
409 std::cout << "</byteCounters>";
410
Alexander Afanasyevd3967a22014-06-30 12:22:10 -0700411 if (faceStatus.getFlags() != 0) {
412 std::cout << "<flags>";
413 if (faceStatus.isLocal()) {
414 std::cout << "<local/>";
415 }
416 if (faceStatus.isOnDemand()) {
417 std::cout << "<on-demand/>";
418 }
419 std::cout << "</flags>";
420 }
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600421 std::cout << "</face>";
jeraldabrahamb6dde382014-03-19 18:58:09 -0700422 }
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600423 std::cout << "</faces>";
jeraldabrahamb6dde382014-03-19 18:58:09 -0700424 }
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600425 else
426 {
427 std::cout << "Faces:" << std::endl;
428
429 Block block;
430 size_t offset = 0;
431 while (offset < buf->size())
432 {
433 bool ok = Block::fromBuffer(buf, offset, block);
434 if (!ok)
435 {
436 std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
437 break;
438 }
439
440 offset += block.size();
441
442 nfd::FaceStatus faceStatus(block);
443
444 std::cout << " faceid=" << faceStatus.getFaceId()
445 << " remote=" << faceStatus.getRemoteUri()
Alexander Afanasyev40c61f72014-06-30 17:21:01 -0700446 << " local=" << faceStatus.getLocalUri();
447 if (faceStatus.hasExpirationPeriod()) {
448 std::cout << " expires="
449 << time::duration_cast<time::seconds>(faceStatus.getExpirationPeriod())
450 .count() << "s";
451 }
452 std::cout << " counters={"
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600453 << "in={" << faceStatus.getNInInterests() << "i "
Chengyu Fan3331cfa2014-07-25 17:36:31 -0600454 << faceStatus.getNInDatas() << "d "
455 << faceStatus.getNInBytes() << "B}"
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600456 << " out={" << faceStatus.getNOutInterests() << "i "
Chengyu Fan3331cfa2014-07-25 17:36:31 -0600457 << faceStatus.getNOutDatas() << "d "
458 << faceStatus.getNOutBytes() << "B}"
Alexander Afanasyevd3967a22014-06-30 12:22:10 -0700459 << "}";
460 if (faceStatus.isLocal())
461 std::cout << " local";
462 if (faceStatus.isOnDemand())
463 std::cout << " on-demand";
464 std::cout << std::endl;
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600465 }
466 }
jeraldabrahamb6dde382014-03-19 18:58:09 -0700467
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300468 runNextStep();
jeraldabrahamb6dde382014-03-19 18:58:09 -0700469 }
470
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300471 //////////////////////////////////////////////////////////////////////////////////
472 //////////////////////////////////////////////////////////////////////////////////
473
jeraldabrahamb6dde382014-03-19 18:58:09 -0700474 void
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300475 fetchFibEnumerationInformation()
jeraldabrahamb6dde382014-03-19 18:58:09 -0700476 {
477 m_buffer = make_shared<OBufferStream>();
478
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300479 Interest interest("/localhost/nfd/fib/list");
jeraldabrahamb6dde382014-03-19 18:58:09 -0700480 interest.setChildSelector(1);
481 interest.setMustBeFresh(true);
jeraldabrahamb6dde382014-03-19 18:58:09 -0700482 m_face.expressInterest(interest,
483 bind(&NfdStatus::fetchSegments, this, _2,
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300484 &NfdStatus::afterFetchedFibEnumerationInformation),
jeraldabrahamb6dde382014-03-19 18:58:09 -0700485 bind(&NfdStatus::onTimeout, this));
486 }
487
488 void
489 afterFetchedFibEnumerationInformation()
490 {
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700491 ConstBufferPtr buf = m_buffer->buf();
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300492 if (m_isOutputXml)
jeraldabrahamb6dde382014-03-19 18:58:09 -0700493 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600494 std::cout << "<fib>";
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700495
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600496 Block block;
497 size_t offset = 0;
498 while (offset < buf->size())
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700499 {
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600500 bool ok = Block::fromBuffer(buf, offset, block);
501 if (!ok)
502 {
503 std::cerr << "ERROR: cannot decode FibEntry TLV";
504 break;
505 }
506 offset += block.size();
507
508 nfd::FibEntry fibEntry(block);
509
510 std::cout << "<fibEntry>";
511 std::string prefix(fibEntry.getPrefix().toUri());
512 escapeSpecialCharacters(&prefix);
513 std::cout << "<prefix>" << prefix << "</prefix>";
514 std::cout << "<nextHops>";
515 for (std::list<nfd::NextHopRecord>::const_iterator
516 nextHop = fibEntry.getNextHopRecords().begin();
517 nextHop != fibEntry.getNextHopRecords().end();
518 ++nextHop)
519 {
520 std::cout << "<nextHop>" ;
521 std::cout << "<faceId>" << nextHop->getFaceId() << "</faceId>";
522 std::cout << "<cost>" << nextHop->getCost() << "</cost>";
523 std::cout << "</nextHop>";
524 }
525 std::cout << "</nextHops>";
526 std::cout << "</fibEntry>";
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700527 }
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600528
529 std::cout << "</fib>";
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600530 }
531 else
532 {
533 std::cout << "FIB:" << std::endl;
534
535 Block block;
536 size_t offset = 0;
537 while (offset < buf->size())
538 {
539 bool ok = Block::fromBuffer(buf, offset, block);
540 if (!ok)
541 {
542 std::cerr << "ERROR: cannot decode FibEntry TLV" << std::endl;
543 break;
544 }
545 offset += block.size();
546
547 nfd::FibEntry fibEntry(block);
548
549 std::cout << " " << fibEntry.getPrefix() << " nexthops={";
550 for (std::list<nfd::NextHopRecord>::const_iterator
551 nextHop = fibEntry.getNextHopRecords().begin();
552 nextHop != fibEntry.getNextHopRecords().end();
553 ++nextHop)
554 {
555 if (nextHop != fibEntry.getNextHopRecords().begin())
556 std::cout << ", ";
557 std::cout << "faceid=" << nextHop->getFaceId()
558 << " (cost=" << nextHop->getCost() << ")";
559 }
560 std::cout << "}" << std::endl;
561 }
jeraldabrahamb6dde382014-03-19 18:58:09 -0700562 }
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300563
564 runNextStep();
jeraldabrahamb6dde382014-03-19 18:58:09 -0700565 }
566
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300567 //////////////////////////////////////////////////////////////////////////////////
568 //////////////////////////////////////////////////////////////////////////////////
569
jeraldabrahamb6dde382014-03-19 18:58:09 -0700570 void
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300571 fetchStrategyChoiceInformation()
jeraldabrahamb6dde382014-03-19 18:58:09 -0700572 {
573 m_buffer = make_shared<OBufferStream>();
574
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300575 Interest interest("/localhost/nfd/strategy-choice/list");
jeraldabrahamb6dde382014-03-19 18:58:09 -0700576 interest.setChildSelector(1);
577 interest.setMustBeFresh(true);
578 m_face.expressInterest(interest,
579 bind(&NfdStatus::fetchSegments, this, _2,
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300580 &NfdStatus::afterFetchedStrategyChoiceInformationInformation),
jeraldabrahamb6dde382014-03-19 18:58:09 -0700581 bind(&NfdStatus::onTimeout, this));
582 }
583
584 void
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300585 afterFetchedStrategyChoiceInformationInformation()
586 {
587 ConstBufferPtr buf = m_buffer->buf();
588 if (m_isOutputXml)
589 {
590 std::cout << "<strategyChoices>";
591
592 Block block;
593 size_t offset = 0;
594 while (offset < buf->size())
595 {
596 bool ok = Block::fromBuffer(buf, offset, block);
597 if (!ok)
598 {
599 std::cerr << "ERROR: cannot decode StrategyChoice TLV";
600 break;
601 }
602 offset += block.size();
603
604 nfd::StrategyChoice strategyChoice(block);
605
606 std::cout << "<strategyChoice>";
607
608 std::string name(strategyChoice.getName().toUri());
609 escapeSpecialCharacters(&name);
610 std::cout << "<namespace>" << name << "</namespace>";
611 std::cout << "<strategy>";
612
613 std::string strategy(strategyChoice.getStrategy().toUri());
614 escapeSpecialCharacters(&strategy);
615
616 std::cout << "<name>" << strategy << "</name>";
617 std::cout << "</strategy>";
618 std::cout << "</strategyChoice>";
619 }
620
621 std::cout << "</strategyChoices>";
622 }
623 else
624 {
625 std::cout << "Strategy choices:" << std::endl;
626
627 Block block;
628 size_t offset = 0;
629 while (offset < buf->size())
630 {
631 bool ok = Block::fromBuffer(buf, offset, block);
632 if (!ok)
633 {
634 std::cerr << "ERROR: cannot decode StrategyChoice TLV" << std::endl;
635 break;
636 }
637 offset += block.size();
638
639 nfd::StrategyChoice strategyChoice(block);
640
641 std::cout << " " << strategyChoice.getName()
642 << " strategy=" << strategyChoice.getStrategy() << std::endl;
643 }
644 }
645
646 runNextStep();
647 }
648
649 void
Chengyu Fan30aa2072014-07-20 13:52:32 -0600650 fetchRibStatusInformation()
651 {
652 m_buffer = make_shared<OBufferStream>();
653
654 Interest interest("/localhost/nfd/rib/list");
655 interest.setChildSelector(1);
656 interest.setMustBeFresh(true);
657
658 m_face.expressInterest(interest,
659 bind(&NfdStatus::fetchSegments, this, _2,
660 &NfdStatus::afterFetchedRibStatusInformation),
661 bind(&NfdStatus::onTimeout, this));
662 }
663
664 void
665 afterFetchedRibStatusInformation()
666 {
667 ConstBufferPtr buf = m_buffer->buf();
668 if (m_isOutputXml)
669 {
670 std::cout << "<rib>";
671
672 Block block;
673 size_t offset = 0;
674 while (offset < buf->size())
675 {
676 bool ok = Block::fromBuffer(buf, offset, block);
677 if (!ok)
678 {
679 std::cerr << "ERROR: cannot decode RibEntry TLV";
680 break;
681 }
682 offset += block.size();
683
684 nfd::RibEntry ribEntry(block);
685
686 std::cout << "<ribEntry>";
687 std::string prefix(ribEntry.getName().toUri());
688 escapeSpecialCharacters(&prefix);
689 std::cout << "<prefix>" << prefix << "</prefix>";
690 std::cout << "<routes>";
691 for (std::list<nfd::Route>::const_iterator
692 nextRoute = ribEntry.begin();
693 nextRoute != ribEntry.end();
694 ++nextRoute)
695 {
696 std::cout << "<route>" ;
697 std::cout << "<faceId>" << nextRoute->getFaceId() << "</faceId>";
698 std::cout << "<origin>" << nextRoute->getOrigin() << "</origin>";
699 std::cout << "<cost>" << nextRoute->getCost() << "</cost>";
700 std::cout << "<flags>" << nextRoute->getFlags() << "</flags>";
701 if (!nextRoute->hasInfiniteExpirationPeriod()) {
702 std::cout << "<expirationPeriod>PT"
703 << time::duration_cast<time::seconds>(nextRoute->getExpirationPeriod())
704 .count() << "S"
705 << "</expirationPeriod>";
706 }
707 std::cout << "</route>";
708 }
709 std::cout << "</routes>";
710 std::cout << "</ribEntry>";
711 }
712
713 std::cout << "</rib>";
714 }
715 else
716 {
717 std::cout << "Rib:" << std::endl;
718
719 Block block;
720 size_t offset = 0;
721 while (offset < buf->size())
722 {
723 bool ok = Block::fromBuffer(buf, offset, block);
724 if (!ok)
725 {
726 std::cerr << "ERROR: cannot decode RibEntry TLV" << std::endl;
727 break;
728 }
729
730 offset += block.size();
731
732 nfd::RibEntry ribEntry(block);
733
734 std::cout << " " << ribEntry.getName().toUri() << " route={";
735 for (std::list<nfd::Route>::const_iterator
736 nextRoute = ribEntry.begin();
737 nextRoute != ribEntry.end();
738 ++nextRoute)
739 {
740 if (nextRoute != ribEntry.begin())
741 std::cout << ", ";
742 std::cout << "faceid=" << nextRoute->getFaceId()
743 << " (origin=" << nextRoute->getOrigin()
744 << " cost=" << nextRoute->getCost()
745 << " flags=" << nextRoute->getFlags();
746 if (!nextRoute->hasInfiniteExpirationPeriod()) {
747 std::cout << " expires="
748 << time::duration_cast<time::seconds>(nextRoute->getExpirationPeriod())
749 .count() << "s";
750 }
751 std::cout << ")";
752 }
753 std::cout << "}" << std::endl;
754 }
755 }
756
757 runNextStep();
758 }
759
760
761 void
jeraldabrahamb6dde382014-03-19 18:58:09 -0700762 fetchInformation()
763 {
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300764 if (m_isOutputXml ||
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600765 (!m_needVersionRetrieval &&
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300766 !m_needChannelStatusRetrieval &&
767 !m_needFaceStatusRetrieval &&
768 !m_needFibEnumerationRetrieval &&
Chengyu Fan30aa2072014-07-20 13:52:32 -0600769 !m_needRibStatusRetrieval &&
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300770 !m_needStrategyChoiceRetrieval))
jeraldabrahamb6dde382014-03-19 18:58:09 -0700771 {
772 enableVersionRetrieval();
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300773 enableChannelStatusRetrieval();
jeraldabrahamb6dde382014-03-19 18:58:09 -0700774 enableFaceStatusRetrieval();
775 enableFibEnumerationRetrieval();
Chengyu Fan30aa2072014-07-20 13:52:32 -0600776 enableRibStatusRetrieval();
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300777 enableStrategyChoiceRetrieval();
jeraldabrahamb6dde382014-03-19 18:58:09 -0700778 }
779
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300780 if (m_isOutputXml)
781 m_fetchSteps.push_back(bind(&NfdStatus::printXmlHeader, this));
782
jeraldabrahamb6dde382014-03-19 18:58:09 -0700783 if (m_needVersionRetrieval)
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300784 m_fetchSteps.push_back(bind(&NfdStatus::fetchVersionInformation, this));
jeraldabrahamb6dde382014-03-19 18:58:09 -0700785
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300786 if (m_needChannelStatusRetrieval)
787 m_fetchSteps.push_back(bind(&NfdStatus::fetchChannelStatusInformation, this));
788
789 if (m_needFaceStatusRetrieval)
790 m_fetchSteps.push_back(bind(&NfdStatus::fetchFaceStatusInformation, this));
791
792 if (m_needFibEnumerationRetrieval)
793 m_fetchSteps.push_back(bind(&NfdStatus::fetchFibEnumerationInformation, this));
794
Chengyu Fan30aa2072014-07-20 13:52:32 -0600795 if (m_needRibStatusRetrieval)
796 m_fetchSteps.push_back(bind(&NfdStatus::fetchRibStatusInformation, this));
797
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300798 if (m_needStrategyChoiceRetrieval)
799 m_fetchSteps.push_back(bind(&NfdStatus::fetchStrategyChoiceInformation, this));
800
801 if (m_isOutputXml)
802 m_fetchSteps.push_back(bind(&NfdStatus::printXmlFooter, this));
803
804 runNextStep();
jeraldabrahamb6dde382014-03-19 18:58:09 -0700805 m_face.processEvents();
806 }
807
808private:
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300809 void
810 printXmlHeader()
811 {
812 std::cout << "<?xml version=\"1.0\"?>";
813 std::cout << "<nfdStatus xmlns=\"ndn:/localhost/nfd/status/1\">";
814
815 runNextStep();
816 }
817
818 void
819 printXmlFooter()
820 {
821 std::cout << "</nfdStatus>";
822
823 runNextStep();
824 }
825
826 void
827 runNextStep()
828 {
829 if (m_fetchSteps.empty())
830 return;
831
832 function<void()> nextStep = m_fetchSteps.front();
833 m_fetchSteps.pop_front();
834 nextStep();
835 }
836
837private:
jeraldabrahamb6dde382014-03-19 18:58:09 -0700838 std::string m_toolName;
839 bool m_needVersionRetrieval;
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300840 bool m_needChannelStatusRetrieval;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700841 bool m_needFaceStatusRetrieval;
842 bool m_needFibEnumerationRetrieval;
Chengyu Fan30aa2072014-07-20 13:52:32 -0600843 bool m_needRibStatusRetrieval;
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300844 bool m_needStrategyChoiceRetrieval;
845 bool m_isOutputXml;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700846 Face m_face;
847
848 shared_ptr<OBufferStream> m_buffer;
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300849
850 std::deque<function<void()> > m_fetchSteps;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700851};
852
853}
854
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700855int main(int argc, char* argv[])
jeraldabrahamb6dde382014-03-19 18:58:09 -0700856{
857 int option;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700858 ndn::NfdStatus nfdStatus(argv[0]);
jeraldabrahamb6dde382014-03-19 18:58:09 -0700859
Chengyu Fan30aa2072014-07-20 13:52:32 -0600860 while ((option = getopt(argc, argv, "hvcfbrsxV")) != -1) {
jeraldabrahamb6dde382014-03-19 18:58:09 -0700861 switch (option) {
862 case 'h':
863 nfdStatus.usage();
Alexander Afanasyev60a7ba52014-03-23 11:23:06 -0700864 return 0;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700865 case 'v':
866 nfdStatus.enableVersionRetrieval();
867 break;
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300868 case 'c':
869 nfdStatus.enableChannelStatusRetrieval();
870 break;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700871 case 'f':
872 nfdStatus.enableFaceStatusRetrieval();
873 break;
874 case 'b':
875 nfdStatus.enableFibEnumerationRetrieval();
876 break;
Chengyu Fan30aa2072014-07-20 13:52:32 -0600877 case 'r':
878 nfdStatus.enableRibStatusRetrieval();
879 break;
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300880 case 's':
881 nfdStatus.enableStrategyChoiceRetrieval();
882 break;
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600883 case 'x':
Alexander Afanasyev0417d2a2014-06-08 10:56:43 +0300884 nfdStatus.enableXmlOutput();
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600885 break;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700886 case 'V':
887 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
888 return 0;
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700889 default:
jeraldabrahamb6dde382014-03-19 18:58:09 -0700890 nfdStatus.usage();
891 return 1;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700892 }
893 }
894
895 try {
896 nfdStatus.fetchInformation();
897 }
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700898 catch (std::exception& e) {
jeraldabrahamb6dde382014-03-19 18:58:09 -0700899 std::cerr << "ERROR: " << e.what() << std::endl;
900 return 2;
901 }
902
903 return 0;
904}