blob: a13dfe1cd2cdd6c350d229aac155d600537b8a03 [file] [log] [blame]
Alexander Afanasyev2aa39622014-01-22 11:51:11 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -07003 * Copyright (c) 2014 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 *
10 * This file is part of NFD (Named Data Networking Forwarding Daemon).
11 * See AUTHORS.md for complete list of NFD authors and contributors.
12 *
13 * NFD is free software: you can redistribute it and/or modify it under the terms
14 * of the GNU General Public License as published by the Free Software Foundation,
15 * either version 3 of the License, or (at your option) any later version.
16 *
17 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
19 * PURPOSE. See the GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along with
22 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
23 **/
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080024
Junxiao Shi09bf7c42014-01-31 11:10:25 -070025#include <getopt.h>
Junxiao Shi98e29f42014-03-31 10:27:26 -070026#include <boost/filesystem.hpp>
27
Junxiao Shi09bf7c42014-01-31 11:10:25 -070028#include "core/logger.hpp"
Junxiao Shi98e29f42014-03-31 10:27:26 -070029#include "core/global-io.hpp"
Junxiao Shi09bf7c42014-01-31 11:10:25 -070030#include "fw/forwarder.hpp"
31#include "mgmt/internal-face.hpp"
Steve DiBenedetto214563c2014-02-03 19:20:36 -070032#include "mgmt/fib-manager.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070033#include "mgmt/face-manager.hpp"
Steve DiBenedetto5330e0d2014-03-05 21:52:51 -070034#include "mgmt/strategy-choice-manager.hpp"
Junxiao Shiea48d8b2014-03-16 13:53:47 -070035#include "mgmt/status-server.hpp"
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070036#include "core/config-file.hpp"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080037
Junxiao Shi09bf7c42014-01-31 11:10:25 -070038namespace nfd {
39
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -070040NFD_LOG_INIT("NFD");
Junxiao Shi09bf7c42014-01-31 11:10:25 -070041
42struct ProgramOptions
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080043{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070044 bool showUsage;
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060045 bool showModules;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070046 std::string config;
Junxiao Shi09bf7c42014-01-31 11:10:25 -070047};
48
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070049class Nfd : noncopyable
Junxiao Shi09bf7c42014-01-31 11:10:25 -070050{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070051public:
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060052
53 void
54 initialize(const std::string& configFile)
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070055 {
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060056 initializeLogging(configFile);
57
58 m_forwarder = make_shared<Forwarder>();
59
60 initializeManagement(configFile);
61 }
62
63
64 void
65 initializeLogging(const std::string& configFile)
66 {
Steve DiBenedetto34c95f72014-04-17 20:56:00 -060067 ConfigFile config(&ConfigFile::ignoreUnknownSection);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060068 LoggerFactory::getInstance().setConfigFile(config);
69
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060070 config.parse(configFile, true);
71 config.parse(configFile, false);
72 }
73
Steve DiBenedetto34c95f72014-04-17 20:56:00 -060074 class IgnoreRibAndLogSections
75 {
76 public:
77 void
78 operator()(const std::string& filename,
79 const std::string& sectionName,
80 const ConfigSection& section,
81 bool isDryRun)
82
83 {
84 // Ignore "log" and sections beginning with "rib_" (intended for rib manager),
85 // but raise an error if we're missing a handler for an NFD section.
86
87 if (sectionName.find("rib_") == 0 || sectionName == "log")
88 {
89 // do nothing
90 }
91 else
92 {
93 // missing NFD section
94 ConfigFile::throwErrorOnUnknownSection(filename, sectionName, section, isDryRun);
95 }
96 }
97 };
98
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060099 void
100 initializeManagement(const std::string& configFile)
101 {
102 m_internalFace = make_shared<InternalFace>();
103
104 m_fibManager = make_shared<FibManager>(boost::ref(m_forwarder->getFib()),
105 bind(&Forwarder::getFace, m_forwarder.get(), _1),
106 m_internalFace);
107
108 m_faceManager = make_shared<FaceManager>(boost::ref(m_forwarder->getFaceTable()),
109 m_internalFace);
110
111 m_strategyChoiceManager =
112 make_shared<StrategyChoiceManager>(boost::ref(m_forwarder->getStrategyChoice()),
113 m_internalFace);
114
115 m_statusServer = make_shared<StatusServer>(m_internalFace,
116 boost::ref(*m_forwarder));
117
Steve DiBenedetto34c95f72014-04-17 20:56:00 -0600118 ConfigFile config((IgnoreRibAndLogSections()));
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700119 m_internalFace->getValidator().setConfigFile(config);
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700120
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600121 m_forwarder->addFace(m_internalFace);
Junxiao Shic041ca32014-02-25 20:01:15 -0700122
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600123 m_faceManager->setConfigFile(config);
124
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700125 // parse config file
126 config.parse(configFile, true);
127 config.parse(configFile, false);
128
129 // add FIB entry for NFD Management Protocol
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600130 shared_ptr<fib::Entry> entry = m_forwarder->getFib().insert("/localhost/nfd").first;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700131 entry->addNextHop(m_internalFace, 0);
132 }
133
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700134 static void
135 printUsage(std::ostream& os, const std::string& programName)
136 {
137 os << "Usage: \n"
138 << " " << programName << " [options]\n"
139 << "\n"
140 << "Run NFD forwarding daemon\n"
141 << "\n"
142 << "Options:\n"
143 << " [--help] - print this help message\n"
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600144 << " [--modules] - list available logging modules\n"
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700145 << " [--config /path/to/nfd.conf] - path to configuration file "
146 << "(default: " << DEFAULT_CONFIG_FILE << ")\n"
147 ;
148 }
149
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600150 static void
151 printModules(std::ostream& os)
152 {
153 using namespace std;
154
155 os << "Available logging modules: \n";
156
157 list<string> modules(LoggerFactory::getInstance().getModules());
158 for (list<string>::const_iterator i = modules.begin(); i != modules.end(); ++i)
159 {
160 os << *i << "\n";
161 }
162 }
163
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700164 static bool
165 parseCommandLine(int argc, char** argv, ProgramOptions& options)
166 {
167 options.showUsage = false;
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600168 options.showModules = false;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700169 options.config = DEFAULT_CONFIG_FILE;
170
171 while (true) {
172 int optionIndex = 0;
173 static ::option longOptions[] = {
174 { "help" , no_argument , 0, 0 },
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600175 { "modules", no_argument , 0, 0 },
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700176 { "config" , required_argument, 0, 0 },
177 { 0 , 0 , 0, 0 }
178 };
179 int c = getopt_long_only(argc, argv, "", longOptions, &optionIndex);
180 if (c == -1)
181 break;
182
183 switch (c) {
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600184 case 0:
185 switch (optionIndex) {
186 case 0: // help
187 options.showUsage = true;
188 break;
189 case 1: // modules
190 options.showModules = true;
191 break;
192 case 2: // config
193 options.config = ::optarg;
194 break;
195 default:
196 return false;
197 }
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700198 break;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700199 }
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700200 }
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700201 return true;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700202 }
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700203
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700204 void
205 terminate(const boost::system::error_code& error,
206 int signalNo,
207 boost::asio::signal_set& signalSet)
208 {
209 if (error)
210 return;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700211
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700212 if (signalNo == SIGINT ||
213 signalNo == SIGTERM)
214 {
215 getGlobalIoService().stop();
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700216 NFD_LOG_INFO("Caught signal '" << strsignal(signalNo) << "', exiting...");
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700217 }
218 else
219 {
220 /// \todo May be try to reload config file (at least security section)
221 signalSet.async_wait(bind(&Nfd::terminate, this, _1, _2,
222 boost::ref(signalSet)));
223 }
Junxiao Shiea48d8b2014-03-16 13:53:47 -0700224 }
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600225
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700226private:
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600227 shared_ptr<Forwarder> m_forwarder;
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600228
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600229 shared_ptr<InternalFace> m_internalFace;
230 shared_ptr<FibManager> m_fibManager;
231 shared_ptr<FaceManager> m_faceManager;
232 shared_ptr<StrategyChoiceManager> m_strategyChoiceManager;
233 shared_ptr<StatusServer> m_statusServer;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700234};
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700235
236} // namespace nfd
237
238int
239main(int argc, char** argv)
240{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700241 using namespace nfd;
Junxiao Shiea48d8b2014-03-16 13:53:47 -0700242
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700243 ProgramOptions options;
244 bool isCommandLineValid = Nfd::parseCommandLine(argc, argv, options);
245 if (!isCommandLineValid) {
246 Nfd::printUsage(std::cerr, argv[0]);
247 return 1;
248 }
249 if (options.showUsage) {
250 Nfd::printUsage(std::cout, argv[0]);
251 return 0;
252 }
253
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600254 if (options.showModules) {
255 Nfd::printModules(std::cout);
256 return 0;
257 }
258
259 Nfd nfdInstance;
260
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700261 try {
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600262 nfdInstance.initialize(options.config);
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700263 }
264 catch (boost::filesystem::filesystem_error& e) {
265 if (e.code() == boost::system::errc::permission_denied) {
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600266 NFD_LOG_FATAL("Permissions denied for " << e.path1() << ". " <<
267 argv[0] << " should be run as superuser");
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700268 }
269 else {
270 NFD_LOG_FATAL(e.what());
271 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600272 return 1;
273 }
274 catch (const std::exception& e) {
275 NFD_LOG_FATAL(e.what());
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700276 return 2;
277 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600278
279 boost::asio::signal_set signalSet(getGlobalIoService());
280 signalSet.add(SIGINT);
281 signalSet.add(SIGTERM);
282 signalSet.add(SIGHUP);
283 signalSet.add(SIGUSR1);
284 signalSet.add(SIGUSR2);
285 signalSet.async_wait(bind(&Nfd::terminate, &nfdInstance, _1, _2,
286 boost::ref(signalSet)));
287
288 try {
289 getGlobalIoService().run();
290 }
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700291 catch (std::exception& e) {
292 NFD_LOG_FATAL(e.what());
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600293 return 3;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700294 }
295
296 return 0;
297}