blob: 9e8fa287caf733b0514628a5205ff3359ae47367 [file] [log] [blame]
Alexander Afanasyev4a771362014-04-24 21:29:33 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
jeraldabrahamb6dde382014-03-19 18:58:09 -07002/**
Alexander Afanasyev4a771362014-04-24 21:29:33 -07003 * Copyright (c) 2014, Regents of the University of California,
4 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis
jeraldabrahamb6dde382014-03-19 18:58:09 -070010 *
Alexander Afanasyev4a771362014-04-24 21:29:33 -070011 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24 *
25 * @author Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
jeraldabrahamb6dde382014-03-19 18:58:09 -070026 */
27
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070028#include "version.hpp"
29
Alexander Afanasyev4a771362014-04-24 21:29:33 -070030#include <ndn-cxx/face.hpp>
31#include <ndn-cxx/name.hpp>
32#include <ndn-cxx/interest.hpp>
jeraldabrahamb6dde382014-03-19 18:58:09 -070033
Alexander Afanasyev4a771362014-04-24 21:29:33 -070034#include <ndn-cxx/management/nfd-fib-entry.hpp>
35#include <ndn-cxx/management/nfd-face-status.hpp>
36#include <ndn-cxx/management/nfd-forwarder-status.hpp>
jeraldabrahamb6dde382014-03-19 18:58:09 -070037
38namespace ndn {
39
40class NfdStatus
41{
42public:
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -070043 explicit
jeraldabrahamb6dde382014-03-19 18:58:09 -070044 NfdStatus(char* toolName)
45 : m_toolName(toolName)
46 , m_needVersionRetrieval(false)
47 , m_needFaceStatusRetrieval(false)
48 , m_needFibEnumerationRetrieval(false)
jeraldabrahamb6dde382014-03-19 18:58:09 -070049 {
50 }
51
52 void
53 usage()
54 {
Alexander Afanasyev60a7ba52014-03-23 11:23:06 -070055 std::cout << "Usage: \n " << m_toolName << " [options]\n\n"
56 "Show NFD version and status information\n\n"
57 "Options:\n"
58 " [-h] - print this help message\n"
jeraldabrahamb6dde382014-03-19 18:58:09 -070059 " [-v] - retrieve version information\n"
60 " [-f] - retrieve face status information\n"
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070061 " [-b] - retrieve FIB information\n"
62 "\n"
63 " [-V] - show version information of nfd-status and exit\n"
64 "\n"
Alexander Afanasyev60a7ba52014-03-23 11:23:06 -070065 "If no options are provided, all information is retrieved.\n"
66 ;
jeraldabrahamb6dde382014-03-19 18:58:09 -070067 }
68
69 void
70 enableVersionRetrieval()
71 {
72 m_needVersionRetrieval = true;
73 }
74
75 void
76 enableFaceStatusRetrieval()
77 {
78 m_needFaceStatusRetrieval = true;
79 }
80
81 void
82 enableFibEnumerationRetrieval()
83 {
84 m_needFibEnumerationRetrieval = true;
85 }
86
87 void
88 onTimeout()
89 {
90 std::cerr << "Request timed out" << std::endl;
91 }
92
93 void
94 fetchSegments(const Data& data, void (NfdStatus::*onDone)())
95 {
96 m_buffer->write((const char*)data.getContent().value(),
97 data.getContent().value_size());
98
99 uint64_t currentSegment = data.getName().get(-1).toSegment();
100
101 const name::Component& finalBlockId = data.getMetaInfo().getFinalBlockId();
102 if (finalBlockId.empty() ||
103 finalBlockId.toSegment() > currentSegment)
104 {
105 m_face.expressInterest(data.getName().getPrefix(-1).appendSegment(currentSegment+1),
106 bind(&NfdStatus::fetchSegments, this, _2, onDone),
107 bind(&NfdStatus::onTimeout, this));
108 }
109 else
110 {
111 return (this->*onDone)();
112 }
113 }
114
115 void
116 afterFetchedVersionInformation(const Data& data)
117 {
118 std::cout << "General NFD status:" << std::endl;
119
Junxiao Shi88d69372014-03-28 11:52:39 -0700120 nfd::ForwarderStatus status(data.getContent());
jeraldabrahamb6dde382014-03-19 18:58:09 -0700121 std::cout << " version="
122 << status.getNfdVersion() << std::endl;
123 std::cout << " startTime="
124 << time::toIsoString(status.getStartTimestamp()) << std::endl;
125 std::cout << " currentTime="
126 << time::toIsoString(status.getCurrentTimestamp()) << std::endl;
127 std::cout << " uptime="
128 << time::duration_cast<time::seconds>(status.getCurrentTimestamp()
129 - status.getStartTimestamp()) << std::endl;
130
131 std::cout << " nNameTreeEntries=" << status.getNNameTreeEntries() << std::endl;
132 std::cout << " nFibEntries=" << status.getNFibEntries() << std::endl;
133 std::cout << " nPitEntries=" << status.getNPitEntries() << std::endl;
134 std::cout << " nMeasurementsEntries=" << status.getNMeasurementsEntries() << std::endl;
135 std::cout << " nCsEntries=" << status.getNCsEntries() << std::endl;
136 std::cout << " nInInterests=" << status.getNInInterests() << std::endl;
137 std::cout << " nOutInterests=" << status.getNOutInterests() << std::endl;
138 std::cout << " nInDatas=" << status.getNInDatas() << std::endl;
139 std::cout << " nOutDatas=" << status.getNOutDatas() << std::endl;
140
141 if (m_needFaceStatusRetrieval)
142 {
143 fetchFaceStatusInformation();
144 }
145 else if (m_needFibEnumerationRetrieval)
146 {
147 fetchFibEnumerationInformation();
148 }
149 }
150
151 void
152 fetchVersionInformation()
153 {
154 Interest interest("/localhost/nfd/status");
155 interest.setChildSelector(1);
156 interest.setMustBeFresh(true);
157 m_face.expressInterest(
158 interest,
159 bind(&NfdStatus::afterFetchedVersionInformation, this, _2),
160 bind(&NfdStatus::onTimeout, this));
161 }
162
163 void
164 afterFetchedFaceStatusInformation()
165 {
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700166 std::cout << "Faces:" << std::endl;
167
168 ConstBufferPtr buf = m_buffer->buf();
169
170 Block block;
171 size_t offset = 0;
172 while (offset < buf->size())
jeraldabrahamb6dde382014-03-19 18:58:09 -0700173 {
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700174 bool ok = Block::fromBuffer(buf, offset, block);
175 if (!ok)
jeraldabrahamb6dde382014-03-19 18:58:09 -0700176 {
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700177 std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
178 break;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700179 }
180
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700181 offset += block.size();
182
183 nfd::FaceStatus faceStatus(block);
184
185 std::cout << " faceid=" << faceStatus.getFaceId()
Junxiao Shi6e694322014-04-03 10:27:13 -0700186 << " remote=" << faceStatus.getRemoteUri()
187 << " local=" << faceStatus.getLocalUri()
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700188 << " counters={"
Junxiao Shi6e694322014-04-03 10:27:13 -0700189 << "in={" << faceStatus.getNInInterests() << "i "
190 << faceStatus.getNInDatas() << "d}"
191 << " out={" << faceStatus.getNOutInterests() << "i "
192 << faceStatus.getNOutDatas() << "d}"
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700193 << "}" << std::endl;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700194 }
195
196 if (m_needFibEnumerationRetrieval)
197 {
198 fetchFibEnumerationInformation();
199 }
200 }
201
202 void
203 fetchFaceStatusInformation()
204 {
205 m_buffer = make_shared<OBufferStream>();
206
207 Interest interest("/localhost/nfd/faces/list");
208 interest.setChildSelector(1);
209 interest.setMustBeFresh(true);
210
211 m_face.expressInterest(interest,
212 bind(&NfdStatus::fetchSegments, this, _2,
213 &NfdStatus::afterFetchedFaceStatusInformation),
214 bind(&NfdStatus::onTimeout, this));
215 }
216
217 void
218 afterFetchedFibEnumerationInformation()
219 {
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700220 std::cout << "FIB:" << std::endl;
221
222 ConstBufferPtr buf = m_buffer->buf();
223
224 Block block;
225 size_t offset = 0;
226 while (offset < buf->size())
jeraldabrahamb6dde382014-03-19 18:58:09 -0700227 {
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700228 bool ok = Block::fromBuffer(buf, offset, block);
229 if (!ok)
jeraldabrahamb6dde382014-03-19 18:58:09 -0700230 {
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700231 std::cerr << "ERROR: cannot decode FibEntry TLV" << std::endl;
232 break;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700233 }
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700234 offset += block.size();
235
236 nfd::FibEntry fibEntry(block);
237
238 std::cout << " " << fibEntry.getPrefix() << " nexthops={";
239 for (std::list<nfd::NextHopRecord>::const_iterator
240 nextHop = fibEntry.getNextHopRecords().begin();
241 nextHop != fibEntry.getNextHopRecords().end();
242 ++nextHop)
243 {
244 if (nextHop != fibEntry.getNextHopRecords().begin())
245 std::cout << ", ";
246 std::cout << "faceid=" << nextHop->getFaceId()
247 << " (cost=" << nextHop->getCost() << ")";
248 }
249 std::cout << "}" << std::endl;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700250 }
251 }
252
253 void
254 fetchFibEnumerationInformation()
255 {
256 m_buffer = make_shared<OBufferStream>();
257
258 Interest interest("/localhost/nfd/fib/list");
259 interest.setChildSelector(1);
260 interest.setMustBeFresh(true);
261 m_face.expressInterest(interest,
262 bind(&NfdStatus::fetchSegments, this, _2,
263 &NfdStatus::afterFetchedFibEnumerationInformation),
264 bind(&NfdStatus::onTimeout, this));
265 }
266
267 void
268 fetchInformation()
269 {
270 if (!m_needVersionRetrieval &&
271 !m_needFaceStatusRetrieval &&
272 !m_needFibEnumerationRetrieval)
273 {
274 enableVersionRetrieval();
275 enableFaceStatusRetrieval();
276 enableFibEnumerationRetrieval();
277 }
278
279 if (m_needVersionRetrieval)
280 {
281 fetchVersionInformation();
282 }
283 else if (m_needFaceStatusRetrieval)
284 {
285 fetchFaceStatusInformation();
286 }
287 else if (m_needFibEnumerationRetrieval)
288 {
289 fetchFibEnumerationInformation();
290 }
291
292 m_face.processEvents();
293 }
294
295private:
296 std::string m_toolName;
297 bool m_needVersionRetrieval;
298 bool m_needFaceStatusRetrieval;
299 bool m_needFibEnumerationRetrieval;
300 Face m_face;
301
302 shared_ptr<OBufferStream> m_buffer;
303};
304
305}
306
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700307int main(int argc, char* argv[])
jeraldabrahamb6dde382014-03-19 18:58:09 -0700308{
309 int option;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700310 ndn::NfdStatus nfdStatus(argv[0]);
jeraldabrahamb6dde382014-03-19 18:58:09 -0700311
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700312 while ((option = getopt(argc, argv, "hvfbV")) != -1) {
jeraldabrahamb6dde382014-03-19 18:58:09 -0700313 switch (option) {
314 case 'h':
315 nfdStatus.usage();
Alexander Afanasyev60a7ba52014-03-23 11:23:06 -0700316 return 0;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700317 case 'v':
318 nfdStatus.enableVersionRetrieval();
319 break;
320 case 'f':
321 nfdStatus.enableFaceStatusRetrieval();
322 break;
323 case 'b':
324 nfdStatus.enableFibEnumerationRetrieval();
325 break;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700326 case 'V':
327 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
328 return 0;
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700329 default:
jeraldabrahamb6dde382014-03-19 18:58:09 -0700330 nfdStatus.usage();
331 return 1;
jeraldabrahamb6dde382014-03-19 18:58:09 -0700332 }
333 }
334
335 try {
336 nfdStatus.fetchInformation();
337 }
Alexander Afanasyev7b7dfdd2014-03-21 13:57:54 -0700338 catch (std::exception& e) {
jeraldabrahamb6dde382014-03-19 18:58:09 -0700339 std::cerr << "ERROR: " << e.what() << std::endl;
340 return 2;
341 }
342
343 return 0;
344}