tools: nfdc route add command
This commit also simplifies 'nfdc face destroy' and its test case.
'nfdc register' is deprecated in favor of 'nfdc route add'.
refs #3866
Change-Id: I1de5cc0bc956d57b0793da920c1e87b3580a3297
diff --git a/tools/nfdc/available-commands.cpp b/tools/nfdc/available-commands.cpp
index 586da48..d6782ac 100644
--- a/tools/nfdc/available-commands.cpp
+++ b/tools/nfdc/available-commands.cpp
@@ -24,11 +24,12 @@
*/
#include "available-commands.hpp"
-#include "help.hpp"
-#include "status.hpp"
#include "face-module.hpp"
-#include "legacy-status.hpp"
+#include "help.hpp"
#include "legacy-nfdc.hpp"
+#include "legacy-status.hpp"
+#include "rib-module.hpp"
+#include "status.hpp"
namespace nfd {
namespace tools {
@@ -40,6 +41,7 @@
registerHelpCommand(parser);
registerStatusCommands(parser);
FaceModule::registerCommands(parser);
+ RibModule::registerCommands(parser);
registerLegacyStatusCommand(parser);
@@ -50,7 +52,7 @@
std::string replacementCommand; ///< replacement for deprecated legacy subcommand
};
const std::vector<LegacyNfdcCommandDefinition> legacyNfdcSubcommands{
- {"register", "register a prefix", ""},
+ {"register", "register a prefix", "route add"},
{"unregister", "unregister a prefix", ""},
{"create", "create a face", "face create"},
{"destroy", "destroy a face", "face destroy"},
diff --git a/tools/nfdc/face-module.cpp b/tools/nfdc/face-module.cpp
index 216ded6..f0c9dfc 100644
--- a/tools/nfdc/face-module.cpp
+++ b/tools/nfdc/face-module.cpp
@@ -209,17 +209,10 @@
void
FaceModule::destroy(ExecuteContext& ctx)
{
- const boost::any faceIdOrUri = ctx.args.at("face");
+ const boost::any& faceIdOrUri = ctx.args.at("face");
FindFace findFace(ctx);
- FindFace::Code res = FindFace::Code::ERROR;
- const uint64_t* faceId = boost::any_cast<uint64_t>(&faceIdOrUri);
- if (faceId != nullptr) {
- res = findFace.execute(*faceId);
- }
- else {
- res = findFace.execute(boost::any_cast<FaceUri>(faceIdOrUri));
- }
+ FindFace::Code res = findFace.execute(faceIdOrUri);
ctx.exitCode = static_cast<int>(res);
switch (res) {
diff --git a/tools/nfdc/find-face.cpp b/tools/nfdc/find-face.cpp
index 520ea92..d877e81 100644
--- a/tools/nfdc/find-face.cpp
+++ b/tools/nfdc/find-face.cpp
@@ -55,6 +55,18 @@
}
FindFace::Code
+FindFace::execute(const boost::any& faceIdOrUri)
+{
+ const uint64_t* faceId = boost::any_cast<uint64_t>(&faceIdOrUri);
+ if (faceId != nullptr) {
+ return this->execute(*faceId);
+ }
+ else {
+ return this->execute(boost::any_cast<FaceUri>(faceIdOrUri));
+ }
+}
+
+FindFace::Code
FindFace::execute(const FaceQueryFilter& filter, bool allowMulti)
{
BOOST_ASSERT(m_res == Code::NOT_STARTED);
diff --git a/tools/nfdc/find-face.hpp b/tools/nfdc/find-face.hpp
index 57eb0f0..45c3f1e 100644
--- a/tools/nfdc/find-face.hpp
+++ b/tools/nfdc/find-face.hpp
@@ -70,6 +70,14 @@
Code
execute(uint64_t faceId);
+ /** \brief find face by FaceId or FaceUri
+ * \param faceIdOrUri a boost::any that contains uint64_t or FaceUri
+ * \note allowMulti will be set to false
+ * \throw boost::bad_any_cast faceIdOrUri is neither uint64_t nor FaceUri
+ */
+ Code
+ execute(const boost::any& faceIdOrUri);
+
/** \brief find face by FaceQueryFilter
* \pre execute has not been invoked
*/
diff --git a/tools/nfdc/rib-module.cpp b/tools/nfdc/rib-module.cpp
index 454dc1e..b85410c 100644
--- a/tools/nfdc/rib-module.cpp
+++ b/tools/nfdc/rib-module.cpp
@@ -24,6 +24,7 @@
*/
#include "rib-module.hpp"
+#include "find-face.hpp"
#include "format-helpers.hpp"
namespace nfd {
@@ -31,6 +32,90 @@
namespace nfdc {
void
+RibModule::registerCommands(CommandParser& parser)
+{
+ CommandDefinition defRouteAdd("route", "add");
+ defRouteAdd
+ .setTitle("add a route")
+ .addArg("prefix", ArgValueType::NAME, Required::YES, Positional::YES)
+ .addArg("nexthop", ArgValueType::FACE_ID_OR_URI, Required::YES, Positional::YES)
+ .addArg("origin", ArgValueType::UNSIGNED, Required::NO, Positional::NO)
+ .addArg("cost", ArgValueType::UNSIGNED, Required::NO, Positional::NO)
+ .addArg("no-inherit", ArgValueType::NONE, Required::NO, Positional::NO)
+ .addArg("capture", ArgValueType::NONE, Required::NO, Positional::NO)
+ .addArg("expires", ArgValueType::UNSIGNED, Required::NO, Positional::NO);
+ parser.addCommand(defRouteAdd, &RibModule::add);
+}
+
+void
+RibModule::add(ExecuteContext& ctx)
+{
+ auto prefix = ctx.args.get<Name>("prefix");
+ const boost::any& nexthop = ctx.args.at("nexthop");
+ auto origin = ctx.args.get<uint64_t>("origin", ndn::nfd::ROUTE_ORIGIN_STATIC);
+ auto cost = ctx.args.get<uint64_t>("cost", 0);
+ bool wantChildInherit = !ctx.args.get<bool>("no-inherit", false);
+ bool wantCapture = ctx.args.get<bool>("capture", false);
+ auto expiresMillis = ctx.args.getOptional<uint64_t>("expires");
+
+ FindFace findFace(ctx);
+ FindFace::Code res = findFace.execute(nexthop);
+
+ ctx.exitCode = static_cast<int>(res);
+ switch (res) {
+ case FindFace::Code::OK:
+ break;
+ case FindFace::Code::ERROR:
+ case FindFace::Code::CANONIZE_ERROR:
+ case FindFace::Code::NOT_FOUND:
+ ctx.err << findFace.getErrorReason() << '\n';
+ return;
+ case FindFace::Code::AMBIGUOUS:
+ ctx.err << "Multiple faces match specified remote FaceUri. Re-run the command with a FaceId:";
+ findFace.printDisambiguation(ctx.err, FindFace::DisambiguationStyle::LOCAL_URI);
+ ctx.err << '\n';
+ return;
+ default:
+ BOOST_ASSERT_MSG(false, "unexpected FindFace result");
+ return;
+ }
+
+ ControlParameters registerParams;
+ registerParams
+ .setName(prefix)
+ .setFaceId(findFace.getFaceId())
+ .setOrigin(origin)
+ .setCost(cost)
+ .setFlags((wantChildInherit ? ndn::nfd::ROUTE_FLAG_CHILD_INHERIT : 0) |
+ (wantCapture ? ndn::nfd::ROUTE_FLAG_CAPTURE : 0));
+ if (expiresMillis) {
+ registerParams.setExpirationPeriod(time::milliseconds(*expiresMillis));
+ }
+
+ ctx.controller.start<ndn::nfd::RibRegisterCommand>(
+ registerParams,
+ [&] (const ControlParameters& resp) {
+ ctx.out << "route-add-accepted ";
+ text::ItemAttributes ia;
+ ctx.out << ia("prefix") << resp.getName()
+ << ia("nexthop") << resp.getFaceId()
+ << ia("origin") << resp.getOrigin()
+ << ia("cost") << resp.getCost()
+ << ia("flags") << static_cast<ndn::nfd::RouteFlags>(resp.getFlags());
+ if (resp.hasExpirationPeriod()) {
+ ctx.out << ia("expires") << resp.getExpirationPeriod().count() << "ms\n";
+ }
+ else {
+ ctx.out<< ia("expires") << "never\n";
+ }
+ },
+ ctx.makeCommandFailureHandler("adding route"),
+ ctx.makeCommandOptions());
+
+ ctx.face.processEvents();
+}
+
+void
RibModule::fetchStatus(Controller& controller,
const function<void()>& onSuccess,
const Controller::DatasetFailCallback& onFailure,
diff --git a/tools/nfdc/rib-module.hpp b/tools/nfdc/rib-module.hpp
index 85230aa..cca1ef4 100644
--- a/tools/nfdc/rib-module.hpp
+++ b/tools/nfdc/rib-module.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2016, Regents of the University of California,
+ * Copyright (c) 2014-2017, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -27,6 +27,7 @@
#define NFD_TOOLS_NFDC_RIB_MODULE_HPP
#include "module.hpp"
+#include "command-parser.hpp"
namespace nfd {
namespace tools {
@@ -41,13 +42,23 @@
class RibModule : public Module, noncopyable
{
public:
- virtual void
+ /** \brief register 'route list', 'route show', 'route add', 'route remove' commands
+ */
+ static void
+ registerCommands(CommandParser& parser);
+
+ /** \brief the 'route add' command
+ */
+ static void
+ add(ExecuteContext& ctx);
+
+ void
fetchStatus(Controller& controller,
const function<void()>& onSuccess,
const Controller::DatasetFailCallback& onFailure,
const CommandOptions& options) override;
- virtual void
+ void
formatStatusXml(std::ostream& os) const override;
/** \brief format a single status item as XML
@@ -57,7 +68,7 @@
void
formatItemXml(std::ostream& os, const RibEntry& item) const;
- virtual void
+ void
formatStatusText(std::ostream& os) const override;
/** \brief format a single status item as text