InterfaceId.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 "InterfaceId.hh"
18 
19 // Custom includes
20 #include <limits>
21 #include <boost/filesystem/fstream.hpp>
22 #include <boost/filesystem.hpp>
24 
25 #define prefix_
26 //-/////////////////////////////////////////////////////////////////////////////////////////////////
27 
28 namespace {
29  template <typename T>
30  T readTokenFromFile(boost::filesystem::path const & path)
31  {
32  boost::filesystem::ifstream file;
33  file.exceptions( std::ifstream::failbit | std::ifstream::badbit);
34  try {
35  file.open(path, std::ios::in);
36  T token;
37  file >> token;
38  file.close();
39  return token;
40  } catch (std::exception &) {
41  return T();
42  }
43  }
44 
45  int readHexFromFile(boost::filesystem::path const & path)
46  {
47  try {
48  return std::stoi(readTokenFromFile<std::string>(path), 0, 16);
49  } catch (std::exception &) {
50  return 0;
51  }
52  }
53 }
54 
56 // senf::emu::InterfaceDeviceId
57 
59 
61  : bus_(Unknown), vendor_(0), device_(0)
62 {}
63 
64 prefix_ senf::emu::InterfaceDeviceId::InterfaceDeviceId(Bus_t b, boost::uint16_t v, boost::uint16_t d)
65  : bus_(b), vendor_(v), device_(d)
66 {}
67 
68 prefix_ senf::emu::InterfaceDeviceId::InterfaceDeviceId(boost::uint8_t b, boost::uint16_t v, boost::uint16_t d)
69  : bus_(Unknown), vendor_(v), device_(d)
70 {
71  if (b == PCI) bus_ = PCI;
72  if (b == USB) bus_ = USB;
73  if (b == PCIe) bus_ = PCIe;
74 }
75 
77 {
78  boost::filesystem::directory_iterator end_itr;
79  for (boost::filesystem::directory_iterator itr ("/sys/class/net"); itr != end_itr; ++itr) {
80  if (not boost::filesystem::is_symlink(itr->path()))
81  continue;
82  if (readTokenFromFile<senf::MACAddress>(itr->path()/"address") != addr)
83  continue;
84  if (not boost::filesystem::exists(itr->path()/"device"))
85  continue;
86 
87  boost::uint16_t vendor (readHexFromFile(itr->path()/"device"/"vendor"));
88  boost::uint16_t device (readHexFromFile(itr->path()/"device"/"device"));
89  std::string b ("Unknown");
90  if (boost::filesystem::exists(itr->path()/"device"/"subsystem"))
91  b = boost::filesystem::canonical(itr->path()/"device"/"subsystem").filename().string();
92  Bus_t bus (Unknown);
93  if (b == "pci")
94  bus = PCI;
95  if (b == "pci_express")
96  bus = PCIe;
97  if (b == "usb")
98  bus = USB;
99 
100  return InterfaceDeviceId(bus, vendor, device);
101  }
102  return InterfaceDeviceId();
103 }
104 
105 std::ostream & senf::emu::operator<<(std::ostream & os, InterfaceDeviceId const & id)
106 {
107  senf::console::format(id, os);
108  return os;
109 }
110 
112  const
113 {
114  if (bus_ != other.bus_)
115  return bus_ < other.bus_;
116  if (vendor_ != other.vendor_)
117  return vendor_ < other.vendor_;
118  return device_ < other.device_;
119 }
120 
122  const
123 {
124  return bus_ == other.bus_ and
125  vendor_ == other.vendor_ and
126  device_ == other.device_;
127 }
128 
130  const
131 {
132  return bus_;
133 }
134 
136  const
137 {
138  return vendor_;
139 }
140 
142  const
143 {
144  return device_;
145 }
146 
148 // senf::emu::InterfaceIdFactoryBase
149 
151 {
152  return v_getId();
153 }
154 
156 {
157  v_releaseId(id);
158 }
159 
161 // senf::emu::SimpleInterfaceIdFactory
162 
163 prefix_ senf::MACAddress senf::emu::SimpleInterfaceIdFactory::v_getId()
164 {
165  boost::uint16_t id (calcFirstFreeId());
166  if (id != 0) {
167  idSet_.insert( id);
168  MACAddress mac (id);
169  mac[0] |= 0x02;
170  return mac;
171  }
172  return MACAddress::None;
173 }
174 
175 prefix_ void senf::emu::SimpleInterfaceIdFactory::v_releaseId(MACAddress const & id)
176 {
177  idSet_.erase( boost::uint16_t(id[4]) << 16 | boost::uint16_t(id[5]));
178 }
179 
180 prefix_ boost::uint32_t senf::emu::SimpleInterfaceIdFactory::calcFirstFreeId()
181 {
182  if (idSet_.empty())
183  return 1;
184  if (idSet_.size() == std::numeric_limits<uint16_t>::max())
185  return 0;
186  if (*idSet_.begin() > 1)
187  return 1;
188  IdSet::const_iterator i = std::adjacent_find(
189  idSet_.begin(), idSet_.end(), boost::lambda::_1+1 < boost::lambda::_2 );
190  if (i == idSet_.end()) --i;
191  return *i + 1;
192 }
193 
194 //-/////////////////////////////////////////////////////////////////////////////////////////////////
195 #undef prefix_
196 
197 
198 // Local Variables:
199 // mode: c++
200 // fill-column: 100
201 // comment-column: 40
202 // c-file-style: "senf"
203 // indent-tabs-mode: nil
204 // ispell-local-dictionary: "american"
205 // compile-command: "scons -u test"
206 // End:
static MACAddress const None
std::uint8_t mac[6]
boost::uint16_t device() const
Definition: InterfaceId.cc:141
std::int32_t max
static const InterfaceDeviceId None
Definition: InterfaceId.hh:41
bool operator==(InterfaceDeviceId const &other) const
Definition: InterfaceId.cc:121
bool operator<(InterfaceDeviceId const &other) const
Definition: InterfaceId.cc:111
InterfaceId public header.
boost::uint16_t vendor() const
Definition: InterfaceId.cc:135
std::ostream & operator<<(std::ostream &os, InterfaceDeviceId const &id)
Definition: InterfaceId.cc:105
#define prefix_
Definition: InterfaceId.cc:25
static InterfaceDeviceId get(senf::MACAddress const &addr)
Definition: InterfaceId.cc:76
void releaseId(MACAddress const &id)
Definition: InterfaceId.cc:155