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 
44  CommandDefinition defRouteShow("route", "show");
45  defRouteShow
46  .setTitle("show routes toward a prefix")
48  parser.addCommand(defRouteShow, &RibModule::show);
49 
50  CommandDefinition defRouteAdd("route", "add");
51  defRouteAdd
52  .setTitle("add a route")
60  parser.addCommand(defRouteAdd, &RibModule::add);
61 
62  CommandDefinition defRouteRemove("route", "remove");
63  defRouteRemove
64  .setTitle("remove a route")
68  parser.addCommand(defRouteRemove, &RibModule::remove);
69 }
70 
71 void
73 {
74  auto nexthopIt = ctx.args.find("nexthop");
75  std::set<uint64_t> nexthops;
76  auto origin = ctx.args.getOptional<RouteOrigin>("origin");
77 
78  if (nexthopIt != ctx.args.end()) {
79  FindFace findFace(ctx);
80  FindFace::Code res = findFace.execute(nexthopIt->second, true);
81 
82  ctx.exitCode = static_cast<int>(res);
83  switch (res) {
84  case FindFace::Code::OK:
85  break;
89  ctx.err << findFace.getErrorReason() << '\n';
90  return;
91  default:
92  BOOST_ASSERT_MSG(false, "unexpected FindFace result");
93  return;
94  }
95 
96  nexthops = findFace.getFaceIds();
97  }
98 
99  listRoutesImpl(ctx, [&] (const RibEntry& entry, const Route& route) {
100  return (nexthops.empty() || nexthops.count(route.getFaceId()) > 0) &&
101  (!origin || route.getOrigin() == *origin);
102  });
103 }
104 
105 void
107 {
108  auto prefix = ctx.args.get<Name>("prefix");
109 
110  listRoutesImpl(ctx, [&] (const RibEntry& entry, const Route& route) {
111  return entry.getName() == prefix;
112  });
113 }
114 
115 void
116 RibModule::listRoutesImpl(ExecuteContext& ctx, const RoutePredicate& filter)
117 {
118  ctx.controller.fetch<ndn::nfd::RibDataset>(
119  [&] (const std::vector<RibEntry>& dataset) {
120  bool hasRoute = false;
121  for (const RibEntry& entry : dataset) {
122  for (const Route& route : entry.getRoutes()) {
123  if (filter(entry, route)) {
124  hasRoute = true;
125  formatRouteText(ctx.out, entry, route, true);
126  ctx.out << '\n';
127  }
128  }
129  }
130 
131  if (!hasRoute) {
132  ctx.exitCode = 6;
133  ctx.err << "Route not found\n";
134  }
135  },
136  ctx.makeDatasetFailureHandler("RIB dataset"),
137  ctx.makeCommandOptions());
138 
139  ctx.face.processEvents();
140 }
141 
142 void
144 {
145  auto prefix = ctx.args.get<Name>("prefix");
146  const boost::any& nexthop = ctx.args.at("nexthop");
147  auto origin = ctx.args.get<RouteOrigin>("origin", ndn::nfd::ROUTE_ORIGIN_STATIC);
148  auto cost = ctx.args.get<uint64_t>("cost", 0);
149  bool wantChildInherit = !ctx.args.get<bool>("no-inherit", false);
150  bool wantCapture = ctx.args.get<bool>("capture", false);
151  auto expiresMillis = ctx.args.getOptional<uint64_t>("expires");
152 
153  FindFace findFace(ctx);
154  FindFace::Code res = findFace.execute(nexthop);
155 
156  ctx.exitCode = static_cast<int>(res);
157  switch (res) {
158  case FindFace::Code::OK:
159  break;
163  ctx.err << findFace.getErrorReason() << '\n';
164  return;
166  ctx.err << "Multiple faces match specified remote FaceUri. Re-run the command with a FaceId:";
167  findFace.printDisambiguation(ctx.err, FindFace::DisambiguationStyle::LOCAL_URI);
168  ctx.err << '\n';
169  return;
170  default:
171  BOOST_ASSERT_MSG(false, "unexpected FindFace result");
172  return;
173  }
174 
175  ControlParameters registerParams;
176  registerParams
177  .setName(prefix)
178  .setFaceId(findFace.getFaceId())
179  .setOrigin(origin)
180  .setCost(cost)
181  .setFlags((wantChildInherit ? ndn::nfd::ROUTE_FLAG_CHILD_INHERIT : ndn::nfd::ROUTE_FLAGS_NONE) |
182  (wantCapture ? ndn::nfd::ROUTE_FLAG_CAPTURE : ndn::nfd::ROUTE_FLAGS_NONE));
183  if (expiresMillis) {
184  registerParams.setExpirationPeriod(time::milliseconds(*expiresMillis));
185  }
186 
187  ctx.controller.start<ndn::nfd::RibRegisterCommand>(
188  registerParams,
189  [&] (const ControlParameters& resp) {
190  ctx.out << "route-add-accepted ";
192  ctx.out << ia("prefix") << resp.getName()
193  << ia("nexthop") << resp.getFaceId()
194  << ia("origin") << resp.getOrigin()
195  << ia("cost") << resp.getCost()
196  << ia("flags") << static_cast<ndn::nfd::RouteFlags>(resp.getFlags());
197  if (resp.hasExpirationPeriod()) {
198  ctx.out << ia("expires") << text::formatDuration<time::milliseconds>(resp.getExpirationPeriod()) << "\n";
199  }
200  else {
201  ctx.out<< ia("expires") << "never\n";
202  }
203  },
204  ctx.makeCommandFailureHandler("adding route"),
205  ctx.makeCommandOptions());
206 
207  ctx.face.processEvents();
208 }
209 
210 void
212 {
213  auto prefix = ctx.args.get<Name>("prefix");
214  const boost::any& nexthop = ctx.args.at("nexthop");
215  auto origin = ctx.args.get<RouteOrigin>("origin", ndn::nfd::ROUTE_ORIGIN_STATIC);
216 
217  FindFace findFace(ctx);
218  FindFace::Code res = findFace.execute(nexthop, true);
219 
220  ctx.exitCode = static_cast<int>(res);
221  switch (res) {
222  case FindFace::Code::OK:
223  break;
227  ctx.err << findFace.getErrorReason() << '\n';
228  return;
229  default:
230  BOOST_ASSERT_MSG(false, "unexpected FindFace result");
231  return;
232  }
233 
234  for (uint64_t faceId : findFace.getFaceIds()) {
235  ControlParameters unregisterParams;
236  unregisterParams
237  .setName(prefix)
238  .setFaceId(faceId)
239  .setOrigin(origin);
240 
241  ctx.controller.start<ndn::nfd::RibUnregisterCommand>(
242  unregisterParams,
243  [&] (const ControlParameters& resp) {
244  ctx.out << "route-removed ";
246  ctx.out << ia("prefix") << resp.getName()
247  << ia("nexthop") << resp.getFaceId()
248  << ia("origin") << resp.getOrigin()
249  << '\n';
250  },
251  ctx.makeCommandFailureHandler("removing route"),
252  ctx.makeCommandOptions());
253  }
254 
255  ctx.face.processEvents();
256 }
257 
258 void
259 RibModule::fetchStatus(Controller& controller,
260  const function<void()>& onSuccess,
261  const Controller::DatasetFailCallback& onFailure,
262  const CommandOptions& options)
263 {
264  controller.fetch<ndn::nfd::RibDataset>(
265  [this, onSuccess] (const std::vector<RibEntry>& result) {
266  m_status = result;
267  onSuccess();
268  },
269  onFailure, options);
270 }
271 
272 void
273 RibModule::formatStatusXml(std::ostream& os) const
274 {
275  os << "<rib>";
276  for (const RibEntry& item : m_status) {
277  this->formatItemXml(os, item);
278  }
279  os << "</rib>";
280 }
281 
282 void
283 RibModule::formatItemXml(std::ostream& os, const RibEntry& item) const
284 {
285  os << "<ribEntry>";
286 
287  os << "<prefix>" << xml::Text{item.getName().toUri()} << "</prefix>";
288 
289  os << "<routes>";
290  for (const Route& route : item.getRoutes()) {
291  os << "<route>"
292  << "<faceId>" << route.getFaceId() << "</faceId>"
293  << "<origin>" << route.getOrigin() << "</origin>"
294  << "<cost>" << route.getCost() << "</cost>";
295  if (route.getFlags() == ndn::nfd::ROUTE_FLAGS_NONE) {
296  os << "<flags/>";
297  }
298  else {
299  os << "<flags>";
300  if (route.isChildInherit()) {
301  os << "<childInherit/>";
302  }
303  if (route.isRibCapture()) {
304  os << "<ribCapture/>";
305  }
306  os << "</flags>";
307  }
308  if (route.hasExpirationPeriod()) {
309  os << "<expirationPeriod>"
310  << xml::formatDuration(time::duration_cast<time::seconds>(route.getExpirationPeriod()))
311  << "</expirationPeriod>";
312  }
313  os << "</route>";
314  }
315  os << "</routes>";
316 
317  os << "</ribEntry>";
318 }
319 
320 void
321 RibModule::formatStatusText(std::ostream& os) const
322 {
323  os << "RIB:\n";
324  for (const RibEntry& item : m_status) {
325  os << " ";
326  formatEntryText(os, item);
327  os << '\n';
328  }
329 }
330 
331 void
332 RibModule::formatEntryText(std::ostream& os, const RibEntry& entry)
333 {
334  os << entry.getName() << " routes={";
335 
336  text::Separator sep(", ");
337  for (const Route& route : entry.getRoutes()) {
338  os << sep;
339  formatRouteText(os, entry, route, false);
340  }
341 
342  os << "}";
343 }
344 
345 void
346 RibModule::formatRouteText(std::ostream& os, const RibEntry& entry, const Route& route,
347  bool includePrefix)
348 {
350 
351  if (includePrefix) {
352  os << ia("prefix") << entry.getName();
353  }
354  os << ia("nexthop") << route.getFaceId();
355  os << ia("origin") << route.getOrigin();
356  os << ia("cost") << route.getCost();
357  os << ia("flags") << static_cast<ndn::nfd::RouteFlags>(route.getFlags());
358  if (route.hasExpirationPeriod()) {
359  os << ia("expires") << text::formatDuration<time::seconds>(route.getExpirationPeriod());
360  }
361  else {
362  os << ia("expires") << "never";
363  }
364 }
365 
366 } // namespace nfdc
367 } // namespace tools
368 } // 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:72
void formatStatusText(std::ostream &os) const override
format collected status as text
Definition: rib-module.cpp:321
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:211
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:273
Code execute(const FaceUri &faceUri, bool allowMulti=false)
find face by FaceUri
Definition: find-face.cpp:42
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
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
ndn::optional< T > getOptional(const std::string &key) const
argument is optional
static void add(ExecuteContext &ctx)
the &#39;route add&#39; command
Definition: rib-module.cpp:143
const std::string & getErrorReason() const
Definition: find-face.hpp:113
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:106
void fetchStatus(Controller &controller, const function< void()> &onSuccess, const Controller::DatasetFailCallback &onFailure, const CommandOptions &options) override
collect status from NFD
Definition: rib-module.cpp:259
std::set< uint64_t > getFaceIds() const
Definition: find-face.cpp:152