rib-module.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014-2018, 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.
10  *
11  * 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 
26 #include "rib-module.hpp"
27 #include "find-face.hpp"
28 #include "format-helpers.hpp"
29 
30 namespace nfd {
31 namespace tools {
32 namespace nfdc {
33 
34 void
36 {
37  CommandDefinition defRouteList("route", "list");
38  defRouteList
39  .setTitle("print RIB routes")
42  parser.addCommand(defRouteList, &RibModule::list);
43  parser.addAlias("route", "list", "");
44 
45  CommandDefinition defRouteShow("route", "show");
46  defRouteShow
47  .setTitle("show routes toward a prefix")
49  parser.addCommand(defRouteShow, &RibModule::show);
50 
51  CommandDefinition defRouteAdd("route", "add");
52  defRouteAdd
53  .setTitle("add a route")
61  parser.addCommand(defRouteAdd, &RibModule::add);
62 
63  CommandDefinition defRouteRemove("route", "remove");
64  defRouteRemove
65  .setTitle("remove a route")
69  parser.addCommand(defRouteRemove, &RibModule::remove);
70 }
71 
72 void
74 {
75  auto nexthopIt = ctx.args.find("nexthop");
76  std::set<uint64_t> nexthops;
77  auto origin = ctx.args.getOptional<RouteOrigin>("origin");
78 
79  if (nexthopIt != ctx.args.end()) {
80  FindFace findFace(ctx);
81  FindFace::Code res = findFace.execute(nexthopIt->second, true);
82 
83  ctx.exitCode = static_cast<int>(res);
84  switch (res) {
85  case FindFace::Code::OK:
86  break;
90  ctx.err << findFace.getErrorReason() << '\n';
91  return;
92  default:
93  BOOST_ASSERT_MSG(false, "unexpected FindFace result");
94  return;
95  }
96 
97  nexthops = findFace.getFaceIds();
98  }
99 
100  listRoutesImpl(ctx, [&] (const RibEntry& entry, const Route& route) {
101  return (nexthops.empty() || nexthops.count(route.getFaceId()) > 0) &&
102  (!origin || route.getOrigin() == *origin);
103  });
104 }
105 
106 void
108 {
109  auto prefix = ctx.args.get<Name>("prefix");
110 
111  listRoutesImpl(ctx, [&] (const RibEntry& entry, const Route& route) {
112  return entry.getName() == prefix;
113  });
114 }
115 
116 void
117 RibModule::listRoutesImpl(ExecuteContext& ctx, const RoutePredicate& filter)
118 {
119  ctx.controller.fetch<ndn::nfd::RibDataset>(
120  [&] (const std::vector<RibEntry>& dataset) {
121  bool hasRoute = false;
122  for (const RibEntry& entry : dataset) {
123  for (const Route& route : entry.getRoutes()) {
124  if (filter(entry, route)) {
125  hasRoute = true;
126  formatRouteText(ctx.out, entry, route, true);
127  ctx.out << '\n';
128  }
129  }
130  }
131 
132  if (!hasRoute) {
133  ctx.exitCode = 6;
134  ctx.err << "Route not found\n";
135  }
136  },
137  ctx.makeDatasetFailureHandler("RIB dataset"),
138  ctx.makeCommandOptions());
139 
140  ctx.face.processEvents();
141 }
142 
143 void
145 {
146  auto prefix = ctx.args.get<Name>("prefix");
147  auto nexthop = ctx.args.at("nexthop");
148  auto origin = ctx.args.get<RouteOrigin>("origin", ndn::nfd::ROUTE_ORIGIN_STATIC);
149  auto cost = ctx.args.get<uint64_t>("cost", 0);
150  bool wantChildInherit = !ctx.args.get<bool>("no-inherit", false);
151  bool wantCapture = ctx.args.get<bool>("capture", false);
152  auto expiresMillis = ctx.args.getOptional<uint64_t>("expires");
153 
154  FindFace findFace(ctx);
155  FindFace::Code res = findFace.execute(nexthop);
156 
157  ctx.exitCode = static_cast<int>(res);
158  switch (res) {
159  case FindFace::Code::OK:
160  break;
164  ctx.err << findFace.getErrorReason() << '\n';
165  return;
167  ctx.err << "Multiple faces match specified remote FaceUri. Re-run the command with a FaceId:";
168  findFace.printDisambiguation(ctx.err, FindFace::DisambiguationStyle::LOCAL_URI);
169  ctx.err << '\n';
170  return;
171  default:
172  BOOST_ASSERT_MSG(false, "unexpected FindFace result");
173  return;
174  }
175 
176  ControlParameters registerParams;
177  registerParams
178  .setName(prefix)
179  .setFaceId(findFace.getFaceId())
180  .setOrigin(origin)
181  .setCost(cost)
182  .setFlags((wantChildInherit ? ndn::nfd::ROUTE_FLAG_CHILD_INHERIT : ndn::nfd::ROUTE_FLAGS_NONE) |
183  (wantCapture ? ndn::nfd::ROUTE_FLAG_CAPTURE : ndn::nfd::ROUTE_FLAGS_NONE));
184  if (expiresMillis) {
185  registerParams.setExpirationPeriod(time::milliseconds(*expiresMillis));
186  }
187 
188  ctx.controller.start<ndn::nfd::RibRegisterCommand>(
189  registerParams,
190  [&] (const ControlParameters& resp) {
191  ctx.out << "route-add-accepted ";
193  ctx.out << ia("prefix") << resp.getName()
194  << ia("nexthop") << resp.getFaceId()
195  << ia("origin") << resp.getOrigin()
196  << ia("cost") << resp.getCost()
197  << ia("flags") << static_cast<ndn::nfd::RouteFlags>(resp.getFlags());
198  if (resp.hasExpirationPeriod()) {
199  ctx.out << ia("expires") << text::formatDuration<time::milliseconds>(resp.getExpirationPeriod()) << "\n";
200  }
201  else {
202  ctx.out<< ia("expires") << "never\n";
203  }
204  },
205  ctx.makeCommandFailureHandler("adding route"),
206  ctx.makeCommandOptions());
207 
208  ctx.face.processEvents();
209 }
210 
211 void
213 {
214  auto prefix = ctx.args.get<Name>("prefix");
215  auto nexthop = ctx.args.at("nexthop");
216  auto origin = ctx.args.get<RouteOrigin>("origin", ndn::nfd::ROUTE_ORIGIN_STATIC);
217 
218  FindFace findFace(ctx);
219  FindFace::Code res = findFace.execute(nexthop, true);
220 
221  ctx.exitCode = static_cast<int>(res);
222  switch (res) {
223  case FindFace::Code::OK:
224  break;
228  ctx.err << findFace.getErrorReason() << '\n';
229  return;
230  default:
231  BOOST_ASSERT_MSG(false, "unexpected FindFace result");
232  return;
233  }
234 
235  for (uint64_t faceId : findFace.getFaceIds()) {
236  ControlParameters unregisterParams;
237  unregisterParams
238  .setName(prefix)
239  .setFaceId(faceId)
240  .setOrigin(origin);
241 
242  ctx.controller.start<ndn::nfd::RibUnregisterCommand>(
243  unregisterParams,
244  [&] (const ControlParameters& resp) {
245  ctx.out << "route-removed ";
247  ctx.out << ia("prefix") << resp.getName()
248  << ia("nexthop") << resp.getFaceId()
249  << ia("origin") << resp.getOrigin()
250  << '\n';
251  },
252  ctx.makeCommandFailureHandler("removing route"),
253  ctx.makeCommandOptions());
254  }
255 
256  ctx.face.processEvents();
257 }
258 
259 void
260 RibModule::fetchStatus(Controller& controller,
261  const std::function<void()>& onSuccess,
262  const Controller::DatasetFailCallback& onFailure,
263  const CommandOptions& options)
264 {
265  controller.fetch<ndn::nfd::RibDataset>(
266  [this, onSuccess] (const std::vector<RibEntry>& result) {
267  m_status = result;
268  onSuccess();
269  },
270  onFailure, options);
271 }
272 
273 void
274 RibModule::formatStatusXml(std::ostream& os) const
275 {
276  os << "<rib>";
277  for (const RibEntry& item : m_status) {
278  this->formatItemXml(os, item);
279  }
280  os << "</rib>";
281 }
282 
283 void
284 RibModule::formatItemXml(std::ostream& os, const RibEntry& item) const
285 {
286  os << "<ribEntry>";
287 
288  os << "<prefix>" << xml::Text{item.getName().toUri()} << "</prefix>";
289 
290  os << "<routes>";
291  for (const Route& route : item.getRoutes()) {
292  os << "<route>"
293  << "<faceId>" << route.getFaceId() << "</faceId>"
294  << "<origin>" << route.getOrigin() << "</origin>"
295  << "<cost>" << route.getCost() << "</cost>";
296  if (route.getFlags() == ndn::nfd::ROUTE_FLAGS_NONE) {
297  os << "<flags/>";
298  }
299  else {
300  os << "<flags>";
301  if (route.isChildInherit()) {
302  os << "<childInherit/>";
303  }
304  if (route.isRibCapture()) {
305  os << "<ribCapture/>";
306  }
307  os << "</flags>";
308  }
309  if (route.hasExpirationPeriod()) {
310  os << "<expirationPeriod>"
311  << xml::formatDuration(time::duration_cast<time::seconds>(route.getExpirationPeriod()))
312  << "</expirationPeriod>";
313  }
314  os << "</route>";
315  }
316  os << "</routes>";
317 
318  os << "</ribEntry>";
319 }
320 
321 void
322 RibModule::formatStatusText(std::ostream& os) const
323 {
324  os << "RIB:\n";
325  for (const RibEntry& item : m_status) {
326  os << " ";
327  formatEntryText(os, item);
328  os << '\n';
329  }
330 }
331 
332 void
333 RibModule::formatEntryText(std::ostream& os, const RibEntry& entry)
334 {
335  os << entry.getName() << " routes={";
336 
337  text::Separator sep(", ");
338  for (const Route& route : entry.getRoutes()) {
339  os << sep;
340  formatRouteText(os, entry, route, false);
341  }
342 
343  os << "}";
344 }
345 
346 void
347 RibModule::formatRouteText(std::ostream& os, const RibEntry& entry, const Route& route,
348  bool includePrefix)
349 {
351 
352  if (includePrefix) {
353  os << ia("prefix") << entry.getName();
354  }
355  os << ia("nexthop") << route.getFaceId();
356  os << ia("origin") << route.getOrigin();
357  os << ia("cost") << route.getCost();
358  os << ia("flags") << static_cast<ndn::nfd::RouteFlags>(route.getFlags());
359  if (route.hasExpirationPeriod()) {
360  os << ia("expires") << text::formatDuration<time::seconds>(route.getExpirationPeriod());
361  }
362  else {
363  os << ia("expires") << "never";
364  }
365 }
366 
367 } // namespace nfdc
368 } // namespace tools
369 } // namespace nfd
const CommandArguments & args
std::string formatDuration(time::nanoseconds d)
ndn::nfd::CommandOptions makeCommandOptions() const
boolean argument without value
Controller::CommandFailCallback makeCommandFailureHandler(const std::string &commandName)
declares semantics of a command
std::ostream & out
output stream
context for command execution
static void list(ExecuteContext &ctx)
the &#39;route list&#39; command
Definition: rib-module.cpp:73
void formatStatusText(std::ostream &os) const override
format collected status as text
Definition: rib-module.cpp:322
T get(const std::string &key, const T &defaultValue=T()) const
found exactly one face, or found multiple faces when allowMulti is true
error during FaceUri canonization
Controller::DatasetFailCallback makeDatasetFailureHandler(const std::string &datasetName)
CommandDefinition & setTitle(const std::string &title)
set one-line description
found multiple faces and allowMulti is false
static void remove(ExecuteContext &ctx)
the &#39;route remove&#39; command
Definition: rib-module.cpp:212
Copyright (c) 2014-2015, Regents of the University of California, Arizona Board of Regents...
Definition: algorithm.hpp:32
procedure to find a face
Definition: find-face.hpp:40
void formatStatusXml(std::ostream &os) const override
format collected status as XML
Definition: rib-module.cpp:274
Code execute(const FaceUri &faceUri, bool allowMulti=false)
find face by FaceUri
Definition: find-face.cpp:43
CommandDefinition & addArg(const std::string &name, ArgValueType valueType, Required isRequired=Required::NO, Positional allowPositional=Positional::NO, const std::string &metavar="")
declare an argument
print attributes of an item
argument is required
optional< T > getOptional(const std::string &key) const
std::ostream & err
error stream
CommandParser & addCommand(const CommandDefinition &def, const ExecuteCommand &execute, std::underlying_type< AvailableIn >::type modes=AVAILABLE_IN_ALL)
add an available command
void fetchStatus(Controller &controller, const std::function< void()> &onSuccess, const Controller::DatasetFailCallback &onFailure, const CommandOptions &options) override
collect status from NFD
Definition: rib-module.cpp:260
argument is optional
static void add(ExecuteContext &ctx)
the &#39;route add&#39; command
Definition: rib-module.cpp:144
const std::string & getErrorReason() const
Definition: find-face.hpp:113
CommandParser & addAlias(const std::string &noun, const std::string &verb, const std::string &verb2)
add an alias "noun verb2" to existing command "noun verb"
print different string on first and subsequent usage
static void registerCommands(CommandParser &parser)
register &#39;route list&#39;, &#39;route show&#39;, &#39;route add&#39;, &#39;route remove&#39; commands
Definition: rib-module.cpp:35
static void show(ExecuteContext &ctx)
the &#39;route show&#39; command
Definition: rib-module.cpp:107
std::set< uint64_t > getFaceIds() const
Definition: find-face.cpp:153