31 #include <ndn-cxx/mgmt/nfd/status-dataset.hpp>
44 parser.
addAlias(
"route",
"list",
"");
48 .
setTitle(
"show routes toward a prefix")
76 auto nexthopIt = ctx.
args.find(
"nexthop");
77 std::set<uint64_t> nexthops;
80 if (nexthopIt != ctx.
args.end()) {
84 ctx.
exitCode =
static_cast<int>(res);
94 BOOST_ASSERT_MSG(
false,
"unexpected FindFace result");
101 listRoutesImpl(ctx, [&] (
const RibEntry&,
const Route& route) {
102 return (nexthops.empty() || nexthops.count(route.getFaceId()) > 0) &&
103 (!origin || route.getOrigin() == *origin);
110 auto prefix = ctx.
args.
get<Name>(
"prefix");
112 listRoutesImpl(ctx, [&] (
const RibEntry& entry,
const Route&) {
113 return entry.getName() == prefix;
118 RibModule::listRoutesImpl(
ExecuteContext& ctx,
const RoutePredicate& filter)
121 [&] (
const auto& dataset) {
122 bool hasRoute =
false;
123 for (
const RibEntry& entry : dataset) {
124 for (
const Route& route : entry.getRoutes()) {
125 if (filter(entry, route)) {
127 formatRouteText(ctx.
out, entry, route,
true);
135 ctx.
err <<
"Route not found\n";
141 ctx.
face.processEvents();
147 auto prefix = ctx.
args.
get<Name>(
"prefix");
148 auto nexthop = ctx.
args.at(
"nexthop");
149 auto origin = ctx.
args.
get<RouteOrigin>(
"origin", ndn::nfd::ROUTE_ORIGIN_STATIC);
150 auto cost = ctx.
args.
get<uint64_t>(
"cost", 0);
151 bool wantChildInherit = !ctx.
args.
get<
bool>(
"no-inherit",
false);
152 bool wantCapture = ctx.
args.
get<
bool>(
"capture",
false);
155 auto registerRoute = [&] (uint64_t faceId) {
156 ControlParameters registerParams;
162 .setFlags((wantChildInherit ? ndn::nfd::ROUTE_FLAG_CHILD_INHERIT : ndn::nfd::ROUTE_FLAGS_NONE) |
163 (wantCapture ? ndn::nfd::ROUTE_FLAG_CAPTURE : ndn::nfd::ROUTE_FLAGS_NONE));
165 registerParams.setExpirationPeriod(time::milliseconds(*expiresMillis));
168 ctx.
controller.start<ndn::nfd::RibRegisterCommand>(
170 [&] (
const ControlParameters& resp) {
172 ctx.
out <<
"route-add-accepted ";
174 ctx.
out << ia(
"prefix") << resp.getName()
175 << ia(
"nexthop") << resp.getFaceId()
176 << ia(
"origin") << resp.getOrigin()
177 << ia(
"cost") << resp.getCost()
178 << ia(
"flags") <<
static_cast<ndn::nfd::RouteFlags
>(resp.getFlags());
179 if (resp.hasExpirationPeriod()) {
180 ctx.
out << ia(
"expires") << text::formatDuration<time::milliseconds>(resp.getExpirationPeriod()) <<
"\n";
183 ctx.
out<< ia(
"expires") <<
"never\n";
190 auto handleFaceNotFound = [&] {
191 const FaceUri* faceUri = std::any_cast<FaceUri>(&nexthop);
192 if (faceUri ==
nullptr) {
193 ctx.
err <<
"Face not found\n";
197 if (faceUri->getScheme() ==
"ether") {
200 ctx.
err <<
"Unable to implicitly create Ethernet faces\n";
201 ctx.
err <<
"Please create the face with 'nfdc face create' before adding the route\n";
205 auto [canonized, error] =
canonize(ctx, *faceUri);
209 ctx.
exitCode =
static_cast<int>(canonizationError.first);
210 ctx.
err << canonizationError.second <<
'\n';
214 ControlParameters faceCreateParams;
215 faceCreateParams.setUri(canonized->toString());
217 ctx.
controller.start<ndn::nfd::FaceCreateCommand>(
219 [&] (
const ControlParameters& resp) {
221 registerRoute(resp.getFaceId());
230 ctx.
exitCode =
static_cast<int>(res);
241 handleFaceNotFound();
244 ctx.
err <<
"Multiple faces match specified remote FaceUri. Re-run the command with a FaceId:";
249 BOOST_ASSERT_MSG(
false,
"unexpected FindFace result");
253 ctx.
face.processEvents();
259 auto prefix = ctx.
args.
get<Name>(
"prefix");
260 auto nexthop = ctx.
args.at(
"nexthop");
261 auto origin = ctx.
args.
get<RouteOrigin>(
"origin", ndn::nfd::ROUTE_ORIGIN_STATIC);
266 ctx.
exitCode =
static_cast<int>(res);
273 ctx.
err << findFace.getErrorReason() <<
'\n';
276 BOOST_ASSERT_MSG(
false,
"unexpected FindFace result");
280 for (uint64_t faceId : findFace.getFaceIds()) {
281 ControlParameters unregisterParams;
287 ctx.
controller.start<ndn::nfd::RibUnregisterCommand>(
289 [&] (
const ControlParameters& resp) {
290 ctx.
out <<
"route-removed ";
292 ctx.
out << ia(
"prefix") << resp.getName()
293 << ia(
"nexthop") << resp.getFaceId()
294 << ia(
"origin") << resp.getOrigin()
301 ctx.
face.processEvents();
306 const std::function<
void()>& onSuccess,
307 const ndn::nfd::DatasetFailureCallback& onFailure,
308 const CommandOptions& options)
310 controller.fetch<ndn::nfd::RibDataset>(
311 [
this, onSuccess] (
const auto& result) {
322 for (
const RibEntry& item : m_status) {
323 this->formatItemXml(os, item);
329 RibModule::formatItemXml(std::ostream& os,
const RibEntry& item)
const
333 os <<
"<prefix>" <<
xml::Text{item.getName().toUri()} <<
"</prefix>";
336 for (
const Route& route : item.getRoutes()) {
338 <<
"<faceId>" << route.getFaceId() <<
"</faceId>"
339 <<
"<origin>" << route.getOrigin() <<
"</origin>"
340 <<
"<cost>" << route.getCost() <<
"</cost>";
341 if (route.getFlags() == ndn::nfd::ROUTE_FLAGS_NONE) {
346 if (route.isChildInherit()) {
347 os <<
"<childInherit/>";
349 if (route.isRibCapture()) {
350 os <<
"<ribCapture/>";
354 if (route.hasExpirationPeriod()) {
355 os <<
"<expirationPeriod>"
357 <<
"</expirationPeriod>";
370 for (
const RibEntry& item : m_status) {
372 formatEntryText(os, item);
378 RibModule::formatEntryText(std::ostream& os,
const RibEntry& entry)
380 os << entry.getName() <<
" routes={";
383 for (
const Route& route : entry.getRoutes()) {
385 formatRouteText(os, entry, route,
false);
392 RibModule::formatRouteText(std::ostream& os,
const RibEntry& entry,
const Route& route,
395 text::ItemAttributes ia;
398 os << ia(
"prefix") << entry.getName();
400 os << ia(
"nexthop") << route.getFaceId();
401 os << ia(
"origin") << route.getOrigin();
402 os << ia(
"cost") << route.getCost();
403 os << ia(
"flags") <<
static_cast<ndn::nfd::RouteFlags
>(route.
getFlags());
404 if (route.hasExpirationPeriod()) {
405 os << ia(
"expires") << text::formatDuration<time::seconds>(route.getExpirationPeriod());
408 os << ia(
"expires") <<
"never";
Represents a route for a name prefix.
std::underlying_type_t< ndn::nfd::RouteFlags > getFlags() const
Context for command execution.
std::ostream & out
output stream
ndn::nfd::DatasetFailureCallback makeDatasetFailureHandler(const std::string &datasetName)
ndn::nfd::Controller & controller
const CommandArguments & args
ndn::nfd::CommandFailureCallback makeCommandFailureHandler(const std::string &commandName)
int exitCode
program exit code
ndn::nfd::CommandOptions makeCommandOptions() const
std::ostream & err
error stream
Print attributes of an item.
Print different string on first and subsequent usage.