ethernet-factory.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "ethernet-factory.hpp"
27 #include "ethernet-transport.hpp"
28 #include "generic-link-service.hpp"
29 #include "core/logger.hpp"
30 #include <boost/range/adaptors.hpp>
31 #include <boost/range/algorithm/copy.hpp>
32 
33 namespace nfd {
34 namespace face {
35 
36 NFD_LOG_INIT("EthernetFactory");
37 NFD_REGISTER_PROTOCOL_FACTORY(EthernetFactory);
38 
39 const std::string&
41 {
42  static std::string id("ether");
43  return id;
44 }
45 
46 
47 void
50 {
51  // ether
52  // {
53  // mcast yes
54  // mcast_group 01:00:5E:00:17:AA
55  // whitelist
56  // {
57  // *
58  // }
59  // blacklist
60  // {
61  // }
62  // }
63 
64  MulticastConfig mcastConfig;
65 
66  if (configSection) {
67  // face_system.ether.mcast defaults to 'yes' but only if face_system.ether section is present
68  mcastConfig.isEnabled = true;
69 
70  for (const auto& pair : *configSection) {
71  const std::string& key = pair.first;
72  const ConfigSection& value = pair.second;
73 
74  if (key == "mcast") {
75  mcastConfig.isEnabled = ConfigFile::parseYesNo(pair, "ether");
76  }
77  else if (key == "mcast_group") {
78  const std::string& valueStr = value.get_value<std::string>();
79  mcastConfig.group = ethernet::Address::fromString(valueStr);
80  if (mcastConfig.group.isNull()) {
81  BOOST_THROW_EXCEPTION(ConfigFile::Error("face_system.ether.mcast_group: '" +
82  valueStr + "' cannot be parsed as an Ethernet address"));
83  }
84  else if (!mcastConfig.group.isMulticast()) {
85  BOOST_THROW_EXCEPTION(ConfigFile::Error("face_system.ether.mcast_group: '" +
86  valueStr + "' is not a multicast address"));
87  }
88  }
89  else if (key == "whitelist") {
90  mcastConfig.netifPredicate.parseWhitelist(value);
91  }
92  else if (key == "blacklist") {
93  mcastConfig.netifPredicate.parseBlacklist(value);
94  }
95  else {
96  BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option face_system.ether." + key));
97  }
98  }
99  }
100 
101  if (!context.isDryRun) {
102  if (m_mcastConfig.isEnabled != mcastConfig.isEnabled) {
103  if (mcastConfig.isEnabled) {
104  NFD_LOG_INFO("enabling multicast on " << mcastConfig.group);
105  }
106  else {
107  NFD_LOG_INFO("disabling multicast");
108  }
109  }
110  else if (m_mcastConfig.group != mcastConfig.group) {
111  NFD_LOG_INFO("changing multicast group from " << m_mcastConfig.group <<
112  " to " << mcastConfig.group);
113  }
114  else if (m_mcastConfig.netifPredicate != mcastConfig.netifPredicate) {
115  NFD_LOG_INFO("changing whitelist/blacklist");
116  }
117  else {
118  // There's no configuration change, but we still need to re-apply configuration because
119  // netifs may have changed.
120  }
121 
122  m_mcastConfig = mcastConfig;
123  this->applyConfig(context);
124  }
125 }
126 
127 void
128 EthernetFactory::createFace(const FaceUri& uri,
129  ndn::nfd::FacePersistency persistency,
130  bool wantLocalFieldsEnabled,
131  const FaceCreatedCallback& onCreated,
132  const FaceCreationFailedCallback& onFailure)
133 {
134  onFailure(406, "Unsupported protocol");
135 }
136 
137 std::vector<shared_ptr<const Channel>>
139 {
140  return {};
141 }
142 
143 shared_ptr<Face>
144 EthernetFactory::createMulticastFace(const NetworkInterfaceInfo& netif,
145  const ethernet::Address& address)
146 {
147  BOOST_ASSERT(address.isMulticast());
148 
149  auto key = std::make_pair(netif.name, address);
150  auto found = m_mcastFaces.find(key);
151  if (found != m_mcastFaces.end()) {
152  return found->second;
153  }
154 
156  opts.allowFragmentation = true;
157  opts.allowReassembly = true;
158 
159  auto linkService = make_unique<face::GenericLinkService>(opts);
160  auto transport = make_unique<face::EthernetTransport>(netif, address);
161  auto face = make_shared<Face>(std::move(linkService), std::move(transport));
162 
163  m_mcastFaces[key] = face;
164  connectFaceClosedSignal(*face, [this, key] { m_mcastFaces.erase(key); });
165 
166  return face;
167 }
168 
169 void
170 EthernetFactory::applyConfig(const FaceSystem::ConfigContext& context)
171 {
172  // collect old faces
173  std::set<shared_ptr<Face>> oldFaces;
174  boost::copy(m_mcastFaces | boost::adaptors::map_values,
175  std::inserter(oldFaces, oldFaces.end()));
176 
177  if (m_mcastConfig.isEnabled) {
178  // determine interfaces on which faces should be created or retained
179  auto capableNetifs = context.listNetifs() |
180  boost::adaptors::filtered([this] (const NetworkInterfaceInfo& netif) {
181  return netif.isUp() && netif.isMulticastCapable() &&
182  m_mcastConfig.netifPredicate(netif);
183  });
184 
185  // create faces
186  for (const auto& netif : capableNetifs) {
187  shared_ptr<Face> face;
188  try {
189  face = this->createMulticastFace(netif, m_mcastConfig.group);
190  }
191  catch (const EthernetTransport::Error& e) {
192  NFD_LOG_ERROR("Cannot create Ethernet multicast face on " << netif.name << ": " <<
193  e.what() << ", continuing");
194  continue;
195  }
196 
197  if (face->getId() == face::INVALID_FACEID) {
198  // new face: register with forwarding
199  context.addFace(face);
200  }
201  else {
202  // existing face: don't destroy
203  oldFaces.erase(face);
204  }
205  }
206  }
207 
208  // destroy old faces that are not needed in new configuration
209  for (const auto& face : oldFaces) {
210  face->close();
211  }
212 }
213 
214 } // namespace face
215 } // namespace nfd
contains information about a network interface
void connectFaceClosedSignal(Face &face, const std::function< void()> &f)
invokes a callback when the face is closed
Definition: channel.cpp:41
std::vector< shared_ptr< const Channel > > getChannels() const override
#define NFD_LOG_ERROR(expression)
Definition: logger.hpp:164
static bool parseYesNo(const ConfigSection &node, const std::string &key, const std::string &sectionName)
parse a config option that can be either "yes" or "no"
Definition: config-file.cpp:62
#define NFD_REGISTER_PROTOCOL_FACTORY(PF)
registers a protocol factory
context for processing a config section in ProtocolFactory
Definition: face-system.hpp:77
#define NFD_LOG_INFO(expression)
Definition: logger.hpp:162
Copyright (c) 2014-2015, Regents of the University of California, Arizona Board of Regents...
boost::optional< const ConfigSection & > OptionalConfigSection
an optional config file section
Definition: config-file.hpp:41
static const std::string & getId()
boost::property_tree::ptree ConfigSection
a config file section
Definition: config-file.hpp:37
void createFace(const FaceUri &uri, ndn::nfd::FacePersistency persistency, bool wantLocalFieldsEnabled, const FaceCreatedCallback &onCreated, const FaceCreationFailedCallback &onFailure) override
unicast face creation is not supported and will always fail
function< void(uint32_t status, const std::string &reason)> FaceCreationFailedCallback
Prototype for the callback that is invoked when the face fails to be created.
Definition: channel.hpp:44
#define NFD_LOG_INIT(name)
Definition: logger.hpp:122
void processConfig(OptionalConfigSection configSection, FaceSystem::ConfigContext &context) override
process face_system.ether config section
function< void(const shared_ptr< Face > &newFace)> FaceCreatedCallback
Prototype for the callback that is invoked when the face is created (as a response to incoming connec...
Definition: channel.hpp:38
const FaceId INVALID_FACEID
indicates an invalid FaceId
Definition: face.hpp:42