TAPEthernetInterface.cc
Go to the documentation of this file.
1 //
2 // Copyright (c) 2020 Fraunhofer Institute for Applied Information Technology (FIT)
3 // Network Research Group (NET)
4 // Schloss Birlinghoven, 53754 Sankt Augustin, GERMANY
5 // Contact: support@wiback.org
6 //
7 // This file is part of the SENF code tree.
8 // It is licensed under the 3-clause BSD License (aka New BSD License).
9 // See LICENSE.txt in the top level directory for details or visit
10 // https://opensource.org/licenses/BSD-3-Clause
11 //
12 
13 
17 #include <linux/sockios.h>
18 #include <linux/filter.h>
19 #include "TAPEthernetInterface.hh"
20 
21 // Custom includes
22 
23 #define prefix_
24 //-/////////////////////////////////////////////////////////////////////////////////////////////////
25 
26 //-/////////////////////////////////////////////////////////////////////////////////////////////////
27 // senf::emu::detail::TAPEthernetInterfaceNet
28 
29 prefix_ senf::emu::detail::TAPEthernetInterfaceNet::TAPEthernetInterfaceNet(std::string const & device)
30  : socket (TapSocketHandle(device)),
31  dev_(device), ctrl_(device),
32  annotatorRx_(true, false, ctrl_.hardwareAddress()), annotatorTx_(false, false),
33  netOutput (annotatorRx_.output), netInput (annotatorTx_.input)
34 {
35  socket.blocking(false);
36 
37  senf::ppi::connect(source.output, annotatorRx_.input);
38  senf::ppi::connect(annotatorTx_.output, sink.input);
39 }
40 
41 prefix_ void senf::emu::detail::TAPEthernetInterfaceNet::assignSockets(bool on)
42 {
43  if (on) {
44  source.handle(socket);
45  sink.handle(socket);
46  } else {
47  source.handle( TapSocketHandle(senf::noinit));
48  sink.handle( TapSocketHandle(senf::noinit));
49  }
50 }
51 
52 //-/////////////////////////////////////////////////////////////////////////////////////////////////
53 // senf::emu::TAPEthernetInterface
54 
55 namespace {
56  struct DisableInterfaceGuard
57  {
58  DisableInterfaceGuard(senf::emu::Interface & iface)
59  : iface_ (iface), enabled_ (iface_.enabled())
60  { if (enabled_) iface_.disable(); }
61 
62  ~DisableInterfaceGuard()
63  { if (enabled_) iface_.enable(); }
64 
65  senf::emu::Interface & iface_;
66  bool enabled_;
67  };
68 }
69 
71  : TAPEthernetInterfaceNet(device),
72  EthernetInterface (netOutput, netInput),
73  pvid_(VLanId::None), accessMode_(false)
74 {
77 
78  namespace fty = console::factory;
79 
80  consoleDir()
81  .add("mmapStats", fty::Command(&TAPEthernetInterface::dumpMmapStats, this)
82  .doc("dumps and resets the socket's RX/TX statistics"));
83  consoleDir()
84  .add("maxBurst", fty::Command(
85  SENF_MEMBINDFNP(void, TAPEthernetInterface, maxBurst, (unsigned)))
86  .doc("set max burst rate"));
87  consoleDir()
88  .add("maxBurst", fty::Command(
89  SENF_MEMBINDFNP(unsigned, TAPEthernetInterface, maxBurst, () const))
90  .doc("get max burst rate"));
91  consoleDir()
92  .add("pvid", fty::Command(
93  SENF_MEMBINDFNP(bool, TAPEthernetInterface, pvid, (VLanId const &, bool)))
94  .doc( "enables filtering for a specific PVID (VLAN ID must be 0...4095)"));
95  consoleDir()
96  .add("pvid", fty::Command(
97  SENF_MEMBINDFNP(VLanId const &, TAPEthernetInterface, pvid, () const))
98  .doc( "report the currently configured PVID (-1 means none)"));
99 
100 
101  console::provideDirectory(interfaceDir(),"by-device").add(dev_, fty::Link(consoleDir()));
102 
103  annotatorRx_.id(id());
104 
105  if (enabled()) {
106  assignSockets(true);
107  }
108 }
109 
111 {
112  try {
113  console::provideDirectory(interfaceDir(),"by-device").remove(device());
114  } catch (...) {};
115 }
116 
118  const
119 {
120  return dev_;
121 }
122 
124 {
125  if (! enabled()) {
126  ctrl_.up();
127  }
128 
129  TAPEthernetInterfaceNet::assignSockets(true);
130 }
131 
133 {
134  if (enabled()) {
135  ctrl_.down();
136  }
137 
138  TAPEthernetInterfaceNet::assignSockets(false);
139 }
140 
141 prefix_ bool senf::emu::TAPEthernetInterface::v_enabled()
142  const
143 {
144  return ctrl_.isUp();
145 }
146 
147 prefix_ void senf::emu::TAPEthernetInterface::v_id(MACAddress const & mac)
148 {
149  DisableInterfaceGuard guard (*this);
150  ctrl_.hardwareAddress(mac);
151  annotatorRx_.id(mac);
152 }
153 
154 prefix_ senf::MACAddress senf::emu::TAPEthernetInterface::v_id()
155  const
156 {
157  return ctrl_.hardwareAddress();
158 }
159 
160 prefix_ bool senf::emu::TAPEthernetInterface::v_promisc()
161  const
162 {
163  return ctrl_.promisc();
164 }
165 
166 prefix_ void senf::emu::TAPEthernetInterface::v_promisc(bool p)
167 {
168  ctrl_.promisc(p);
169 }
170 
171 prefix_ bool senf::emu::TAPEthernetInterface::v_annotationMode()
172  const
173 {
174  return annotatorRx_.annotate();
175 }
176 
177 prefix_ void senf::emu::TAPEthernetInterface::v_annotationMode(bool a)
178 {
179  annotatorRx_.annotate(a);
180 }
181 
183  const
184 {
185  return ctrl_.mtu();
186 }
187 
189 {
190  ctrl_.mtu(v);
191 }
192 
193 prefix_ void senf::emu::TAPEthernetInterface::v_mcAdd(MACAddress const & address)
194 {
195  throw senf::SystemException("multicast not supported on TAP Interfaces", ENOSYS);
196 }
197 
198 prefix_ void senf::emu::TAPEthernetInterface::v_mcDrop(MACAddress const & address)
199 {
200  throw senf::SystemException("multicast not supported on TAP Interfaces", ENOSYS);
201 }
202 
203 
204 prefix_ void senf::emu::TAPEthernetInterface::v_flushRxQueues()
205 {
206  TAPEthernetInterfaceNet::source.flush();
207 }
208 
209 prefix_ bool senf::emu::TAPEthernetInterface::pvid(VLanId const & p, bool accessMode)
210 {
211  if (!accessMode and p.stag())
212  return false;
213 
214  pvid_ = p;
215  accessMode_ = accessMode;
216 
217  if (pvid_) {
218  if (accessMode_) {
219  annotatorRx_.insertTag(pvid_);
220  annotatorTx_.removeTag(pvid_);
221  } else {
222  annotatorRx_.removeTag(pvid_);
223  annotatorTx_.insertTag(pvid_);
224  }
225  } else {
226  annotatorRx_.clearTag();
227  annotatorTx_.clearTag();
228  }
229 
230  return true;
231 }
232 
234 {
235  return TAPEthernetInterfaceNet::annotatorRx_.vlanMismatch();
236 }
237 
239 {
240  return TAPEthernetInterfaceNet::annotatorTx_.vlanMismatch();
241 }
242 
244  const
245 {
246  return source.maxBurst();
247 }
248 
250 {
251  source.maxBurst(maxBurst);
252 }
253 
254 prefix_ void senf::emu::TAPEthernetInterface::dumpMmapStats(std::ostream & os)
255 {
256  if (TAPEthernetInterfaceNet::socket.valid()) {
257  os << "Socket acvtive (fd=" << socket.protocol().fd() << ", available " << socket.protocol().available() << "), RxStats: ";
258  source.rxStats().dump(os); os << " TxStats: "; sink.txStats().dump(os); os << std::endl;
259  } else {
260  os << "Socket closed. Not stats available." << std::endl;
261  }
262 }
263 
264 //-/////////////////////////////////////////////////////////////////////////////////////////////////
265 #undef prefix_
266 
267 
268 // Local Variables:
269 // mode: c++
270 // fill-column: 100
271 // comment-column: 40
272 // c-file-style: "senf"
273 // indent-tabs-mode: nil
274 // ispell-local-dictionary: "american"
275 // compile-command: "scons -u test"
276 // End:
Interface API base class
std::string const & v_device() const override
Hardware Ethernet Interface.
#define SENF_MEMBINDFNP(ret, cls, fn, args)
std::uint8_t mac[6]
bool enabled() const
true, if interface enabled
noinit
TAPEthernetInterface public header.
console::DirectoryNode & consoleDir() const
Access interface console directory.
bool stag() const
std::string const & device() const
NodeType & add(std::string const &name, boost::shared_ptr< NodeType > node)
virtual void v_disable() override
Called to disable interface.
ProtocolClientSocketHandle< TapSocketProtocol > TapSocketHandle
console::DirectoryNode & interfaceDir()
virtual void v_enable() override
Called to enable interface.
TAPEthernetInterface(std::string const &name)
virtual unsigned v_mtu() const override
Called to get interface MTU.
VLanId const & pvid() const
#define prefix_