InterfaceAPI.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 "InterfaceAPI.hh"
18 
19 // Custom includes
20 #include <time.h>
21 #include <unistd.h>
22 #include <boost/format.hpp>
26 #include <senf/Utils/Statistics.hh>
27 #include <senf/Utils/String.hh>
28 #include "Version.hh"
29 
30 #define prefix_
31 //-/////////////////////////////////////////////////////////////////////////////////////////////////
32 
33 //-/////////////////////////////////////////////////////////////////////////////////////////////////
34 // senf::emu::Interface
35 
36 unsigned senf::emu::Interface::nodeId_ (::getpid());
37 
39 {
40  namespace kw = console::kw;
41  namespace fty = console::factory;
42 
43  consoleDir().add("enable", fty::Command(&Interface::enable, this)
44  .doc("Enable (ifconfig up) interface") );
45  consoleDir().add("disable", fty::Command(&Interface::disable, this)
46  .doc("Disable (ifconfig down) interface") );
47  consoleDir().add("enabled", fty::Command(&Interface::enabled, this)
48  .formatter(console::formatEnabledDisabled)
49  .doc("Check, whether interface is enabled.") );
50  consoleDir().add("id", fty::Command(SENF_MEMBINDFNP(void, Interface, id, (MACAddress const &)))
51  .arg("id","new interface EUID")
52  .overloadDoc("Set interface id (MACAddress)") );
53  consoleDir().add("id", fty::Command(SENF_MEMBINDFNP(MACAddress const &, Interface, id, () const))
54  .overloadDoc("Get interface id (MACAddress)") );
55  consoleDir().add("deviceId", fty::Command(SENF_MEMBINDFNP(InterfaceDeviceId, Interface, deviceId, () const ))
56  .overloadDoc("Get interface device id") );
57  consoleDir().add("deviceId", fty::Command(SENF_MEMBINDFNP(void, Interface, deviceId, (InterfaceDeviceId) ))
58  .overloadDoc("Set interface device id)") );
59  consoleDir().add("device", fty::Command(SENF_MEMBINDFNP(std::string const &, Interface, device, () const ))
60  .overloadDoc("Returns the interface device name") );
61  consoleDir().add("type", fty::Command(&Interface::interfaceTypeName, this)
62  .doc("Get interface type") );
63  console::DirectoryNode & stats (consoleDir().add("stats", fty::Directory()));
64  stats.add("statistics-interval", fty::Command<void (ClockService::clock_type)>(boost::ref(startStatistics))
65  .arg("interval", "Statistics interval",
66  kw::parser=senf::parseClockServiceInterval)
67  .doc("Set the interval, at which statistics output is generated from this interface.\n"
68  "Without setting an interval, NO statistics will be generated.") );
69 
70  index_ = 1;
71  deviceId_ = InterfaceDeviceId::get(id());
72  std::string name (senf::str(index_));
73  while (interfaceDir().hasChild(name))
74  name = senf::str(++index_);
75  interfaceDir().add(name, consoleDir());
76  console::DirectoryNode & iddir (console::provideDirectory(interfaceDir(),"by-id"));
77  std::string idstr (senf::str(id()));
78  if (! iddir.hasChild(idstr))
79  iddir.add(idstr, fty::Link(consoleDir()));
80 }
81 
83 {
84  MACAddress oldId = id_;
85  v_id( mac);
86  id_ = mac;
87  console::DirectoryNode & iddir (console::provideDirectory(interfaceDir(), "by-id"));
88  if (iddir.hasChild(senf::str(oldId)))
89  iddir.remove(senf::str(oldId));
90  iddir.add(senf::str(id()), console::factory::Link(consoleDir()));
91  idChangedSignal( *this, oldId);
92 }
93 
94 prefix_ boost::optional<senf::Statistics &> senf::emu::Interface::statistic(std::string const & name)
95 {
96  Statistics::iterator i (statistics_.find(name));
97  if (i != statistics_.end())
98  return boost::optional<senf::Statistics &>( *(i->second));
99  return boost::optional<senf::Statistics &>();
100 }
101 
102 //-/////////////////////////////////////////////////////////////////////////////////////////////////
103 // senf::emu::Receiver
104 
105 prefix_ void senf::emu::Receiver::init()
106 {
107  namespace fty = console::factory;
108  interface().consoleDir().add("promisc",
109  fty::Command(SENF_MEMBINDFNP(void, Receiver, promisc, (bool) ))
110  .overloadDoc("Enable/disable promiscuous mode.") );
111  interface().consoleDir().add("promisc",
112  fty::Command(SENF_MEMBINDFNP(bool, Receiver, promisc, () const))
113  .overloadDoc("Get promiscuous state.") );
114  interface().consoleDir().add("annotate",
115  fty::Command(SENF_MEMBINDFNP(void, Receiver, annotationMode, (bool) ))
116  .overloadDoc("Enable/disable annotation mode.") );
117  interface().consoleDir().add("annotate",
118  fty::Command(SENF_MEMBINDFNP(bool, Receiver, annotationMode, () const))
119  .overloadDoc("Get annotation mode (on/off).") );
120  interface().consoleDir().add("mcAdd",
121  fty::Command(&Receiver::mcAdd, this)
122  .overloadDoc("Add multicast address to interface.") );
123  interface().consoleDir().add("mcDrop",
124  fty::Command(&Receiver::mcDrop, this)
125  .overloadDoc("Drop multicast address from interface.") );
126  interface().consoleDir().add("flushRxQueues",
127  fty::Command(&Receiver::flushRxQueues, this)
128  .overloadDoc("Flushes the Rx queues where possible.") );
129 }
130 
131 //-/////////////////////////////////////////////////////////////////////////////////////////////////
132 // senf::emu::Transmitter
133 
134 prefix_ void senf::emu::Transmitter::init()
135 {
136  namespace fty = console::factory;
137  interface().consoleDir().add("mtu",
138  fty::Command(SENF_MEMBINDFNP(void, Transmitter, mtu, (unsigned) ))
139  .overloadDoc("Set MTU.") );
140  interface().consoleDir().add("mtu",
141  fty::Command(SENF_MEMBINDFNP(unsigned, Transmitter, mtu, () const))
142  .overloadDoc("Get MTU.") );
143  interface().consoleDir().add("flushTxQueues",
144  fty::Command(&Transmitter::flushTxQueues, this)
145  .overloadDoc("Flushes the Tx queues where possible.") );
146 }
147 
148 //-/////////////////////////////////////////////////////////////////////////////////////////////////
149 
150 namespace {
151 
152  struct InterfaceDir
153  {
154  InterfaceDir() {
155  namespace fty = senf::console::factory;
156  dir.add("nodeId", fty::Command(SENF_FNP(unsigned, senf::emu::Interface::nodeId, ()))
157  .doc("Get or set node id.\n"
158  "The nodeId defaults to the process id") );
159  dir.add("nodeId", fty::Command(SENF_FNP(void, senf::emu::Interface::nodeId, (unsigned)))
160  .arg("id","new node id") );
161  senf::console::sysdir().add("interfaces", dir);
162  }
164  };
165 
166  senf::console::SysInfo::Proxy addSysInfo ("NetEmu",
167  "SENF NetEmu: The PPI Network Emulator\n"
168  " (c) 2020 Fraunhofer Institute for Applied Information Technology (FIT)\n"
169  " Contact: http://wiback.org\n"
170  " Version: " SENF_NETEMU_LIB_VERSION "\n", 1);
171 
172  boost::uint16_t initIndex()
173  {
174  boost::uint32_t tm (::time(0));
176  tm = tm ^ (tm >> 16) ^ senf::ClockService::in_nanoseconds(clk) ^ ::getpid();
177  return senf::emu::perturb(tm);
178  }
179 
180  boost::uint16_t & macIdIndex()
181  {
182  static boost::uint16_t index (initIndex());
183  return index;
184  }
185 
186  // Just for the fun of it ... This is the AES/Rijndael substitution table
187  // This is a bijective, non-linear transformation with no fixed points
188  boost::uint8_t aesSubst[] = {
189  0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,
190  0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
191  0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,
192  0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
193  0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,
194  0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
195  0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed,
196  0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
197  0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f,
198  0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
199  0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
200  0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
201  0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,
202  0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
203  0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
204  0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
205  0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f,
206  0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
207  0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11,
208  0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
209  0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f,
210  0xb0, 0x54, 0xbb, 0x16
211  };
212 
213 }
214 
216 {
217  static InterfaceDir interfaceDir;
218  return interfaceDir.dir.node();
219 }
220 
221 prefix_ boost::uint16_t senf::emu::perturb(boost::uint16_t value)
222 {
223  boost::uint8_t high (aesSubst[(value>>8) & 0xff]);
224  boost::uint8_t low (aesSubst[value & 0xffu]);
225  return (((low+high) & 0xff)<<8) | ((low-high)&0xff);
226 }
227 
228 prefix_ void senf::emu::macIdSeed(boost::uint16_t seed)
229 {
230  macIdIndex() = seed;
231 }
232 
234 {
235  // These MAC's are NOT random, they are UNIQUE ...
236  boost::uint16_t index (perturb(macIdIndex()++));
237  MACAddress eui;
238  eui[0] = ((magic>>24) & 0xfcu) | 0x02u;
239  eui[1] = (magic>>16) & 0xffu;
240  eui[2] = (magic>>8) & 0xffu;
241 // eui[3] = magic & 0xffu;
242  eui[3] = ::getpid() & 0xffu; // increase the randomness space by 8 more bits
243  eui[4] = (index>>8) & 0xffu;
244  eui[5] = index & 0xffu;
245  return eui;
246 }
247 
248 //-/////////////////////////////////////////////////////////////////////////////////////////////////
249 #undef prefix_
250 
251 
252 // Local Variables:
253 // mode: c++
254 // fill-column: 100
255 // comment-column: 40
256 // c-file-style: "senf"
257 // indent-tabs-mode: nil
258 // ispell-local-dictionary: "american"
259 // compile-command: "scons -u test"
260 // End:
boost::uint16_t perturb(boost::uint16_t value)
config::time_type clock_type
void macIdSeed(boost::uint16_t seed)
Re-seed the MACAddress address generator.
Interface API base class
#define SENF_FNP(ret, fn, args)
#define SENF_MEMBINDFNP(ret, cls, fn, args)
std::uint8_t mac[6]
unsigned index() const
Get interface index.
bool enabled() const
true, if interface enabled
void flushRxQueues()
Flush Rx Queues.
InterfaceDeviceId deviceId() const
bool hasChild(std::string const &name) const
static unsigned nodeId()
Get unique node id.
void init()
Initialize interface.
Definition: InterfaceAPI.cc:38
static SENF_CLOCKSERVICE_CONSTEXPR int64_type in_nanoseconds(clock_type const &v)
console::DirectoryNode & consoleDir() const
Access interface console directory.
std::string const & device() const
NodeType & add(std::string const &name, boost::shared_ptr< NodeType > node)
MACAddress const & id() const
Get interface MAC Address.
InterfaceAPI public header.
Interface API base class for receive capable interfaces.
void startStatistics(ClockService::clock_type inverval)
Start statistics generation.
Interface API base class for transmit capable interfaces.
void mcDrop(senf::MACAddress const &address)
console::DirectoryNode & interfaceDir()
#define prefix_
Definition: InterfaceAPI.cc:30
unspecified_keyword_type name
virtual MACAddress v_id() const =0
Return the interface mac address.
MACAddress uniqueMAC(boost::uint32_t magic)
Get pseudo-random but unique MACAddress.
static clock_type now()
GenericNode::ptr remove(std::string const &name)
void flushTxQueues()
Flush Tx Queues.
std::string interfaceTypeName() const
void mcAdd(senf::MACAddress const &address)
static InterfaceDeviceId get(senf::MACAddress const &addr)
Definition: InterfaceId.cc:76
boost::signals2::signal< void(Interface &, MACAddress)> idChangedSignal
boost::optional< senf::Statistics & > statistic(std::string const &name)
Get registered statistic.
Definition: InterfaceAPI.cc:94
void disable()
Disable interface (aka ifconfig down)
void enable()
Enable interface (aka ifconfig up)