blob: 295ad3f6695f318c61fd09f00d5bf172a8aa2449 [file] [log] [blame]
Junxiao Shi38f4ce92016-08-04 10:01:52 +00001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Davide Pesavento26cbdbd2017-02-19 21:37:43 -05003 * Copyright (c) 2014-2017, Regents of the University of California,
Junxiao Shi38f4ce92016-08-04 10:01:52 +00004 * 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"
Junxiao Shi918e5d42017-02-25 03:58:21 +000027#include "find-face.hpp"
Junxiao Shi38f4ce92016-08-04 10:01:52 +000028#include "format-helpers.hpp"
29
30namespace nfd {
31namespace tools {
Junxiao Shi331ade72016-08-19 14:07:19 +000032namespace nfdc {
Junxiao Shi38f4ce92016-08-04 10:01:52 +000033
34void
Junxiao Shi918e5d42017-02-25 03:58:21 +000035RibModule::registerCommands(CommandParser& parser)
36{
37 CommandDefinition defRouteAdd("route", "add");
38 defRouteAdd
39 .setTitle("add a route")
40 .addArg("prefix", ArgValueType::NAME, Required::YES, Positional::YES)
41 .addArg("nexthop", ArgValueType::FACE_ID_OR_URI, Required::YES, Positional::YES)
42 .addArg("origin", ArgValueType::UNSIGNED, Required::NO, Positional::NO)
43 .addArg("cost", ArgValueType::UNSIGNED, Required::NO, Positional::NO)
44 .addArg("no-inherit", ArgValueType::NONE, Required::NO, Positional::NO)
45 .addArg("capture", ArgValueType::NONE, Required::NO, Positional::NO)
46 .addArg("expires", ArgValueType::UNSIGNED, Required::NO, Positional::NO);
47 parser.addCommand(defRouteAdd, &RibModule::add);
Junxiao Shi084b7952017-02-26 22:00:53 +000048
49 CommandDefinition defRouteRemove("route", "remove");
50 defRouteRemove
51 .setTitle("remove a route")
52 .addArg("prefix", ArgValueType::NAME, Required::YES, Positional::YES)
53 .addArg("nexthop", ArgValueType::FACE_ID_OR_URI, Required::YES, Positional::YES)
54 .addArg("origin", ArgValueType::UNSIGNED, Required::NO, Positional::NO);
55 parser.addCommand(defRouteRemove, &RibModule::remove);
Junxiao Shi918e5d42017-02-25 03:58:21 +000056}
57
58void
59RibModule::add(ExecuteContext& ctx)
60{
61 auto prefix = ctx.args.get<Name>("prefix");
62 const boost::any& nexthop = ctx.args.at("nexthop");
63 auto origin = ctx.args.get<uint64_t>("origin", ndn::nfd::ROUTE_ORIGIN_STATIC);
64 auto cost = ctx.args.get<uint64_t>("cost", 0);
65 bool wantChildInherit = !ctx.args.get<bool>("no-inherit", false);
66 bool wantCapture = ctx.args.get<bool>("capture", false);
67 auto expiresMillis = ctx.args.getOptional<uint64_t>("expires");
68
69 FindFace findFace(ctx);
70 FindFace::Code res = findFace.execute(nexthop);
71
72 ctx.exitCode = static_cast<int>(res);
73 switch (res) {
74 case FindFace::Code::OK:
75 break;
76 case FindFace::Code::ERROR:
77 case FindFace::Code::CANONIZE_ERROR:
78 case FindFace::Code::NOT_FOUND:
79 ctx.err << findFace.getErrorReason() << '\n';
80 return;
81 case FindFace::Code::AMBIGUOUS:
82 ctx.err << "Multiple faces match specified remote FaceUri. Re-run the command with a FaceId:";
83 findFace.printDisambiguation(ctx.err, FindFace::DisambiguationStyle::LOCAL_URI);
84 ctx.err << '\n';
85 return;
86 default:
87 BOOST_ASSERT_MSG(false, "unexpected FindFace result");
88 return;
89 }
90
91 ControlParameters registerParams;
92 registerParams
93 .setName(prefix)
94 .setFaceId(findFace.getFaceId())
95 .setOrigin(origin)
96 .setCost(cost)
97 .setFlags((wantChildInherit ? ndn::nfd::ROUTE_FLAG_CHILD_INHERIT : 0) |
98 (wantCapture ? ndn::nfd::ROUTE_FLAG_CAPTURE : 0));
99 if (expiresMillis) {
100 registerParams.setExpirationPeriod(time::milliseconds(*expiresMillis));
101 }
102
103 ctx.controller.start<ndn::nfd::RibRegisterCommand>(
104 registerParams,
105 [&] (const ControlParameters& resp) {
106 ctx.out << "route-add-accepted ";
107 text::ItemAttributes ia;
108 ctx.out << ia("prefix") << resp.getName()
109 << ia("nexthop") << resp.getFaceId()
110 << ia("origin") << resp.getOrigin()
111 << ia("cost") << resp.getCost()
112 << ia("flags") << static_cast<ndn::nfd::RouteFlags>(resp.getFlags());
113 if (resp.hasExpirationPeriod()) {
114 ctx.out << ia("expires") << resp.getExpirationPeriod().count() << "ms\n";
115 }
116 else {
117 ctx.out<< ia("expires") << "never\n";
118 }
119 },
120 ctx.makeCommandFailureHandler("adding route"),
121 ctx.makeCommandOptions());
122
123 ctx.face.processEvents();
124}
125
126void
Junxiao Shi084b7952017-02-26 22:00:53 +0000127RibModule::remove(ExecuteContext& ctx)
128{
129 auto prefix = ctx.args.get<Name>("prefix");
130 const boost::any& nexthop = ctx.args.at("nexthop");
131 auto origin = ctx.args.get<uint64_t>("origin", ndn::nfd::ROUTE_ORIGIN_STATIC);
132
133 FindFace findFace(ctx);
134 FindFace::Code res = findFace.execute(nexthop, true);
135
136 ctx.exitCode = static_cast<int>(res);
137 switch (res) {
138 case FindFace::Code::OK:
139 break;
140 case FindFace::Code::ERROR:
141 case FindFace::Code::CANONIZE_ERROR:
142 case FindFace::Code::NOT_FOUND:
143 ctx.err << findFace.getErrorReason() << '\n';
144 return;
145 default:
146 BOOST_ASSERT_MSG(false, "unexpected FindFace result");
147 return;
148 }
149
150 for (const FaceStatus& faceStatus : findFace.getResults()) {
151 ControlParameters unregisterParams;
152 unregisterParams
153 .setName(prefix)
154 .setFaceId(faceStatus.getFaceId())
155 .setOrigin(origin);
156
157 ctx.controller.start<ndn::nfd::RibUnregisterCommand>(
158 unregisterParams,
159 [&] (const ControlParameters& resp) {
160 ctx.out << "route-removed ";
161 text::ItemAttributes ia;
162 ctx.out << ia("prefix") << resp.getName()
163 << ia("nexthop") << resp.getFaceId()
164 << ia("origin") << resp.getOrigin()
165 << '\n';
166 },
167 ctx.makeCommandFailureHandler("removing route"),
168 ctx.makeCommandOptions());
169 }
170
171 ctx.face.processEvents();
172}
173
174void
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000175RibModule::fetchStatus(Controller& controller,
176 const function<void()>& onSuccess,
Junxiao Shi29b41282016-08-22 03:47:02 +0000177 const Controller::DatasetFailCallback& onFailure,
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000178 const CommandOptions& options)
179{
180 controller.fetch<ndn::nfd::RibDataset>(
181 [this, onSuccess] (const std::vector<RibEntry>& result) {
182 m_status = result;
183 onSuccess();
184 },
185 onFailure, options);
186}
187
188void
189RibModule::formatStatusXml(std::ostream& os) const
190{
191 os << "<rib>";
192 for (const RibEntry& item : m_status) {
193 this->formatItemXml(os, item);
194 }
195 os << "</rib>";
196}
197
198void
199RibModule::formatItemXml(std::ostream& os, const RibEntry& item) const
200{
201 os << "<ribEntry>";
202
203 os << "<prefix>" << xml::Text{item.getName().toUri()} << "</prefix>";
204
205 os << "<routes>";
206 for (const Route& route : item.getRoutes()) {
207 os << "<route>"
208 << "<faceId>" << route.getFaceId() << "</faceId>"
209 << "<origin>" << route.getOrigin() << "</origin>"
210 << "<cost>" << route.getCost() << "</cost>";
211 if (route.getFlags() == ndn::nfd::ROUTE_FLAGS_NONE) {
212 os << "<flags/>";
213 }
214 else {
215 os << "<flags>";
216 if (route.isChildInherit()) {
217 os << "<childInherit/>";
218 }
219 if (route.isRibCapture()) {
220 os << "<ribCapture/>";
221 }
222 os << "</flags>";
223 }
Davide Pesavento26cbdbd2017-02-19 21:37:43 -0500224 if (route.hasExpirationPeriod()) {
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000225 os << "<expirationPeriod>"
226 << xml::formatDuration(route.getExpirationPeriod())
227 << "</expirationPeriod>";
228 }
229 os << "</route>";
230 }
231 os << "</routes>";
232
233 os << "</ribEntry>";
234}
235
236void
237RibModule::formatStatusText(std::ostream& os) const
238{
239 os << "RIB:\n";
240 for (const RibEntry& item : m_status) {
241 this->formatItemText(os, item);
242 }
243}
244
245void
246RibModule::formatItemText(std::ostream& os, const RibEntry& item) const
247{
248 os << " " << item.getName() << " route={";
249
250 text::Separator sep(", ");
251 for (const Route& route : item.getRoutes()) {
252 os << sep
253 << "faceid=" << route.getFaceId()
254 << " (origin=" << route.getOrigin()
255 << " cost=" << route.getCost();
Davide Pesavento26cbdbd2017-02-19 21:37:43 -0500256 if (route.hasExpirationPeriod()) {
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000257 os << " expires=" << text::formatDuration(route.getExpirationPeriod());
258 }
259 if (route.isChildInherit()) {
260 os << " ChildInherit";
261 }
262 if (route.isRibCapture()) {
263 os << " RibCapture";
264 }
265 os << ")";
266 }
267
268 os << "}";
269 os << "\n";
270}
271
Junxiao Shi331ade72016-08-19 14:07:19 +0000272} // namespace nfdc
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000273} // namespace tools
274} // namespace nfd