WLANInterface.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 "WLANInterface.hh"
18 
19 // Custom includes
21 #include <senf/Utils/String.hh>
22 #include <senf/Utils/senflikely.hh>
23 
24 #define prefix_
25 //-/////////////////////////////////////////////////////////////////////////////////////////////////
26 
27 //-/////////////////////////////////////////////////////////////////////////////////////////////////
28 // senf::emu::WLANModulationParameter / -Registry
29 
30 namespace {
32  { "BPSK/DSSS", 1000, -82, },
33  { "QPSK/DSSS", 2000, -82, },
34  { "CCK55", 5500, -82, },
35  { "CCK11", 11000, -82, },
36  };
38  { "BPSK 1/2", 6000, -81, },
39  { "BPSK 3/4", 9000, -81, },
40  { "QPSK 1/2", 12000, -79, },
41  { "QPSK 3/4", 18000, -77, },
42  { "16QAM 1/2", 24000, -74, },
43  { "16QAM 3/4", 36000, -70, },
44  { "64QAM 2/3", 48000, -66, },
45  { "64QAM 3/4", 54000, -65, },
46  };
47 }
48 
49 prefix_ std::vector<senf::emu::WLANModulationParameterRegistry::LegacyModulationInfo>
51 {
52  return std::vector<LegacyModulationInfo>(legacyInfos11b, legacyInfos11b + sizeof(legacyInfos11b) / sizeof(LegacyModulationInfo));
53 }
54 
55 prefix_ std::vector<senf::emu::WLANModulationParameterRegistry::LegacyModulationInfo>
57 {
58  return std::vector<LegacyModulationInfo>(legacyInfosOFDM, legacyInfosOFDM + sizeof(legacyInfosOFDM) / sizeof(LegacyModulationInfo));
59 }
60 
61 prefix_ senf::emu::WLANModulationParameterRegistry::WLANModulationParameterRegistry()
62 {
63  // register HT modulations
65  if (info.index >= WLAN_MCSInfo::NUM_HT_INDEX)
66  continue;
67  for (unsigned i=0; i<4; ++i) {
68  if (info.rate[i] == 0)
69  continue;
71  info.coding, info.rssi[i/2], info.rate[i], WLAN_MCSInfo::fromBandwidthIndex(i),
72  WLANModulationParameter::HT, info.streams, WLAN_MCSInfo::toHTIndex(info.index, info.streams),
73  (i%2==1));
74  registerModulation( p);
75  }
76  }
77  // register VHT modulations
79  if (info.index >= WLAN_MCSInfo::NUM_VHT_INDEX)
80  continue;
81  for (unsigned i=0; i<8; ++i) {
82  if (info.rate[i] == 0)
83  continue;
85  info.coding, info.rssi[i/2], info.rate[i], WLAN_MCSInfo::fromBandwidthIndex(i),
86  WLANModulationParameter::VHT, info.streams, info.index, (i%2==1));
87  registerModulation( p);
88  }
89  }
90  // register non-HT legacy modulations
91  for (LegacyModulationInfo const & mod : legacyInfos11b) {
92  WLANModulationParameter p (mod.coding, mod.rssi, mod.rate, 20000, WLANModulationParameter::Legacy, 1, 0);
93  registerModulation( p);
94  }
95  // add a 'pseudo' index for OFDM rates to allow treating them silimar to HT/VHT below
96  unsigned ind(0);
97  for (LegacyModulationInfo const & mod : legacyInfosOFDM) {
98  WLANModulationParameter p (mod.coding, mod.rssi, mod.rate, 20000, WLANModulationParameter::Legacy, 1, ind++);
99  registerModulation( p);
100  }
101  // register the two 'special' modulations
102  {
103  WLANModulationParameter p ("auto", 0, 0, 0, WLANModulationParameter::Automatic, 0, 0, false);
104  parameterIdAuto_ = registerModulation( p);
105  } {
106  WLANModulationParameter p ("unknown", 0, 0, 0, WLANModulationParameter::Unknown, 0, 0, false);
107  parameterIdUnknown_ = registerModulation( p);
108  }
109 }
110 
111 prefix_ boost::uint32_t senf::emu::WLANModulationParameterRegistry::registerModulation(WLANModulationParameter & p)
112 {
114  modulations_.insert(std::make_pair(id, p));
115  idMap_.insert(std::make_pair(WLANModulationParameter::modulationId(
116  p.type, p.rate, p.bandwidth, p.index, p.streams, p.shortGI), id));
117  return id;
118 }
119 
121  const
122 {
123  Modulations::const_iterator it (modulations_.find(id));
124  if (it == modulations_.end())
125  throw ModulationParameter::Error() << id << " (unknown id)";
126  return it->second;
127 }
128 
130  const
131 {
132  try {
133  return idMap_.at(WLANModulationParameter::modulationId(
134  WLANModulationParameter::Legacy, rate, 0, 0, 0, false));
135  }
136  catch(...) {
137  return parameterIdUnknown_;
138  }
139 }
140 
142  const
143 {
144  try {
145  return idMap_.at(WLANModulationParameter::modulationId(
146  WLANModulationParameter::HT, 0, bandwidth, htMcsIndex, 0, shortGI));
147  }
148  catch(...) {
149  return parameterIdUnknown_;
150  }
151 }
152 
153 prefix_ senf::emu::ModulationParameter::id_t senf::emu::WLANModulationParameterRegistry::parameterIdByMCS_VHT(unsigned vhtMcsIndex, unsigned streams, unsigned bandwidth, bool shortGI)
154  const
155 {
156  try {
157  return idMap_.at(WLANModulationParameter::modulationId(
158  WLANModulationParameter::VHT, 0, bandwidth, vhtMcsIndex, streams, shortGI));
159  }
160  catch(...) {
161  return parameterIdUnknown_;
162  }
163 }
164 
166  const
167 {
168  Modulations::const_iterator it (modulations_.find(id));
169  if (it == modulations_.end() or (id == parameterIdUnknown_))
170  return std::set<senf::emu::ModulationParameter::id_t> ();
171 
172  std::set<ModulationParameter::id_t> res;
173  for (auto const & m : modulations_) {
174  if ((m.second.type == it->second.type) and (m.second.rate > 0) and (m.second.bandwidth == it->second.bandwidth) and (m.second.streams <= it->second.streams)) {
175  switch (giMatch) {
176  case Any:
177  res.emplace(m.first);
178  break;
179  case Equal:
180  if (m.second.shortGI == it->second.shortGI)
181  res.emplace(m.first);
182  break;
183  case Short:
184  if (m.second.shortGI)
185  res.emplace(m.first);
186  break;
187  case Long:
188  if (!m.second.shortGI)
189  res.emplace(m.first);
190  break;
191  }
192  }
193  }
194  return res;
195 }
196 
198  const
199 {
200  Modulations::const_iterator it (modulations_.find(id));
201  if (it == modulations_.end())
202  return parameterIdUnknown_;
203 
204  for (auto const & m : modulations_) {
205  if ((m.second.type == it->second.type) and (m.second.rate > 0) and (m.second.bandwidth == it->second.bandwidth)
206  and (m.second.streams == it->second.streams) and (m.second.index == it->second.index)) {
207  if (m.second.shortGI)
208  return m.first;
209  }
210  }
211 
212  return parameterIdUnknown_;
213 }
214 
216  const
217 {
218  Modulations::const_iterator it (modulations_.find(id));
219  if (it == modulations_.end())
220  return parameterIdUnknown_;
221 
222  for (auto const & m : modulations_) {
223  if ((m.second.type == it->second.type) and (m.second.rate > 0) and (m.second.bandwidth == it->second.bandwidth)
224  and (m.second.streams == it->second.streams) and (m.second.index == it->second.index)) {
225  if (!m.second.shortGI)
226  return m.first;
227  }
228  }
229 
230  return parameterIdUnknown_;
231 }
232 
234  const
235 {
236  Modulations::const_iterator it (modulations_.find(id));
237  if (it == modulations_.end() or (id == parameterIdUnknown_))
238  return parameterIdUnknown_;
239 
240  if (it->second.index < diff)
241  diff = it->second.index;
242 
243  while (diff > 0) {
244  for (auto const & m : modulations_) {
245  if ((m.second.type == it->second.type) and (m.second.rate > 0) and (m.second.bandwidth == it->second.bandwidth) and (m.second.shortGI == it->second.shortGI)
246  and (m.second.streams == it->second.streams) and (m.second.index == it->second.index - diff)) {
247  return m.first;
248  }
249  }
250  diff--;
251  }
252 
253  return id;
254 }
255 
256 
258  const
259 {
260  return parameterIdAuto_;
261 }
262 
264  const
265 {
266  return parameterIdUnknown_;
267 }
268 
269 prefix_ senf::emu::WLANModulationParameter::WLANModulationParameter(std::string const & _label, short _minRssi,
270  unsigned _rate, unsigned _bandwidth, Type _type, unsigned _streams, unsigned _index, bool _shortGI)
271  : ModulationParameter(_label, _minRssi, _rate, _bandwidth, WLANInterface::linkTypeId),
272  type(_type), index(_index), streams(_streams), shortGI(_shortGI)
273 {}
274 
275 prefix_ boost::uint16_t senf::emu::WLANModulationParameter::v_modulationId()
276  const
277 {
278  return modulationId(type, rate, bandwidth, index, streams, shortGI);
279 }
280 
281 prefix_ boost::uint16_t senf::emu::WLANModulationParameter::modulationId(Type _type, unsigned _rate,
282  unsigned _bandwidth, unsigned _index, unsigned _streams, bool _shortGI)
283 {
284  switch (_type) {
285  case Legacy:
286  return 1000 + _rate;
287  case VHT:
288  return 200 + ((_index + (_streams-1) * WLAN_MCSInfo::MAX_INDEX) * 8u) + WLAN_MCSInfo::toBandwidthIndex(_bandwidth, _shortGI);
289  case HT:
290  return 2 + (_index * 4) + WLAN_MCSInfo::toBandwidthIndex(_bandwidth, _shortGI);
291  case Automatic:
292  return 1;
293  case Unknown:
294  return 0;
295  }
296  return 0;
297 }
298 
299 prefix_ senf::emu::ModulationParameter * senf::emu::WLANModulationParameter::v_clone()
300  const
301 {
302  return new WLANModulationParameter(*this);
303 }
304 
305 prefix_ void senf::emu::WLANModulationParameter::v_dump(std::ostream & os)
306  const
307 {
308  static const char * types[] = { "Legacy", "MCS", "Automatic", "Unknown" };
309  os << " type: " << (type <= Unknown ? types[type] : "?") << std::endl
310  << "MCS Index: " << ((type==HT or type == VHT) ? senf::str(index) : "-") << std::endl
311  << "# streams: " << streams << std::endl
312  << " short GI: " << (shortGI ? "true" : "false") << std::endl;
313 }
314 
315 prefix_ void senf::emu::WLANModulationParameter::v_dumpTableHeader(std::ostream & os)
316  const
317 {
318  boost::format fmt ("%5d %7d %8s");
319  os << fmt % "index" % "streams" % "short GI";
320 }
321 
322 prefix_ void senf::emu::WLANModulationParameter::v_dumpTableRow(std::ostream & os)
323  const
324 {
325  boost::format fmt ("%5d %7d %8s");
326  os << fmt % ((type==HT or type == VHT) ? senf::str(index) : " - ") % streams % (shortGI ? "true" : "false");
327 }
328 
329 //-/////////////////////////////////////////////////////////////////////////////////////////////////
330 // senf::emu::WLANInterface
331 
333 {
337 
338  namespace fty = console::factory;
339  consoleDir().add("modulation", fty::Command(
340  SENF_MEMBINDFNP(void, WLANInterface, modulation, (WLANModulationParameter::Type, unsigned value) ))
341  .arg("type", "'mcs' or 'legacy'")
342  .arg("value", "modulation value; mcs index or legacy rate")
343  .doc("set modulation") );
344  consoleDir().add("modulation", fty::Command(
346  .arg("type", "must be 'auto'")
347  .doc("set modulation to auto") );
348 }
349 
351 {
352  switch (type) {
355  index, streams, bandwidth(), false));
356  return;
357  default:
358  throw InvalidArgumentException("invalid argument for modulation; two arguments (index + stream) required.");
359  }
360 }
361 
363 {
364  switch (type) {
367  value, bandwidth(), false));
368  return;
371  return;
373  throw InvalidArgumentException("invalid argument for vht modulation: argument missing");
375  throw InvalidArgumentException("invalid argument for auto-modulation; no argument required.");
377  throw InvalidArgumentException("invalid wlan modulation type: unknown");
378  }
379 }
380 
382 {
383  switch (type) {
386  return;
388  throw InvalidArgumentException("invalid wlan modulation type: unknown");
389  default:
390  throw InvalidArgumentException("argument missing for modulation setting.");
391  }
392 }
393 
394 prefix_ boost::uint8_t senf::emu::WLANInterface::v_linkTypeId()
395  const
396 {
397  return linkTypeId;
398 }
399 
401  const
402 {
403  unsigned maxNSS (0);
404  for (auto const & m : modulationParameterIds()) {
407  maxNSS = std::max(maxNSS, id.streams);
408  }
409  }
410 
411  return maxNSS;
412 }
413 
414 //-/////////////////////////////////////////////////////////////////////////////////////////////////
415 #undef prefix_
416 
417 
418 // Local Variables:
419 // mode: c++
420 // fill-column: 100
421 // comment-column: 40
422 // c-file-style: "senf"
423 // indent-tabs-mode: nil
424 // ispell-local-dictionary: "american"
425 // compile-command: "scons -u test"
426 // End:
unsigned registerModulation(ModulationParameter &parameter)
#define SENF_MEMBINDFNP(ret, cls, fn, args)
static boost::uint16_t modulationId(Type _type, unsigned _rate, unsigned _bandwidth, unsigned _index, unsigned _streams, bool _shortGI)
ModulationParameter::id_t parameterIdByMCS_HT(unsigned htMcsIndex, unsigned bandwidth, bool shortGI) const
ModulationParameter::id_t parameterIdAuto() const
ModulationParameter::id_t parameterIdByLegacyRate(unsigned rate) const
u8 type
unsigned bandwidth
Bandwidth in KHz.
ModulationParameter::id_t parameterIdLower(ModulationParameter::id_t id, unsigned diff) const
boost::uint8_t linkTypeId() const
static constexpr unsigned NUM_HT_INDEX
Wireless modulation parameter.
std::int32_t max
#define prefix_
static constexpr unsigned MAX_INDEX
std::set< ModulationParameter::id_t > parameterIdsByType(ModulationParameter::id_t id, GIMatch giMatch=Any) const
static std::vector< LegacyModulationInfo > getLegacyModulationInfosOFDM()
unsigned rate
Bitrate in kbit/s.
ModulationParameter::id_t parameterIdByMCS_VHT(unsigned vhtMcsIndex, unsigned streams, unsigned bandwidth, bool shortGI) const
console::ScopedDirectory & consoleDir()
static std::vector< LegacyModulationInfo > getLegacyModulationInfos11b()
ModulationParameter::id_t parameterIdUnknown() const
static std::uint8_t toHTIndex(std::uint8_t index, std::uint8_t streams)
WLANInterface public header.
WLANModulationParameter const & findModulationById(ModulationParameter::id_t id) const
static std::vector< Info > getInfos()
unsigned maxNSS() const
static constexpr unsigned NUM_VHT_INDEX
ModulationParameter::id_t parameterIdAsSGI(ModulationParameter::id_t id) const
static ModulationParameterRegistry & instance()
static WLANModulationParameterRegistry & instance()
ModulationParameter::id_t parameterIdAsLGI(ModulationParameter::id_t id) const
static std::uint8_t toBandwidthIndex(unsigned bandwidth, bool shortGI=false)
ModulationParameter::id_t modulation() const
Get current modulation parameter configuration id.
static unsigned fromBandwidthIndex(std::uint8_t bandwidthIndex)