mgmt: add UDP IPv4 and ethernet multicast face creation to face manager
refs: #1195
Change-Id: I693772d6a5c79873c5715718a6cacd80dc8c74e1
diff --git a/daemon/main.cpp b/daemon/main.cpp
index e4ead64..9f7bb75 100644
--- a/daemon/main.cpp
+++ b/daemon/main.cpp
@@ -229,6 +229,7 @@
g_internalFace);
g_faceManager = new FaceManager(g_forwarder->getFaceTable(), g_internalFace);
+ g_faceManager->setConfigFile(config);
g_localControlHeaderManager =
new LocalControlHeaderManager(bind(&Forwarder::getFace, g_forwarder, _1),
@@ -237,8 +238,6 @@
g_strategyChoiceManager = new StrategyChoiceManager(g_forwarder->getStrategyChoice(),
g_internalFace);
- /// \todo add face manager section handler
-
/// \todo add parsing back when there is an official default config file
// config.parse(g_options.m_config);
diff --git a/daemon/mgmt/face-manager.cpp b/daemon/mgmt/face-manager.cpp
index 9874176..701bddd 100644
--- a/daemon/mgmt/face-manager.cpp
+++ b/daemon/mgmt/face-manager.cpp
@@ -7,19 +7,19 @@
#include "face-manager.hpp"
#include "core/face-uri.hpp"
+#include "core/network-interface.hpp"
#include "fw/face-table.hpp"
#include "face/tcp-factory.hpp"
#include "face/udp-factory.hpp"
+
+#ifdef HAVE_UNIX_SOCKETS
#include "face/unix-stream-factory.hpp"
+#endif // HAVE_UNIX_SOCKETS
+
+#ifdef HAVE_PCAP
#include "face/ethernet-factory.hpp"
-
-#ifdef __linux__
-#include <netinet/ether.h>
-#else
-#include <net/ethernet.h>
-#endif
-
+#endif // HAVE_PCAP
namespace nfd {
@@ -63,6 +63,11 @@
bind(&FaceManager::onFaceRequest, this, _2));
}
+FaceManager::~FaceManager()
+{
+
+}
+
void
FaceManager::setConfigFile(ConfigFile& configFile)
{
@@ -79,6 +84,8 @@
bool hasSeenUdp = false;
bool hasSeenEther = false;
+ const std::list<shared_ptr<NetworkInterfaceInfo> > nicList(listNetworkInterfaces());
+
for (ConfigSection::const_iterator item = configSection.begin();
item != configSection.end();
++item)
@@ -105,7 +112,7 @@
throw Error("Duplicate \"udp\" section");
hasSeenUdp = true;
- processSectionUdp(item->second, isDryRun);
+ processSectionUdp(item->second, isDryRun, nicList);
}
else if (item->first == "ether")
{
@@ -113,7 +120,7 @@
throw Error("Duplicate \"ether\" section");
hasSeenEther = true;
- processSectionEther(item->second, isDryRun);
+ processSectionEther(item->second, isDryRun, nicList);
}
else
{
@@ -132,6 +139,8 @@
// path /var/run/nfd.sock ; UNIX stream listener path
// }
+#if defined(HAVE_UNIX_SOCKETS)
+
bool needToListen = true;
std::string path = "/var/run/nfd.sock";
@@ -167,6 +176,10 @@
m_factories.insert(std::make_pair("unix", factory));
}
+#else
+ throw ConfigFile::Error("NFD was compiled without UNIX sockets support, cannot process \"unix\" section");
+#endif // HAVE_UNIX_SOCKETS
+
}
void
@@ -226,7 +239,9 @@
}
void
-FaceManager::processSectionUdp(const ConfigSection& configSection, bool isDryRun)
+FaceManager::processSectionUdp(const ConfigSection& configSection,
+ bool isDryRun,
+ const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
{
// ; the udp section contains settings of UDP faces and channels
// udp
@@ -245,8 +260,9 @@
size_t timeout = 30;
size_t keepAliveInterval = 25;
bool useMcast = true;
+ std::string mcastGroup = "224.0.23.170";
std::string mcastPort = "56363";
- std::string mcastGroup;
+
for (ConfigSection::const_iterator i = configSection.begin();
i != configSection.end();
@@ -319,10 +335,7 @@
{
shared_ptr<UdpFactory> factory = make_shared<UdpFactory>(boost::cref(port));
- shared_ptr<UdpChannel> ipv4Channel =
- factory->createChannel("0.0.0.0", port, time::seconds(timeout));
- shared_ptr<UdpChannel> ipv6Channel =
- factory->createChannel("::", port, time::seconds(timeout));
+ factory->createChannel("::", port, time::seconds(timeout));
m_factories.insert(std::make_pair("udp", factory));
m_factories.insert(std::make_pair("udp4", factory));
@@ -330,14 +343,67 @@
if (useMcast)
{
- /// \todo create one multicast face per NIC
- NFD_LOG_WARN("multicast faces are not implemented");
+ bool useEndpoint = false;
+ udp::Endpoint localEndpoint;
+
+ try
+ {
+ localEndpoint.port(boost::lexical_cast<uint16_t>(port));
+ useEndpoint = true;
+ }
+ catch (const boost::bad_lexical_cast& error)
+ {
+ NFD_LOG_DEBUG("Treating UDP port \"" << port << "\" as a service name");
+ }
+
+ for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
+ i != nicList.end();
+ ++i)
+ {
+ const shared_ptr<NetworkInterfaceInfo>& nic = *i;
+ if (nic->isUp() && nic->isMulticastCapable() && !nic->ipv4Addresses.empty())
+ {
+ shared_ptr<MulticastUdpFace> newFace =
+ factory->createMulticastFace(nic->ipv4Addresses[0].to_string(),
+ mcastGroup, mcastPort);
+
+ NFD_LOG_INFO("Created multicast Face ID " << newFace->getId());
+
+ if (useEndpoint)
+ {
+ for (std::vector<boost::asio::ip::address_v4>::const_iterator j =
+ nic->ipv4Addresses.begin();
+ j != nic->ipv4Addresses.end();
+ ++j)
+ {
+ localEndpoint.address(*j);
+ factory->createChannel(localEndpoint, time::seconds(timeout));
+ }
+ }
+ else
+ {
+ for (std::vector<boost::asio::ip::address_v4>::const_iterator j =
+ nic->ipv4Addresses.begin();
+ j != nic->ipv4Addresses.end();
+ ++j)
+ {
+ factory->createChannel(j->to_string(), port, time::seconds(timeout));
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ factory->createChannel("0.0.0.0", port, time::seconds(timeout));
}
}
}
void
-FaceManager::processSectionEther(const ConfigSection& configSection, bool isDryRun)
+FaceManager::processSectionEther(const ConfigSection& configSection,
+ bool isDryRun,
+ const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
{
// ; the ether section contains settings of Ethernet faces and channels
// ether
@@ -347,8 +413,12 @@
// mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
// }
+#if defined(HAVE_PCAP)
+
+ using ethernet::Address;
+
bool useMcast = true;
- std::string mcastGroup;
+ Address mcastGroup(ethernet::getDefaultMulticastAddress());
for (ConfigSection::const_iterator i = configSection.begin();
i != configSection.end();
@@ -361,9 +431,8 @@
else if (i->first == "mcast_group")
{
- const std::string mcastGroup = i->second.get_value<std::string>();
- /// \todo change to use ethernet::Address::fromString
- if (!ether_aton(mcastGroup.c_str()))
+ mcastGroup = Address::fromString(i->second.get_value<std::string>());
+ if (mcastGroup.isNull())
{
throw ConfigFile::Error("Invalid value for option \"" +
i->first + "\" in \"ether\" section");
@@ -382,10 +451,34 @@
if (useMcast)
{
- /// \todo create one multicast face per NIC
- NFD_LOG_WARN("multicast faces are not implemented");
+ for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
+ i != nicList.end();
+ ++i)
+ {
+ const shared_ptr<NetworkInterfaceInfo>& nic = *i;
+ if (nic->isUp() && nic->isMulticastCapable())
+ {
+ try
+ {
+ shared_ptr<EthernetFace> newFace =
+ factory->createMulticastFace(nic->name, mcastGroup);
+ NFD_LOG_INFO("Created multicast Face ID " << newFace->getId());
+ }
+ catch (const EthernetFactory::Error& factoryError)
+ {
+ NFD_LOG_ERROR(factoryError.what() << ", continuing");
+ }
+ catch (const EthernetFace::Error& faceError)
+ {
+ NFD_LOG_ERROR(faceError.what() << ", continuing");
+ }
+ }
+ }
}
}
+#else
+ throw ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section");
+#endif // HAVE_PCAP
}
@@ -524,9 +617,6 @@
sendResponse(requestName, 200, "Success");
}
-FaceManager::~FaceManager()
-{
-}
} // namespace nfd
diff --git a/daemon/mgmt/face-manager.hpp b/daemon/mgmt/face-manager.hpp
index 316af2a..55e4df4 100644
--- a/daemon/mgmt/face-manager.hpp
+++ b/daemon/mgmt/face-manager.hpp
@@ -21,6 +21,7 @@
const std::string FACE_MANAGER_PRIVILEGE = "faces";
class FaceTable;
class ProtocolFactory;
+class NetworkInterfaceInfo;
class FaceManager : public ManagerBase
{
@@ -37,6 +38,9 @@
FaceManager(FaceTable& faceTable,
shared_ptr<InternalFace> face);
+ virtual
+ ~FaceManager();
+
/** \brief Subscribe to a face management section(s) for the config file
*/
void
@@ -45,9 +49,6 @@
void
onFaceRequest(const Interest& request);
- VIRTUAL_WITH_TESTS
- ~FaceManager();
-
PROTECTED_WITH_TESTS_ELSE_PRIVATE:
void
@@ -84,10 +85,14 @@
processSectionTcp(const ConfigSection& configSection, bool isDryRun);
void
- processSectionUdp(const ConfigSection& configSection, bool isDryRun);
+ processSectionUdp(const ConfigSection& configSection,
+ bool isDryRun,
+ const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList);
void
- processSectionEther(const ConfigSection& configSection, bool isDryRun);
+ processSectionEther(const ConfigSection& configSection,
+ bool isDryRun,
+ const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList);
/** \brief parse a config option that can be either "yes" or "no"
* \throw ConfigFile::Error value is neither "yes" nor "no"
@@ -102,7 +107,6 @@
typedef std::map< std::string/*protocol*/, shared_ptr<ProtocolFactory> > FactoryMap;
FactoryMap m_factories;
FaceTable& m_faceTable;
- //
typedef function<void(FaceManager*,
const Name&,
diff --git a/tests/mgmt/face-manager.cpp b/tests/mgmt/face-manager.cpp
index 9937632..e4e7954 100644
--- a/tests/mgmt/face-manager.cpp
+++ b/tests/mgmt/face-manager.cpp
@@ -323,6 +323,8 @@
return error.what() == expectedMessage;
}
+#ifdef HAVE_UNIX_SOCKETS
+
BOOST_AUTO_TEST_CASE(TestProcessSectionUnix)
{
const std::string CONFIG =
@@ -383,6 +385,7 @@
"Unrecognized option \"hello\" in \"unix\" section"));
}
+#endif // HAVE_UNIX_SOCKETS
BOOST_AUTO_TEST_CASE(TestProcessSectionTcp)
@@ -573,8 +576,11 @@
"Unrecognized option \"hello\" in \"udp\" section"));
}
+#ifdef HAVE_PCAP
+
BOOST_AUTO_TEST_CASE(TestProcessSectionEther)
{
+
const std::string CONFIG =
"face_system\n"
"{\n"
@@ -651,6 +657,8 @@
"Unrecognized option \"hello\" in \"ether\" section"));
}
+#endif
+
BOOST_AUTO_TEST_CASE(TestFireInterestFilter)
{
shared_ptr<Interest> command(make_shared<Interest>("/localhost/nfd/faces"));
@@ -738,23 +746,6 @@
}
};
-// template <> class AuthorizedCommandFixture<FaceManagerFixture> :
-// public CommandFixture<FaceManagerFixture>
-// {
-// public:
-// AuthorizedCommandFixture()
-// {
-// const std::string regex = "^<localhost><nfd><faces>";
-// FaceManagerFixture::ManagerBase::addInterestRule(regex, *CommandFixture<FaceManagerFixture>::m_certificate);
-// }
-
-// virtual
-// ~AuthorizedCommandFixture()
-// {
-
-// }
-// };
-
BOOST_FIXTURE_TEST_CASE(UnsupportedCommand, AuthorizedCommandFixture<FaceManagerFixture>)
{
ndn::nfd::FaceManagementOptions options;