30 #include <boost/range/adaptors.hpp>
31 #include <boost/range/algorithm/copy.hpp>
41 static std::string id(
"ether");
48 m_netifAddConn =
netmon->onInterfaceAdded.connect([
this] (
const auto& netif) {
49 applyUnicastConfigToNetif(netif);
50 applyMcastConfigToNetif(*netif);
74 UnicastConfig unicastConfig;
75 MulticastConfig mcastConfig;
79 unicastConfig.isEnabled = unicastConfig.wantListen = mcastConfig.isEnabled =
true;
81 for (
const auto& pair : *configSection) {
82 const std::string& key = pair.first;
85 if (key ==
"listen") {
88 else if (key ==
"idle_timeout") {
89 unicastConfig.idleTimeout = time::seconds(ConfigFile::parseNumber<uint32_t>(pair,
"face_system.ether"));
91 else if (key ==
"mcast") {
94 else if (key ==
"mcast_group") {
95 const std::string& valueStr = value.get_value<std::string>();
96 mcastConfig.group = ethernet::Address::fromString(valueStr);
97 if (mcastConfig.group.isNull()) {
98 NDN_THROW(ConfigFile::Error(
"face_system.ether.mcast_group: '" +
99 valueStr +
"' cannot be parsed as an Ethernet address"));
101 else if (!mcastConfig.group.isMulticast()) {
102 NDN_THROW(ConfigFile::Error(
"face_system.ether.mcast_group: '" +
103 valueStr +
"' is not a multicast address"));
106 else if (key ==
"mcast_ad_hoc") {
108 mcastConfig.linkType = wantAdHoc ? ndn::nfd::LINK_TYPE_AD_HOC : ndn::nfd::LINK_TYPE_MULTI_ACCESS;
110 else if (key ==
"whitelist") {
111 mcastConfig.netifPredicate.parseWhitelist(value);
113 else if (key ==
"blacklist") {
114 mcastConfig.netifPredicate.parseBlacklist(value);
117 NDN_THROW(ConfigFile::Error(
"Unrecognized option face_system.ether." + key));
126 if (unicastConfig.isEnabled) {
127 if (m_unicastConfig.wantListen && !unicastConfig.wantListen && !m_channels.empty()) {
128 NFD_LOG_WARN(
"Cannot stop listening on Ethernet channels");
130 if (m_unicastConfig.idleTimeout != unicastConfig.idleTimeout && !m_channels.empty()) {
131 NFD_LOG_WARN(
"Idle timeout setting applies to new Ethernet channels only");
134 else if (m_unicastConfig.isEnabled && !m_channels.empty()) {
135 NFD_LOG_WARN(
"Cannot disable Ethernet channels after initialization");
138 if (m_mcastConfig.isEnabled != mcastConfig.isEnabled) {
139 if (mcastConfig.isEnabled) {
140 NFD_LOG_INFO(
"enabling multicast on " << mcastConfig.group);
146 else if (mcastConfig.isEnabled) {
147 if (m_mcastConfig.linkType != mcastConfig.linkType && !m_mcastFaces.empty()) {
148 NFD_LOG_WARN(
"Cannot change ad hoc setting on existing faces");
150 if (m_mcastConfig.group != mcastConfig.group) {
151 NFD_LOG_INFO(
"changing multicast group from " << m_mcastConfig.group <<
152 " to " << mcastConfig.group);
154 if (m_mcastConfig.netifPredicate != mcastConfig.netifPredicate) {
161 m_unicastConfig = std::move(unicastConfig);
162 m_mcastConfig = std::move(mcastConfig);
163 applyConfig(context);
167 EthernetFactory::doCreateFace(
const CreateFaceRequest& req,
171 if (!req.localUri || req.localUri->getScheme() !=
"dev") {
173 onFailure(406,
"Creation of unicast Ethernet faces requires a LocalUri with dev:// scheme");
177 if (req.params.persistency == ndn::nfd::FACE_PERSISTENCY_ON_DEMAND) {
179 onFailure(406,
"Outgoing Ethernet faces do not support on-demand persistency");
183 ethernet::Address remoteEndpoint(ethernet::Address::fromString(req.remoteUri.getHost()));
184 std::string localEndpoint(req.localUri->getHost());
186 if (remoteEndpoint.isMulticast()) {
188 onFailure(406,
"Cannot create multicast Ethernet faces");
192 if (req.params.wantLocalFields) {
194 NFD_LOG_TRACE(
"createFace: cannot create non-local face with local fields enabled");
195 onFailure(406,
"Local fields can only be enabled on faces with local scope");
199 if (req.params.mtu && *req.params.mtu <
MIN_MTU) {
202 onFailure(406,
"Override MTU cannot be less than " + std::to_string(
MIN_MTU));
206 for (
const auto& i : m_channels) {
207 if (i.first == localEndpoint) {
208 i.second->connect(remoteEndpoint, req.params, onCreated, onFailure);
213 NFD_LOG_TRACE(
"No channels available to connect to " << remoteEndpoint);
214 onFailure(504,
"No channels available to connect");
217 shared_ptr<EthernetChannel>
219 time::nanoseconds idleTimeout)
221 auto it = m_channels.find(localEndpoint->getName());
222 if (it != m_channels.end())
225 auto channel = std::make_shared<EthernetChannel>(localEndpoint, idleTimeout);
226 m_channels[localEndpoint->getName()] = channel;
230 std::vector<shared_ptr<const Channel>>
231 EthernetFactory::doGetChannels()
const
238 const ethernet::Address& address)
240 BOOST_ASSERT(address.isMulticast());
242 std::pair key(netif.getName(), address);
243 auto found = m_mcastFaces.find(key);
244 if (found != m_mcastFaces.end()) {
245 return found->second;
252 auto linkService = make_unique<GenericLinkService>(opts);
253 auto transport = make_unique<MulticastEthernetTransport>(netif, address, m_mcastConfig.linkType);
254 auto face = make_shared<Face>(std::move(linkService), std::move(transport));
256 m_mcastFaces[key] = face;
259 auto channelIt = m_channels.find(netif.getName());
260 if (channelIt != m_channels.end()) {
261 face->setChannel(channelIt->second);
267 shared_ptr<EthernetChannel>
268 EthernetFactory::applyUnicastConfigToNetif(
const shared_ptr<const ndn::net::NetworkInterface>& netif)
270 if (!m_unicastConfig.isEnabled) {
274 if (!netif->isUp()) {
275 NFD_LOG_DEBUG(
"Not creating channel on " << netif->getName() <<
": netif is down");
279 if (netif->getType() != ndn::net::InterfaceType::ETHERNET) {
280 NFD_LOG_DEBUG(
"Not creating channel on " << netif->getName() <<
": incompatible netif type");
284 if (netif->getEthernetAddress().isNull()) {
285 NFD_LOG_DEBUG(
"Not creating channel on " << netif->getName() <<
": invalid Ethernet address");
289 auto channel = this->
createChannel(netif, m_unicastConfig.idleTimeout);
290 if (m_unicastConfig.wantListen && !channel->isListening()) {
292 channel->listen(this->
addFace,
nullptr);
294 catch (
const EthernetChannel::Error& e) {
295 NFD_LOG_WARN(
"Cannot listen on " << netif->getName() <<
": " << e.what());
302 EthernetFactory::applyMcastConfigToNetif(
const ndn::net::NetworkInterface& netif)
304 if (!m_mcastConfig.isEnabled) {
309 NFD_LOG_DEBUG(
"Not creating multicast face on " << netif.getName() <<
": netif is down");
313 if (netif.getType() != ndn::net::InterfaceType::ETHERNET) {
314 NFD_LOG_DEBUG(
"Not creating multicast face on " << netif.getName() <<
": incompatible netif type");
318 if (netif.getEthernetAddress().isNull()) {
319 NFD_LOG_DEBUG(
"Not creating multicast face on " << netif.getName() <<
": invalid Ethernet address");
323 if (!netif.canMulticast()) {
324 NFD_LOG_DEBUG(
"Not creating multicast face on " << netif.getName() <<
": netif cannot multicast");
328 if (!m_mcastConfig.netifPredicate(netif)) {
329 NFD_LOG_DEBUG(
"Not creating multicast face on " << netif.getName() <<
": rejected by whitelist/blacklist");
333 NFD_LOG_DEBUG(
"Creating multicast face on " << netif.getName());
334 shared_ptr<Face> face;
338 catch (
const std::runtime_error& e) {
339 NFD_LOG_WARN(
"Cannot create multicast face on " << netif.getName() <<
": " << e.what());
352 EthernetFactory::applyConfig(
const FaceSystem::ConfigContext&)
354 if (m_unicastConfig.isEnabled) {
362 std::set<shared_ptr<Face>> oldFaces;
363 boost::copy(m_mcastFaces | boost::adaptors::map_values, std::inserter(oldFaces, oldFaces.end()));
366 for (
const auto& netif :
netmon->listNetworkInterfaces()) {
367 applyUnicastConfigToNetif(netif);
369 auto face = applyMcastConfigToNetif(*netif);
370 if (face !=
nullptr) {
372 oldFaces.erase(face);
377 for (
const auto& face : oldFaces) {
static bool parseYesNo(const ConfigSection &node, const std::string &key, const std::string §ionName)
Parse a config option that can be either "yes" or "no".
Protocol factory for Ethernet.
EthernetFactory(const CtorParams ¶ms)
static const std::string & getId() noexcept
shared_ptr< Face > createMulticastFace(const ndn::net::NetworkInterface &localEndpoint, const ethernet::Address &group)
Create a face to communicate on the given Ethernet multicast group.
shared_ptr< EthernetChannel > createChannel(const shared_ptr< const ndn::net::NetworkInterface > &localEndpoint, time::nanoseconds idleTimeout)
Create Ethernet-based channel on the specified network interface.
Context for processing a config section in ProtocolFactory.
Provides support for an underlying protocol.
static std::vector< shared_ptr< const Channel > > getChannelsFromMap(const ChannelMap &channelMap)
std::set< std::string > providedSchemes
FaceUri schemes provided by this protocol factory.
FaceCreatedCallback addFace
callback when a new face is created
shared_ptr< ndn::net::NetworkMonitor > netmon
NetworkMonitor for listing available network interfaces and monitoring their changes.
#define NFD_LOG_INIT(name)
std::function< void(uint32_t status, const std::string &reason)> FaceCreationFailedCallback
Prototype for the callback that is invoked when a face fails to be created.
constexpr FaceId INVALID_FACEID
Indicates an invalid FaceId.
constexpr ssize_t MIN_MTU
Minimum MTU that may be set.
std::function< void(const shared_ptr< Face > &)> FaceCreatedCallback
Prototype for the callback that is invoked when a face is created (in response to an incoming connect...
void connectFaceClosedSignal(Face &face, std::function< void()> f)
Invokes a callback when a face is closed.
boost::optional< const ConfigSection & > OptionalConfigSection
An optional configuration file section.
boost::property_tree::ptree ConfigSection
A configuration file section.
#define NFD_REGISTER_PROTOCOL_FACTORY(PF)
Registers a protocol factory.
Options that control the behavior of GenericLinkService.
bool allowReassembly
Enables reassembly.
bool allowFragmentation
Enables fragmentation.
Parameters to ProtocolFactory constructor.