blob: ebea105e325c12973c70003e6ad391af6a3536be [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
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070028#include "version.hpp"
Junxiao Shi09bf7c42014-01-31 11:10:25 -070029#include "core/logger.hpp"
Junxiao Shi98e29f42014-03-31 10:27:26 -070030#include "core/global-io.hpp"
Junxiao Shi09bf7c42014-01-31 11:10:25 -070031#include "fw/forwarder.hpp"
32#include "mgmt/internal-face.hpp"
Steve DiBenedetto214563c2014-02-03 19:20:36 -070033#include "mgmt/fib-manager.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070034#include "mgmt/face-manager.hpp"
Steve DiBenedetto5330e0d2014-03-05 21:52:51 -070035#include "mgmt/strategy-choice-manager.hpp"
Junxiao Shiea48d8b2014-03-16 13:53:47 -070036#include "mgmt/status-server.hpp"
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070037#include "core/config-file.hpp"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080038
Junxiao Shi09bf7c42014-01-31 11:10:25 -070039namespace nfd {
40
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -070041NFD_LOG_INIT("NFD");
Junxiao Shi09bf7c42014-01-31 11:10:25 -070042
43struct ProgramOptions
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080044{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070045 bool showUsage;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070046 bool showVersion;
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060047 bool showModules;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070048 std::string config;
Junxiao Shi09bf7c42014-01-31 11:10:25 -070049};
50
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070051class Nfd : noncopyable
Junxiao Shi09bf7c42014-01-31 11:10:25 -070052{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070053public:
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060054
55 void
56 initialize(const std::string& configFile)
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070057 {
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060058 initializeLogging(configFile);
59
60 m_forwarder = make_shared<Forwarder>();
61
62 initializeManagement(configFile);
63 }
64
65
66 void
67 initializeLogging(const std::string& configFile)
68 {
Steve DiBenedetto34c95f72014-04-17 20:56:00 -060069 ConfigFile config(&ConfigFile::ignoreUnknownSection);
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060070 LoggerFactory::getInstance().setConfigFile(config);
71
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060072 config.parse(configFile, true);
73 config.parse(configFile, false);
74 }
75
Steve DiBenedetto34c95f72014-04-17 20:56:00 -060076 class IgnoreRibAndLogSections
77 {
78 public:
79 void
80 operator()(const std::string& filename,
81 const std::string& sectionName,
82 const ConfigSection& section,
83 bool isDryRun)
84
85 {
86 // Ignore "log" and sections beginning with "rib_" (intended for rib manager),
87 // but raise an error if we're missing a handler for an NFD section.
88
Yingdi Yue5224e92014-04-29 18:04:02 -070089 if (sectionName.find("rib") == 0 || sectionName == "log")
Steve DiBenedetto34c95f72014-04-17 20:56:00 -060090 {
91 // do nothing
92 }
93 else
94 {
95 // missing NFD section
96 ConfigFile::throwErrorOnUnknownSection(filename, sectionName, section, isDryRun);
97 }
98 }
99 };
100
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600101 void
102 initializeManagement(const std::string& configFile)
103 {
104 m_internalFace = make_shared<InternalFace>();
105
106 m_fibManager = make_shared<FibManager>(boost::ref(m_forwarder->getFib()),
107 bind(&Forwarder::getFace, m_forwarder.get(), _1),
108 m_internalFace);
109
110 m_faceManager = make_shared<FaceManager>(boost::ref(m_forwarder->getFaceTable()),
111 m_internalFace);
112
113 m_strategyChoiceManager =
114 make_shared<StrategyChoiceManager>(boost::ref(m_forwarder->getStrategyChoice()),
115 m_internalFace);
116
117 m_statusServer = make_shared<StatusServer>(m_internalFace,
118 boost::ref(*m_forwarder));
119
Steve DiBenedetto34c95f72014-04-17 20:56:00 -0600120 ConfigFile config((IgnoreRibAndLogSections()));
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700121 m_internalFace->getValidator().setConfigFile(config);
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700122
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600123 m_forwarder->addFace(m_internalFace);
Junxiao Shic041ca32014-02-25 20:01:15 -0700124
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600125 m_faceManager->setConfigFile(config);
126
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700127 // parse config file
128 config.parse(configFile, true);
129 config.parse(configFile, false);
130
131 // add FIB entry for NFD Management Protocol
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600132 shared_ptr<fib::Entry> entry = m_forwarder->getFib().insert("/localhost/nfd").first;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700133 entry->addNextHop(m_internalFace, 0);
134 }
135
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700136 static void
137 printUsage(std::ostream& os, const std::string& programName)
138 {
139 os << "Usage: \n"
140 << " " << programName << " [options]\n"
141 << "\n"
142 << "Run NFD forwarding daemon\n"
143 << "\n"
144 << "Options:\n"
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700145 << " [--help] - print this help message\n"
146 << " [--version] - print version and exit\n"
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600147 << " [--modules] - list available logging modules\n"
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700148 << " [--config /path/to/nfd.conf] - path to configuration file "
149 << "(default: " << DEFAULT_CONFIG_FILE << ")\n"
150 ;
151 }
152
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600153 static void
154 printModules(std::ostream& os)
155 {
156 using namespace std;
157
158 os << "Available logging modules: \n";
159
160 list<string> modules(LoggerFactory::getInstance().getModules());
161 for (list<string>::const_iterator i = modules.begin(); i != modules.end(); ++i)
162 {
163 os << *i << "\n";
164 }
165 }
166
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700167 static bool
168 parseCommandLine(int argc, char** argv, ProgramOptions& options)
169 {
170 options.showUsage = false;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700171 options.showVersion = false;
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600172 options.showModules = false;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700173 options.config = DEFAULT_CONFIG_FILE;
174
175 while (true) {
176 int optionIndex = 0;
177 static ::option longOptions[] = {
178 { "help" , no_argument , 0, 0 },
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600179 { "modules", no_argument , 0, 0 },
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700180 { "config" , required_argument, 0, 0 },
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700181 { "version", no_argument , 0, 0 },
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700182 { 0 , 0 , 0, 0 }
183 };
184 int c = getopt_long_only(argc, argv, "", longOptions, &optionIndex);
185 if (c == -1)
186 break;
187
188 switch (c) {
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700189 case 0:
190 switch (optionIndex) {
191 case 0: // help
192 options.showUsage = true;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700193 break;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700194 case 1: // modules
195 options.showModules = true;
196 break;
197 case 2: // config
198 options.config = ::optarg;
199 break;
200 case 3: // version
201 options.showVersion = true;
202 break;
203 default:
204 return false;
205 }
206 break;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700207 }
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700208 }
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700209 return true;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700210 }
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700211
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700212 void
213 terminate(const boost::system::error_code& error,
214 int signalNo,
215 boost::asio::signal_set& signalSet)
216 {
217 if (error)
218 return;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700219
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700220 if (signalNo == SIGINT ||
221 signalNo == SIGTERM)
222 {
223 getGlobalIoService().stop();
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700224 NFD_LOG_INFO("Caught signal '" << strsignal(signalNo) << "', exiting...");
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700225 }
226 else
227 {
228 /// \todo May be try to reload config file (at least security section)
229 signalSet.async_wait(bind(&Nfd::terminate, this, _1, _2,
230 boost::ref(signalSet)));
231 }
Junxiao Shiea48d8b2014-03-16 13:53:47 -0700232 }
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600233
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700234private:
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600235 shared_ptr<Forwarder> m_forwarder;
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600236
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600237 shared_ptr<InternalFace> m_internalFace;
238 shared_ptr<FibManager> m_fibManager;
239 shared_ptr<FaceManager> m_faceManager;
240 shared_ptr<StrategyChoiceManager> m_strategyChoiceManager;
241 shared_ptr<StatusServer> m_statusServer;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700242};
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700243
244} // namespace nfd
245
246int
247main(int argc, char** argv)
248{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700249 using namespace nfd;
Junxiao Shiea48d8b2014-03-16 13:53:47 -0700250
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700251 ProgramOptions options;
252 bool isCommandLineValid = Nfd::parseCommandLine(argc, argv, options);
253 if (!isCommandLineValid) {
254 Nfd::printUsage(std::cerr, argv[0]);
255 return 1;
256 }
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700257
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700258 if (options.showUsage) {
259 Nfd::printUsage(std::cout, argv[0]);
260 return 0;
261 }
262
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700263 if (options.showVersion) {
264 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
265 return 0;
266 }
267
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600268 if (options.showModules) {
269 Nfd::printModules(std::cout);
270 return 0;
271 }
272
273 Nfd nfdInstance;
274
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700275 try {
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600276 nfdInstance.initialize(options.config);
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700277 }
278 catch (boost::filesystem::filesystem_error& e) {
279 if (e.code() == boost::system::errc::permission_denied) {
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600280 NFD_LOG_FATAL("Permissions denied for " << e.path1() << ". " <<
281 argv[0] << " should be run as superuser");
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700282 }
283 else {
284 NFD_LOG_FATAL(e.what());
285 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600286 return 1;
287 }
288 catch (const std::exception& e) {
289 NFD_LOG_FATAL(e.what());
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700290 return 2;
291 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600292
293 boost::asio::signal_set signalSet(getGlobalIoService());
294 signalSet.add(SIGINT);
295 signalSet.add(SIGTERM);
296 signalSet.add(SIGHUP);
297 signalSet.add(SIGUSR1);
298 signalSet.add(SIGUSR2);
299 signalSet.async_wait(bind(&Nfd::terminate, &nfdInstance, _1, _2,
300 boost::ref(signalSet)));
301
302 try {
303 getGlobalIoService().run();
304 }
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700305 catch (std::exception& e) {
306 NFD_LOG_FATAL(e.what());
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600307 return 3;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700308 }
309
310 return 0;
311}