blob: b85410c9d632eee1ebbc166addb99af1393e21f4 [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);
48}
49
50void
51RibModule::add(ExecuteContext& ctx)
52{
53 auto prefix = ctx.args.get<Name>("prefix");
54 const boost::any& nexthop = ctx.args.at("nexthop");
55 auto origin = ctx.args.get<uint64_t>("origin", ndn::nfd::ROUTE_ORIGIN_STATIC);
56 auto cost = ctx.args.get<uint64_t>("cost", 0);
57 bool wantChildInherit = !ctx.args.get<bool>("no-inherit", false);
58 bool wantCapture = ctx.args.get<bool>("capture", false);
59 auto expiresMillis = ctx.args.getOptional<uint64_t>("expires");
60
61 FindFace findFace(ctx);
62 FindFace::Code res = findFace.execute(nexthop);
63
64 ctx.exitCode = static_cast<int>(res);
65 switch (res) {
66 case FindFace::Code::OK:
67 break;
68 case FindFace::Code::ERROR:
69 case FindFace::Code::CANONIZE_ERROR:
70 case FindFace::Code::NOT_FOUND:
71 ctx.err << findFace.getErrorReason() << '\n';
72 return;
73 case FindFace::Code::AMBIGUOUS:
74 ctx.err << "Multiple faces match specified remote FaceUri. Re-run the command with a FaceId:";
75 findFace.printDisambiguation(ctx.err, FindFace::DisambiguationStyle::LOCAL_URI);
76 ctx.err << '\n';
77 return;
78 default:
79 BOOST_ASSERT_MSG(false, "unexpected FindFace result");
80 return;
81 }
82
83 ControlParameters registerParams;
84 registerParams
85 .setName(prefix)
86 .setFaceId(findFace.getFaceId())
87 .setOrigin(origin)
88 .setCost(cost)
89 .setFlags((wantChildInherit ? ndn::nfd::ROUTE_FLAG_CHILD_INHERIT : 0) |
90 (wantCapture ? ndn::nfd::ROUTE_FLAG_CAPTURE : 0));
91 if (expiresMillis) {
92 registerParams.setExpirationPeriod(time::milliseconds(*expiresMillis));
93 }
94
95 ctx.controller.start<ndn::nfd::RibRegisterCommand>(
96 registerParams,
97 [&] (const ControlParameters& resp) {
98 ctx.out << "route-add-accepted ";
99 text::ItemAttributes ia;
100 ctx.out << ia("prefix") << resp.getName()
101 << ia("nexthop") << resp.getFaceId()
102 << ia("origin") << resp.getOrigin()
103 << ia("cost") << resp.getCost()
104 << ia("flags") << static_cast<ndn::nfd::RouteFlags>(resp.getFlags());
105 if (resp.hasExpirationPeriod()) {
106 ctx.out << ia("expires") << resp.getExpirationPeriod().count() << "ms\n";
107 }
108 else {
109 ctx.out<< ia("expires") << "never\n";
110 }
111 },
112 ctx.makeCommandFailureHandler("adding route"),
113 ctx.makeCommandOptions());
114
115 ctx.face.processEvents();
116}
117
118void
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000119RibModule::fetchStatus(Controller& controller,
120 const function<void()>& onSuccess,
Junxiao Shi29b41282016-08-22 03:47:02 +0000121 const Controller::DatasetFailCallback& onFailure,
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000122 const CommandOptions& options)
123{
124 controller.fetch<ndn::nfd::RibDataset>(
125 [this, onSuccess] (const std::vector<RibEntry>& result) {
126 m_status = result;
127 onSuccess();
128 },
129 onFailure, options);
130}
131
132void
133RibModule::formatStatusXml(std::ostream& os) const
134{
135 os << "<rib>";
136 for (const RibEntry& item : m_status) {
137 this->formatItemXml(os, item);
138 }
139 os << "</rib>";
140}
141
142void
143RibModule::formatItemXml(std::ostream& os, const RibEntry& item) const
144{
145 os << "<ribEntry>";
146
147 os << "<prefix>" << xml::Text{item.getName().toUri()} << "</prefix>";
148
149 os << "<routes>";
150 for (const Route& route : item.getRoutes()) {
151 os << "<route>"
152 << "<faceId>" << route.getFaceId() << "</faceId>"
153 << "<origin>" << route.getOrigin() << "</origin>"
154 << "<cost>" << route.getCost() << "</cost>";
155 if (route.getFlags() == ndn::nfd::ROUTE_FLAGS_NONE) {
156 os << "<flags/>";
157 }
158 else {
159 os << "<flags>";
160 if (route.isChildInherit()) {
161 os << "<childInherit/>";
162 }
163 if (route.isRibCapture()) {
164 os << "<ribCapture/>";
165 }
166 os << "</flags>";
167 }
Davide Pesavento26cbdbd2017-02-19 21:37:43 -0500168 if (route.hasExpirationPeriod()) {
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000169 os << "<expirationPeriod>"
170 << xml::formatDuration(route.getExpirationPeriod())
171 << "</expirationPeriod>";
172 }
173 os << "</route>";
174 }
175 os << "</routes>";
176
177 os << "</ribEntry>";
178}
179
180void
181RibModule::formatStatusText(std::ostream& os) const
182{
183 os << "RIB:\n";
184 for (const RibEntry& item : m_status) {
185 this->formatItemText(os, item);
186 }
187}
188
189void
190RibModule::formatItemText(std::ostream& os, const RibEntry& item) const
191{
192 os << " " << item.getName() << " route={";
193
194 text::Separator sep(", ");
195 for (const Route& route : item.getRoutes()) {
196 os << sep
197 << "faceid=" << route.getFaceId()
198 << " (origin=" << route.getOrigin()
199 << " cost=" << route.getCost();
Davide Pesavento26cbdbd2017-02-19 21:37:43 -0500200 if (route.hasExpirationPeriod()) {
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000201 os << " expires=" << text::formatDuration(route.getExpirationPeriod());
202 }
203 if (route.isChildInherit()) {
204 os << " ChildInherit";
205 }
206 if (route.isRibCapture()) {
207 os << " RibCapture";
208 }
209 os << ")";
210 }
211
212 os << "}";
213 os << "\n";
214}
215
Junxiao Shi331ade72016-08-19 14:07:19 +0000216} // namespace nfdc
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000217} // namespace tools
218} // namespace nfd