HardwareWLANInterface.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 
14  // @tho: There must be a better way to decide which mcs/legacy modualtion to provide for either 2.4 or 5.x GHz bands
15 
19 #include "HardwareWLANInterface.hh"
20 
21 // Custom includes
22 #include <linux/filter.h>
23 #include <algorithm>
24 #include <boost/icl/interval_set.hpp>
25 #include <senf/Utils/algorithm.hh>
26 #include <senf/Utils/String.hh>
30 #include <senf/Ext/NetEmu/Log.hh>
31 
32 #define prefix_
33 //-/////////////////////////////////////////////////////////////////////////////////////////////////
34 
35 #define MHZ_TO_KHZ(freq) ((freq) * 1000)
36 
37 #define IGNORE_EXCPETION(expr) \
38  try { \
39  expr \
40  } catch (std::exception &) {};
41 
42 //-/////////////////////////////////////////////////////////////////////////////////////////////////
43 // senf::emu::detail::HardwareWLANInterfaceNet
44 
45 prefix_ senf::emu::detail::HardwareWLANInterfaceNet::HardwareWLANInterfaceNet()
46  : socket (senf::noinit),
47  source (socket),
48  sink (socket),
49  annotatorRx_(true, true), annotatorTx_(false, true),
50  monSocket (senf::noinit),
51  monSource(monSocket),
52  netOutput (monitorDataFilter.output), netInput (annotatorTx_.input)
53 {
54  ppi::connect(source, annotatorRx_.input);
55  ppi::connect(annotatorRx_.output, monitorDataFilter.input_plain);
56  ppi::connect(monSource, monitorDataFilter);
57  ppi::connect(annotatorTx_.output, sink.input);
58 }
59 
60 prefix_ void senf::emu::detail::HardwareWLANInterfaceNet::assignMonitorSocket(ConnectedMMapReadPacketSocketHandle & monSocket_)
61 {
62  monSocket = monSocket_;
63  monSource.handle(monSocket);
64 }
65 
66 prefix_ void senf::emu::detail::HardwareWLANInterfaceNet::assignDataSocket(ConnectedMMapPacketSocketHandle & socket_)
67 {
68  socket = socket_;
69  source.handle(socket);
70  sink.handle(socket);
71 }
72 
73 prefix_ void senf::emu::detail::HardwareWLANInterfaceNet::dataSource(bool on)
74 {
75  if (on) {
76  source.handle(socket);
77  // clean update the source queue, as we have changed the socket
78  source.flush();
79  // flush any pending packets from the filter
80  monitorDataFilter.flushQueues();
81  // flush old rxDropped values
82  source.dropped();
83  } else {
85  }
86 }
87 
88 prefix_ unsigned senf::emu::detail::HardwareWLANInterfaceNet::rcvBuf()
89 {
90  if (socket)
91  return socket.protocol().rcvbuf();
92  return 0;
93 }
94 
95 prefix_ void senf::emu::detail::HardwareWLANInterfaceNet::rcvBuf(unsigned rcvbuf)
96 {
97  if (socket)
98  socket.protocol().rcvbuf(rcvbuf);
99 }
100 
101 prefix_ unsigned senf::emu::detail::HardwareWLANInterfaceNet::sndBuf()
102 {
103  if (socket)
104  return socket.protocol().sndbuf();
105  return 0;
106 }
107 
108 prefix_ void senf::emu::detail::HardwareWLANInterfaceNet::sndBuf(unsigned sndbuf)
109 {
110  if (socket)
111  socket.protocol().sndbuf(sndbuf);
112 }
113 
114 prefix_ void senf::emu::detail::HardwareWLANInterfaceNet::flush()
115 {
116  if (socket)
117  source.flush();
118  if (monSocket)
119  monSource.flush();
120  monitorDataFilter.flushQueues();
121 }
122 
123 prefix_ senf::emu::TSFTHistogram & senf::emu::detail::HardwareWLANInterfaceNet::tsftHistogram()
124 {
125  return monitorDataFilter.tsftHistogram();
126 }
127 
128 
129 //-/////////////////////////////////////////////////////////////////////////////////////////////////
130 // senf::emu::HardwareWLANInterface
131 
132 namespace {
133  struct DisableInterfaceGuard
134  {
135  DisableInterfaceGuard(senf::emu::Interface & iface)
136  : iface_ (iface), enabled_ (iface_.enabled())
137  { if (enabled_) iface_.disable(); }
138 
139  ~DisableInterfaceGuard()
140  { if (enabled_) iface_.enable(); }
141 
142  senf::emu::Interface & iface_;
143  bool enabled_;
144  };
145 }
146 
147 namespace senf { namespace emu {
148  SENF_CONSOLE_REGISTER_ENUM_MEMBER( WirelessNLController, Band_t, (BAND_2GHZ)(BAND_5GHZ) );
149  SENF_CONSOLE_REGISTER_ENUM_MEMBER( HardwareWLANInterface::HTMode, Enum, (Disabled)(Enabled)(HT20only)(HT40only) );
150 }}
151 
152 prefix_ senf::emu::HardwareWLANInterface::HardwareWLANInterface(std::pair<std::string,std::string> interfaces)
153  : WLANInterface(detail::HardwareWLANInterfaceNet::netOutput, detail::HardwareWLANInterfaceNet::netInput),
154  netctl_(interfaces.first), wnlc_(interfaces.first), dev_(interfaces.first), monitorDev_ (interfaces.second), spectralScanner_(wnlc_.phyName()),
155  wifiStatistics_(monitorDevice()), frequencyOffset_(0), restrictedBand_(-1), htMode_(HTMode::Disabled),
156  modId_( WLANModulationParameterRegistry::instance().parameterIdUnknown()), bw_(0), txPower_(0),
157  rcvBufSize_ (1024), sndBufSize_ (96*1024), qlen_ (512), pvid_(VLanId::None), accessMode_(false)
158 {
159  init();
160 }
161 
162 prefix_ void senf::emu::HardwareWLANInterface::init()
163 {
164  if (wnlc_.hasHTCapabilities()) {
165  switch (wnlc_.htCapabilities().channelWidth) {
168  break;
171  break;
172  default:
173  // this forces the monitorDataFilter to disable packet reordering
175  break;
176  }
177  } else {
179  }
180 
181  registerFrequencies();
182  registerModulations();
183  registerTxPowers();
184 
187 
188  namespace fty = console::factory;
189  namespace kw = senf::console::kw;
190  consoleDir()
191  .add("tsftHistogram", HardwareWLANInterfaceNet::monitorDataFilter.tsftHistogram().dir);
192  consoleDir()
193  .add("filterStats", fty::Command( &HardwareWLANInterface::dumpFilterStats, this)
194  .doc("dumps and resets the WLAN Data Filter statistics"));
195  consoleDir()
196  .add("mmapStats", fty::Command( &HardwareWLANInterface::dumpMmapStats, this)
197  .doc("dumps and resets the MMAP RX/TX statistics"));
198  consoleDir()
199  .add("frequencyOffset", fty::Command(
201  .doc("set the frequency offset"));
202  consoleDir()
203  .add("frequencyOffset", fty::Command(
205  .overloadDoc("get the frequency offset"));
206  consoleDir()
207  .add("restrictBand", fty::Command(
209  .arg("band", "'BAND_2GHZ' or 'BAND_5GHZ'")
210  .doc("restrict the registered frequencies to given band") );
211  consoleDir()
212  .add("htMode", fty::Command(
214  .arg("mode", "HT mode")
215  .doc("setting HT mode") );
216  consoleDir()
217  .add("htMode", fty::Command(
219  .overloadDoc("get HT mode setting") );
220  consoleDir()
221  .add("restrictBand", fty::Command(
223  .overloadDoc("clear restriction") );
224  consoleDir()
225  .add("coverageClass", fty::Command(
226  SENF_MEMFNP(unsigned, WirelessNLController, coverageClass, ()), &wnlc_)
227  .doc("get the coverage class"));
228  consoleDir()
229  .add("coverageClass", fty::Command(
230  SENF_MEMFNP(void, WirelessNLController, coverageClass, (unsigned)), &wnlc_)
231  .overloadDoc("set the coverage class"));
232  consoleDir()
233  .add("monitorDevice", fty::Command(
234  SENF_MEMBINDFNP(std::string const &, HardwareWLANInterface, monitorDevice, () const))
235  .overloadDoc("Get monitor device name.\n"
236  "If the device name is empty, data is read from the normal device"
237  "and no monitor information (SNR, Noise, signal level) is available.") );
238  consoleDir()
239  .add("sndBuf", fty::Command(
240  SENF_MEMBINDFNP(void, HardwareWLANInterface, sndBuf, (unsigned)))
241  .doc( "set the send socket buffer size in bytes"));
242  consoleDir()
243  .add("sndBuf", fty::Command(
245  .doc( "get the send socket buffer size in bytes"));
246  consoleDir()
247  .add("rcvBuf", fty::Command(
248  SENF_MEMBINDFNP(void, HardwareWLANInterface, rcvBuf, (unsigned)))
249  .doc( "set the receive socket buffer size in bytes"));
250  consoleDir()
251  .add("rcvBuf", fty::Command(
253  .doc( "get the receive socket buffer size in bytes"));
254  consoleDir()
255  .add("qlen", fty::Command(
256  SENF_MEMBINDFNP(void, HardwareWLANInterface, qlen, (unsigned)))
257  .doc("set mmap read queue length in # of packets"));
258  consoleDir()
259  .add("qlen", fty::Command(
260  SENF_MEMBINDFNP(unsigned, HardwareWLANInterface, qlen, () const))
261  .doc("get mmap read queue length in # of packets"));
262  consoleDir()
263  .add("maxBurst", fty::Command(
264  SENF_MEMBINDFNP(void, HardwareWLANInterface, maxBurst, (unsigned)))
265  .doc("set max. number to frames to be read in a burst."));
266  consoleDir()
267  .add("maxBurst", fty::Command(
268  SENF_MEMBINDFNP(unsigned, HardwareWLANInterface, maxBurst, () const))
269  .doc("set max. number to frames to be read in a burst."));
270  consoleDir()
271  .add("pvid", fty::Command(
272  SENF_MEMBINDFNP(bool, HardwareWLANInterface, pvid, (VLanId const &, bool)))
273  .doc( "enables filtering for a specific PVID (VLAN ID must be 0...4095)"));
274  consoleDir()
275  .add("pvid", fty::Command(
276  SENF_MEMBINDFNP(VLanId const &, HardwareWLANInterface, pvid, () const))
277  .doc( "report the currently configured PVID (-1 means none)"));
278  consoleDir()
279  .add("spectralScanStats", fty::Command(&HardwareWLANInterface::spectralScanStats, this)
280  .doc("current spectralScanner stats."));
281  consoleDir()
282  .add("dumpSurvey", fty::Command(&HardwareWLANInterface::dumpSurvey, this)
283  .doc("current survey stats"));
284  consoleDir()
285  .add("triggerScan", fty::Command(&HardwareWLANInterface::triggerScan, this)
286  .doc("triggers a fresh scan"));
287  consoleDir()
288  .add("getScan", fty::Command(&HardwareWLANInterface::getScan, this)
289  .doc("retrieves latest scan results"));
290  consoleDir()
291  .add("wifiStatistics", fty::Command(&HardwareWLANInterface::dumpWifiStatistics, this)
292  .doc("Dumps current WifiStatistics."));
293 
294  console::provideDirectory(interfaceDir(),"by-device").add(device(), fty::Link(consoleDir()));
295 
296  if (enabled())
297  init_sockets();
298 
299  if (!spectralScanner_.detected()) {
300  SENF_LOG( (WlanLogArea) (senf::log::MESSAGE) ("ath spectral scanner not detected for " << wnlc_.phyName() << ". DebugFS mounted at /sys/kernel/debug ?") );
301  } else {
302  SENF_LOG( (WlanLogArea) (senf::log::MESSAGE) ("ath spectral scanner detected for " << wnlc_.phyName()) );
303  }
304 }
305 
307 {
308  try {
309  console::provideDirectory(interfaceDir(),"by-device").remove(device());
310  } catch (...) {};
311 }
312 
313 prefix_ void senf::emu::HardwareWLANInterface::registerFrequencies()
314 {
315  typedef boost::icl::interval_set<WirelessNLController::frequency_type> FrequencyRanges;
317  FrequencyRanges frequencyRanges;
319  if (restrictedBand_ < 0)
320  nlFreqRange = wnlc_.frequencies();
321  else
322  nlFreqRange = wnlc_.frequencies( WirelessNLController::Band_t(restrictedBand_));
323  // register non-HT frequencies/bandwidth
324  for (WirelessNLController::frequency_type freq : nlFreqRange) {
325  // TODO: (we need to think about this in more detail): filter out channels where the center frequency is smaller than the offset
326  if ((frequencyOffset_ < 0) && (freq < unsigned(abs(frequencyOffset_))))
327  continue;
328  frequencyRanges.insert( FrequencyRange(
329  freq + frequencyOffset_ - MHZ_TO_KHZ(10), freq + frequencyOffset_ + MHZ_TO_KHZ(10)));
330  if (htMode_ != HTMode::HT40only)
331  registerFrequency(freq + frequencyOffset_, MHZ_TO_KHZ(20));
332  }
334  return;
335  if (htMode_ == HTMode::Disabled || htMode_ == HTMode::HT20only)
336  return;
337  // register HT40(+) frequencies/bandwidth
339  if (boost::icl::contains(frequencyRanges, FrequencyRange(
340  freq + frequencyOffset_ - MHZ_TO_KHZ(10), freq + frequencyOffset_ + MHZ_TO_KHZ(30)))) {
341  registerFrequency(freq + frequencyOffset_ + MHZ_TO_KHZ(10), MHZ_TO_KHZ(40));
342  }
343  }
344  if (htMode_ == HTMode::HT40only || !wnlc_.hasVHTCapabilities())
345  return;
346  // register VHT80( frequencies/bandwidth
348  if (boost::icl::contains(frequencyRanges, FrequencyRange(
349  freq + frequencyOffset_ - MHZ_TO_KHZ(50), freq + frequencyOffset_ + MHZ_TO_KHZ(30)))) {
350  registerFrequency(freq + frequencyOffset_ - MHZ_TO_KHZ(10), MHZ_TO_KHZ(80));
351  }
352  }
353 }
354 
355 prefix_ void senf::emu::HardwareWLANInterface::registerVHTModulation(unsigned vhtMcsIndex, unsigned nss, unsigned bw, bool shortGI)
356 {
358  if (WLAN_MCSInfo::getRate(vhtMcsIndex, nss+1, bw, shortGI) > 0)
359  registerModulation(registry.parameterIdByMCS_VHT(vhtMcsIndex, nss+1, bw, shortGI));
360 }
361 
362 prefix_ void senf::emu::HardwareWLANInterface::registerModulations_vht(BitrateParameters::VHT_MCSBitmapTable const & vht_mcs_table)
363 {
364  VHTCapabilitiesInfo const & vhtCapa (wnlc_.vhtCapabilities());
365  for (size_t nss = 0; nss < vht_mcs_table.size(); nss++) {
366  for (size_t index = 0; index < vht_mcs_table[nss].size(); index++) {
367  if (not vht_mcs_table[nss].test(index))
368  continue;
369  for (int bw : {MHZ_TO_KHZ(20), MHZ_TO_KHZ(40)}) {
370  registerVHTModulation(index, nss, bw, false);
371  registerVHTModulation(index, nss, bw, true);
372  }
373  registerVHTModulation(index, nss, MHZ_TO_KHZ(80), false);
374  if (vhtCapa.shortGIfor80MHz)
375  registerVHTModulation(index, nss, MHZ_TO_KHZ(80), true);
376  if (vhtCapa.supportedChannelWidth == VHTCapabilitiesInfo::SupportedChannelWidth_160MHz) {
377  registerVHTModulation(index, nss, MHZ_TO_KHZ(160), false);
378  if (vhtCapa.shortGIfor160_8080MHz)
379  registerVHTModulation(index, nss, MHZ_TO_KHZ(160), true);
380  }
381  }
382  }
383 }
384 
385 prefix_ void senf::emu::HardwareWLANInterface::registerModulations()
386 {
388  // register the two 'special' modulations
390  registerModulation( registry.parameterIdAuto());
391  BitrateParameters const & bitrates (wnlc_.bitrates());
392  if (htMode_ == HTMode::Disabled || htMode_ == HTMode::Enabled) {
393  // register non-HT legacy modulations
394  std::set<BitrateParameters::LegacyBitrate> legacyRates;
395  if (bitrates.legacy_24)
396  legacyRates.insert( bitrates.legacy_24->begin(), bitrates.legacy_24->end());
397  if (bitrates.legacy_5)
398  legacyRates.insert( bitrates.legacy_5->begin(), bitrates.legacy_5->end());
399  for (BitrateParameters::LegacyBitrate legacyRate : legacyRates) {
400  registerModulation( registry.parameterIdByLegacyRate( legacyRate));
401  }
402  }
403  if (htMode_ != HTMode::Disabled) {
404  // register HT MCS modulations
405  HTCapabilitiesInfo const & htCapa (wnlc_.htCapabilities());
406  std::set<BitrateParameters::MCSIndex> mcsIndexes;
407  if (bitrates.mcs_24)
408  mcsIndexes.insert( bitrates.mcs_24->begin(), bitrates.mcs_24->end());
409  if (bitrates.mcs_5)
410  mcsIndexes.insert( bitrates.mcs_5->begin(), bitrates.mcs_5->end());
411  for (BitrateParameters::MCSIndex mcsIndex : mcsIndexes) {
412  if (htMode_ != HTMode::HT40only)
413  registerModulation( registry.parameterIdByMCS_HT( mcsIndex, MHZ_TO_KHZ(20), false));
414  if (! wnlc_.hasHTCapabilities())
415  continue;
416  if (htMode_ != HTMode::HT40only)
417  if (htCapa.rxHT20SGI) // Indicates short GI support for 20 MHz
418  registerModulation( registry.parameterIdByMCS_HT( mcsIndex, MHZ_TO_KHZ(20), true));
419  if (htMode_ == HTMode::HT20only)
420  continue;
421  if (htCapa.channelWidth == HTCapabilitiesInfo::HT20_40) {
422  registerModulation( registry.parameterIdByMCS_HT( mcsIndex, MHZ_TO_KHZ(40), false));
423  if (htCapa.rxHT40SGI) // Indicates short GI support for 40 MHz
424  registerModulation( registry.parameterIdByMCS_HT( mcsIndex, MHZ_TO_KHZ(40), true));
425  }
426  }
427  // register VHT MCS modulations
428  if (wnlc_.hasVHTCapabilities()) {
429  if (bitrates.vht_mcs_table_24)
430  registerModulations_vht(bitrates.vht_mcs_table_24.get());
431  if (bitrates.vht_mcs_table_5)
432  registerModulations_vht(bitrates.vht_mcs_table_5.get());
433  }
434  }
435 }
436 
438 {
441  registerFrequencies();
442  registerModulations();
443 }
444 
445 prefix_ void senf::emu::HardwareWLANInterface::registerTxPowers()
446 {
447  registerTxPower(100, 3000);
448 }
449 
451  const
452 {
453  return dev_;
454 }
455 
457  const
458 {
459  return monitorDev_;
460 }
461 
462 prefix_ void senf::emu::HardwareWLANInterface::init_sockets()
463 {
464  monitorDataFilter.id(id());
465  annotatorRx_.id(id());
466 
468  ctrl.promisc(true);
469  ctrl.up();
470 
471  netctl_.promisc(false);
472  netctl_.down();
473 }
474 
475 prefix_ void senf::emu::HardwareWLANInterface::openMonitorSocket()
476 {
478  monSocket_.protocol().rcvbuf( rcvBufSize_);
480  monitorDataFilter.promisc(netctl_.promisc());
481  monitorDataFilter.flushQueues();
482  assignMonitorSocket(monSocket_);
483 
484  // in monitor mode, we disable the wifi_statistics module
485  wifiStatistics_.enable(false);
486 }
487 
488 prefix_ void senf::emu::HardwareWLANInterface::closeMonitorSocket()
489 {
491 
492  if (HardwareWLANInterfaceNet::monSocket.valid())
493  HardwareWLANInterfaceNet::monSocket.close();
494 
495 
496  // in non-monitor mode, we enable the wifi_statistics module
497  wifiStatistics_.enable(true);
498 }
499 
500 prefix_ void senf::emu::HardwareWLANInterface::openDataSocket()
501 {
502  std::string vlanDevice (device() + "." + senf::str(pvid_));
503 
504  netctl_.up();
505 
506  if (!promisc() and pvid_) {
507  // if there exists a VLAN interface, remove it first
508  try {
509  netctl_.delVLAN(pvid_.id());
510  }
511  catch (...) {
512  }
513  netctl_.addVLAN(pvid_.id());
514  NetdeviceController(vlanDevice).up();
515  }
516 
517  ConnectedMMapPacketSocketHandle socket_ (((promisc() or !pvid_) ? device() : vlanDevice),
518  qlen_, SENF_EMU_MAXMTU);
519 
520  socket_.protocol().rcvbuf( rcvBufSize_);
521  socket_.protocol().sndbuf( sndBufSize_);
522  // socket_.protocol().sndLowat(SENF_EMU_MAXMTU);
523  HardwareWLANInterfaceNet::assignDataSocket(socket_);
524 
525  if (promisc() and pvid_) {
526  if (accessMode_) {
527  annotatorRx_.insertTag(pvid_);
528  annotatorTx_.removeTag(pvid_);
529  } else {
530  annotatorRx_.removeTag(pvid_);
531  annotatorTx_.insertTag(pvid_);
532  }
533  } else {
534  annotatorRx_.clearTag();
535  annotatorTx_.clearTag();
536  }
537 
538  // switch to promisc rx method, which works around possibily misconfigured VLAN offloading
539  annotatorRx_.promisc(promisc());
540 }
541 
543  const
544 {
545  return HardwareWLANInterfaceNet::socket.valid();
546 }
547 
548 prefix_ void senf::emu::HardwareWLANInterface::closeDataSocket()
549 {
550  try {
551  if (!promisc() and pvid_) {
552  netctl_.delVLAN(pvid_.id());
553  }
554  }
555  catch (...) {
556  }
557 
560 
561  if (HardwareWLANInterfaceNet::socket.valid())
562  HardwareWLANInterfaceNet::socket.close();
563 
564  netctl_.down();
565 }
566 
567 prefix_ void senf::emu::HardwareWLANInterface::close_sockets()
568 {
569  closeMonitorSocket();
570  closeDataSocket();
572 }
573 
574 prefix_ void senf::emu::HardwareWLANInterface::v_enable()
575 {
576  if (! enabled()) {
577  init_sockets();
578  }
579 }
580 
581 prefix_ void senf::emu::HardwareWLANInterface::v_disable()
582 {
583  close_sockets();
584 }
585 
586 prefix_ bool senf::emu::HardwareWLANInterface::v_enabled()
587  const
588 {
590 }
591 
592 prefix_ void senf::emu::HardwareWLANInterface::v_id(MACAddress const & id)
593 {
594  DisableInterfaceGuard guard (*this);
596  monitorDataFilter.id(id);
597  annotatorRx_.id(id);
598 }
599 
600 prefix_ senf::MACAddress senf::emu::HardwareWLANInterface::v_id()
601  const
602 {
603  return netctl_.hardwareAddress();
604 }
605 
606 prefix_ bool senf::emu::HardwareWLANInterface::v_promisc()
607  const
608 {
609  return netctl_.promisc();
610 }
611 
612 prefix_ void senf::emu::HardwareWLANInterface::v_promisc(bool p)
613 {
614  if ( netctl_.promisc() == p)
615  return;
616 
617  // NOTE: If a PVID is configured, we need to close/open the socket
618  // Hence, we would loose any join mesh/ibss states.
619 
620  bool dataSocketOpen (HardwareWLANInterfaceNet::socket.valid());
621  if (dataSocketOpen and pvid_) {
622  closeDataSocket();
623  }
624 
625  netctl_.promisc(p);
626  monitorDataFilter.promisc(p);
627 
628  if (dataSocketOpen and pvid_) {
629  openDataSocket();
630  }
631 
632  frequencyHint(0);
633 }
634 
635 prefix_ void senf::emu::HardwareWLANInterface::v_annotationMode(bool a)
636 {
637  if (monitorDataFilter.annotate() == a)
638  return;
639 
640  monitorDataFilter.annotate(a);
641 
642  if (a) {
643  openMonitorSocket();
644  dataSource(false);
645  } else {
646  closeMonitorSocket();
647  dataSource(true);
648  }
649 }
650 
651 prefix_ bool senf::emu::HardwareWLANInterface::v_annotationMode()
652  const
653 {
654  return monitorDataFilter.annotate();
655 }
656 
657 prefix_ void senf::emu::HardwareWLANInterface::v_mcAdd(MACAddress const & address)
658 {
659  HardwareWLANInterfaceNet::socket.protocol().mcAdd( dev_, address);
660 }
661 
662 prefix_ void senf::emu::HardwareWLANInterface::v_mcDrop(MACAddress const & address)
663 {
664  HardwareWLANInterfaceNet::socket.protocol().mcDrop( dev_, address);
665 }
666 
667 prefix_ unsigned senf::emu::HardwareWLANInterface::v_mtu()
668  const
669 {
670  return netctl_.mtu();
671 }
672 
673 prefix_ void senf::emu::HardwareWLANInterface::v_mtu(unsigned v)
674 {
675  netctl_.mtu(v);
677 }
678 
679 prefix_ void senf::emu::HardwareWLANInterface::v_flushRxQueues()
680 {
681  HardwareWLANInterfaceNet::flush();
682 }
683 
684 prefix_ void senf::emu::HardwareWLANInterface::v_flushTxQueues()
685 {
686  HardwareWLANInterfaceNet::sink.flush();
687 }
688 
689 prefix_ bool senf::emu::HardwareWLANInterface::pvid(VLanId const & p, bool accessMode)
690 {
691  if (!accessMode and p.stag())
692  return false;
693 
694  if (pvid_ == p and accessMode_ == accessMode)
695  return true;
696 
697  // NOTE: Here we loose any join mesh/ibss states.
698 
699  bool dataSocketOpen (HardwareWLANInterfaceNet::socket.valid());
700  if (dataSocketOpen) {
701  closeDataSocket();
702  }
703 
704  pvid_ = p;
705  accessMode_ = accessMode;
706 
707  if (dataSocketOpen) {
708  openDataSocket();
709  }
710 
711  return true;
712 }
713 
715 {
716  return HardwareWLANInterfaceNet::annotatorRx_.vlanMismatch();
717 }
718 
720 {
721  return HardwareWLANInterfaceNet::annotatorTx_.vlanMismatch();
722 }
723 
724 prefix_ senf::emu::ModulationParameter::id_t senf::emu::HardwareWLANInterface::v_modulationId()
725  const
726 {
727  return modId_;
728 }
729 
730 prefix_ unsigned senf::emu::HardwareWLANInterface::v_bandwidth()
731  const
732 {
733  return bw_;
734 }
735 
736 prefix_ void senf::emu::HardwareWLANInterface::v_modulationId(ModulationParameter::id_t id)
737 {
738  WLANModulationParameter const & modPara (WLANModulationParameterRegistry::instance().findModulationById(id));
739  BitrateParameters bratePara;
740 
741  if ((wnlc_.supportedBands().size() == 1) or (wnlc_.frequency() <= 3000000)) {
742  if (senf::contains(wnlc_.supportedBands(), WirelessNLController::BAND_2GHZ)) {
743  switch (modPara.type) {
747  // fall through
749  bratePara.mcs_24.reset(BitrateParameters::MCSIndexSet());
750  // fall through
755  break;
756  }
757  if (modPara.type == WLANModulationParameter::Legacy) {
758  bratePara.legacy_24->insert(modPara.rate);
759  }
760  if (modPara.type == WLANModulationParameter::HT) {
761  bratePara.mcs_24->insert(modPara.index);
762  }
763  if (modPara.type == WLANModulationParameter::VHT) {
764  // ath10k requires bits 0...7 to be set. Also there can not be gaps.
765  for (unsigned n = 1; n <= std::max(8u,modPara.index); n++)
766  bratePara.vht_mcs_table_24->at(modPara.streams-1).set(n-1);
767  bratePara.vht_mcs_table_24->at(modPara.streams-1).set(modPara.index);
768  }
769  }
770  }
771  if ((wnlc_.supportedBands().size() == 1) or (wnlc_.frequency() >= 4900000)) {
772  if (senf::contains(wnlc_.supportedBands(), WirelessNLController::BAND_5GHZ)) {
773  switch (modPara.type) {
777  // fall through
779  bratePara.mcs_5.reset(BitrateParameters::MCSIndexSet());
780  // fall through
785  break;
786  }
787  if (modPara.type == WLANModulationParameter::Legacy) {
788  bratePara.legacy_5->insert(modPara.rate);
789  }
790  if (modPara.type == WLANModulationParameter::HT) {
791  bratePara.mcs_5->insert(modPara.index);
792  }
793  if (modPara.type == WLANModulationParameter::VHT) {
794  // ath10k requires bits 0...7 to be set. Also there can not be gaps.
795  for (unsigned n = 1; n <= std::max(8u,modPara.index); n++)
796  bratePara.vht_mcs_table_5->at(modPara.streams-1).set(n-1);
797  bratePara.vht_mcs_table_5->at(modPara.streams-1).set(modPara.index);
798  }
799  }
800  }
801 
802  wnlc_.set_bitrates(bratePara);
803  modId_ = modPara.id;
804 
805 #undef insertParameterIfTypeMatch
806 }
807 
808 prefix_ void senf::emu::HardwareWLANInterface::modulationSet(std::set<ModulationParameter::id_t> const & ids)
809 {
810  BitrateParameters bratePara;
811  std::set<WLANModulationParameter::Type> types;
812 
813  if (!ids.empty()) {
814  try {
815  for (auto const & id : ids)
816  types.emplace(WLANModulationParameterRegistry::instance().findModulationById(id).type);
817  }
818  catch(std::exception & e) {
819  throw InvalidArgumentException("Unknown WLANModulationParameter") << e.what();
820  }
821  if (types.size() != 1) {
822  throw InvalidArgumentException("WLANModulationParameter mismatch");
823  }
824 
825  if ((wnlc_.supportedBands().size() == 1) or (wnlc_.frequency() <= 3000000)) {
826  if (senf::contains(wnlc_.supportedBands(), WirelessNLController::BAND_2GHZ)) {
827  switch (*types.begin()) {
831  // fall through
833  bratePara.mcs_24.reset(BitrateParameters::MCSIndexSet());
834  // fall through
836  if (*types.begin() != WLANModulationParameter::HT and *types.begin() != WLANModulationParameter::VHT)
839  break;
840  }
841  if (*types.begin() == WLANModulationParameter::Legacy) {
842  for (auto const & id : ids) {
843  WLANModulationParameter const & modPara (WLANModulationParameterRegistry::instance().findModulationById(id));
844  bratePara.legacy_24->insert(modPara.rate);
845  // ath5k (at least the XR7) requires 1M to be set ?!?
846  bratePara.legacy_24->insert(1000);
847  }
848  }
849  if (*types.begin() == WLANModulationParameter::HT) {
850  for (auto const & id : ids) {
851  WLANModulationParameter const & modPara (WLANModulationParameterRegistry::instance().findModulationById(id));
852  bratePara.mcs_24->insert(modPara.index);
853  }
854  }
855  if (*types.begin() == WLANModulationParameter::VHT) {
856  // ath10k requires bits 0...7 to be set. Also there can not be gaps.
857  std::map<unsigned,unsigned> maxMCS;
858  for (auto const & id : ids) {
859  WLANModulationParameter const & modPara (WLANModulationParameterRegistry::instance().findModulationById(id));
860  maxMCS[modPara.streams-1] = std::max(7u, std::max(maxMCS[modPara.streams-1], modPara.index));
861  }
862  for (unsigned nss = 0; nss < NL80211_VHT_NSS_MAX; nss++) {
863  for (unsigned n = 0; n <= maxMCS[nss]; n++)
864  bratePara.vht_mcs_table_24->at(nss).set(n);
865  }
866  }
867  }
868  }
869  if ((wnlc_.supportedBands().size() == 1) or (wnlc_.frequency() >= 4900000)) {
870  if (senf::contains(wnlc_.supportedBands(), WirelessNLController::BAND_5GHZ)) {
871  switch (*types.begin()) {
875  // fall through
877  bratePara.mcs_5.reset(BitrateParameters::MCSIndexSet());
878  // fall through
880  if (*types.begin() != WLANModulationParameter::HT and *types.begin() != WLANModulationParameter::VHT)
883  break;
884  }
885  if (*types.begin() == WLANModulationParameter::Legacy) {
886  for (auto const & id : ids) {
887  WLANModulationParameter const & modPara (WLANModulationParameterRegistry::instance().findModulationById(id));
888  bratePara.legacy_5->insert(modPara.rate);
889  }
890  }
891  if (*types.begin() == WLANModulationParameter::HT) {
892  for (auto const & id : ids) {
893  WLANModulationParameter const & modPara (WLANModulationParameterRegistry::instance().findModulationById(id));
894  bratePara.mcs_5->insert(modPara.index);
895  }
896  }
897  if (*types.begin() == WLANModulationParameter::VHT) {
898  // ath10k requires bits 0...7 to be set. Also there can not be gaps.
899  std::map<unsigned,unsigned> maxMCS;
900  for (auto const & id : ids) {
901  WLANModulationParameter const & modPara (WLANModulationParameterRegistry::instance().findModulationById(id));
902  maxMCS[modPara.streams-1] = std::max(8u, std::max(maxMCS[modPara.streams-1], modPara.index+1));
903  }
904  for (unsigned nss = 0; nss < NL80211_VHT_NSS_MAX; nss++) {
905  if (maxMCS[nss] > 0) {
906  for (unsigned n = 1; n <= maxMCS[nss]; n++)
907  bratePara.vht_mcs_table_5->at(nss).set(n-1);
908  }
909  }
910  }
911  }
912  }
913  }
914 
915  wnlc_.set_bitrates(bratePara);
916 
917  // report the upper bound (our target rate, the other(s) are considered as fallbacks)
918  if (!ids.empty()) {
919  std::map<unsigned, ModulationParameter::id_t> rates;
920  for (auto const & i : ids) {
921  rates.insert(std::make_pair(WLANModulationParameterRegistry::instance().findModulationById(i).rate, i));
922  }
923  modId_ = rates.rbegin()->second;
924  } else {
926  }
927 
928 #undef insertParameterIfTypeMatch
929 }
930 
931 prefix_ void senf::emu::HardwareWLANInterface::v_frequency(unsigned freq, unsigned bandwidth)
932 {
934 
935  if (freq != 0 && bandwidth != 0) {
936  switch (bandwidth) {
937  case MHZ_TO_KHZ(20):
938  wnlc.set_frequency( freq-frequencyOffset_,
940  bw_ = MHZ_TO_KHZ(20);
941  break;
942  case MHZ_TO_KHZ(40):
944  bw_ = MHZ_TO_KHZ(40);
945  break;
946  case MHZ_TO_KHZ(80):
948  bw_ = MHZ_TO_KHZ(80);
949  break;
950  default:
951  throw InvalidArgumentException("invalid bandwidth: ") << bandwidth;
952  break;
953  }
954  }
955 
956  frequencyHint(bw_);
957 
958  // drop all old frames from the kernel queues
959  flushRxQueues();
960 }
961 
962 prefix_ unsigned senf::emu::HardwareWLANInterface::v_frequency()
963  const
964 {
965  switch (bw_) {
966  case MHZ_TO_KHZ(20):
967  return wnlc_.frequency() + frequencyOffset_;
968  case MHZ_TO_KHZ(40):
969  return wnlc_.frequency() + frequencyOffset_ + MHZ_TO_KHZ(10);
970  case MHZ_TO_KHZ(80):
971  return wnlc_.frequency() + frequencyOffset_ + MHZ_TO_KHZ(30);
972  }
973  return 0;
974 }
975 
976 prefix_ int senf::emu::HardwareWLANInterface::v_txPower()
977  const
978 {
979  return txPower_;
980 }
981 
982 prefix_ void senf::emu::HardwareWLANInterface::v_txPower(int power)
983 {
984  // rounding it to a dB value (ath10k seems to require this)
985  power /= 100;
986  power *= 100;
987 
988  if (power == txPower_)
989  return;
990 
991  try {
993  } catch (NetlinkException & ex) {
994  throw;
995  }
996  txPower_ = power;
997 }
998 
1000 {
1001  return HardwareWLANInterfaceNet::monitorDataFilter.stats();
1002 }
1003 
1005 {
1006  HardwareWLANInterfaceNet::monitorDataFilter.dropUnknownMCS(q);
1007 }
1008 
1010 {
1011  HardwareWLANInterfaceNet::monitorDataFilter.stats().dump(os);
1012  HardwareWLANInterfaceNet::monitorDataFilter.dumpState(os);
1013 }
1014 
1016 {
1017  if (!HardwareWLANInterfaceNet::socket and !HardwareWLANInterfaceNet::monSocket) {
1018  os << "Socket closed. No stats available." << std::endl;
1019  return;
1020  }
1021 
1022  if (HardwareWLANInterfaceNet::monSocket) {
1023  auto rs (HardwareWLANInterfaceNet::monSocket.protocol().rxStats());
1024  os << "MMAP Rx (monitor, fd=" << monSocket.protocol().fd() << ", avail " << socket.protocol().available() << ") stats: "; rs.dump(os);
1025  } else {
1026  auto rs (HardwareWLANInterfaceNet::socket.protocol().rxStats());
1027  os << "MMAP Rx (data, fd=" << socket.protocol().fd() << ", avail " << socket.protocol().available() << ") stats: "; rs.dump(os);
1028  }
1029  if (HardwareWLANInterfaceNet::socket) {
1030  auto ts (HardwareWLANInterfaceNet::socket.protocol().txStats());
1031  os << "MMAP Tx (data, fd=" << socket.protocol().fd() << ") stats: "; ts.dump(os);
1032  }
1033 
1034  os << std::endl;
1035 }
1036 
1038  const
1039 {
1040  if (HardwareWLANInterfaceNet::socket)
1041  return socket.protocol().interfaceDead();
1042  return false; // do not call us if the iface is not active
1043 }
1044 
1046 {
1047  if (offset == frequencyOffset_)
1048  return;
1049  frequencyOffset_ = offset;
1051  registerFrequencies();
1052 }
1053 
1055 {
1056  restrictedBand_ = band;
1058  registerFrequencies();
1059 }
1060 
1062 {
1063  restrictedBand_ = -1;
1065  registerFrequencies();
1066 }
1067 
1069  const
1070 {
1071  return htMode_;
1072 }
1073 
1075 {
1076  if (mode != HTMode::Disabled && !wnlc_.hasHTCapabilities())
1077  throw InvalidArgumentException("HT mode not supported by this interface");
1078 
1079  if (htMode_ == mode)
1080  return;
1081 
1082  htMode_ = mode;
1085  registerFrequencies();
1086  registerModulations();
1087 }
1088 
1089 prefix_ void senf::emu::HardwareWLANInterface::v_coverageRange(unsigned distance)
1090 {
1092 }
1093 
1094 prefix_ senf::emu::WirelessNLController::IbssJoinParameters::ptrI
1096  unsigned int freq, unsigned int bandwidth, bool & success)
1097 {
1098  if (! enabled())
1099  throw senf::SystemException(
1100  "joinAdhoc (" + ssid + ") failed: Interface (" + device() + ") is down ", ENETDOWN);
1101 
1103  switch (bandwidth) {
1104  case MHZ_TO_KHZ(20):
1105  channelMode = (htMode_ == HTMode::Disabled
1108  break;
1109  case MHZ_TO_KHZ(40):
1111  freq -= MHZ_TO_KHZ(10);
1112  break;
1113  case MHZ_TO_KHZ(80):
1115  freq -= MHZ_TO_KHZ(30);
1116  break;
1117  default:
1118  throw InvalidArgumentException("invalid bandwidth: ") << bandwidth;
1119  }
1120 
1121  return WirelessNLController::IbssJoinParameters::ptrI(new WirelessNLController::IbssJoinParameters(
1122  membind(&HardwareWLANInterface::do_ibss_join, this),
1123  ssid, freq-frequencyOffset_, channelMode, success) );
1124 }
1125 
1126 prefix_ senf::emu::WirelessNLController::MeshJoinParameters::ptrM
1128  unsigned int freq, unsigned int bandwidth, bool & success)
1129 {
1130  if (! enabled())
1131  throw senf::SystemException(
1132  "joinMesh (" + meshId + ") failed: Interface (" + device() + ") is down ", ENETDOWN);
1133 
1135  switch (bandwidth) {
1136  case MHZ_TO_KHZ(20):
1137  channelMode = (htMode_ == HTMode::Disabled
1140  break;
1141  case MHZ_TO_KHZ(40):
1143  freq -= MHZ_TO_KHZ(10);
1144  break;
1145  case MHZ_TO_KHZ(80):
1147  freq -= MHZ_TO_KHZ(30);
1148  break;
1149  default:
1150  throw InvalidArgumentException("invalid bandwidth: ") << bandwidth;
1151  }
1152 
1153  return WirelessNLController::MeshJoinParameters::ptrM(new WirelessNLController::MeshJoinParameters(
1154  membind(&HardwareWLANInterface::do_mesh_join, this),
1155  meshId, freq-frequencyOffset_, channelMode, success) );
1156 }
1157 
1159 {
1160  if (bandwidth == 0) {
1161  closeDataSocket();
1162  } else {
1163  if (bandwidth != 20000 and bandwidth != 40000 and bandwidth != 80000) {
1164  throw InvalidArgumentException("invalid bandwidth: ") << bandwidth;
1165  }
1166  openDataSocket();
1167  bw_ = bandwidth;
1168  frequencyHint(bw_);
1169  }
1170 }
1171 
1172 prefix_ void senf::emu::HardwareWLANInterface::do_mesh_join(WirelessNLController::JoinParameters const & parameters)
1173 {
1174  openDataSocket();
1175 
1176  wnlc_.do_mesh_join(parameters);
1177 
1178  switch (parameters.channelMode_) {
1180  bw_ = MHZ_TO_KHZ(40);
1181  break;
1184  bw_ = MHZ_TO_KHZ(20);
1185  break;
1187  bw_ = MHZ_TO_KHZ(80);
1188  break;
1189  default:
1190  throw InvalidArgumentException("invalid channelMode: ") << parameters.channelMode_;
1191  break;
1192  }
1193 
1194  frequencyHint(bw_);
1195 }
1196 
1197 prefix_ void senf::emu::HardwareWLANInterface::do_ibss_join(WirelessNLController::JoinParameters const & parameters)
1198 {
1199  openDataSocket();
1200 
1201  wnlc_.do_ibss_join(parameters);
1202 
1203  switch (parameters.channelMode_) {
1205  bw_ = MHZ_TO_KHZ(40);
1206  break;
1209  bw_ = MHZ_TO_KHZ(20);
1210  break;
1212  bw_ = MHZ_TO_KHZ(80);
1213  break;
1214  default:
1215  throw InvalidArgumentException("invalid channelMode: ") << parameters.channelMode_;
1216  break;
1217  }
1218 
1219  frequencyHint(bw_);
1220 }
1221 
1223 {
1224  try {
1225  wnlc_.mesh_leave();
1226  }
1227  catch (...) {};
1228 
1229  try {
1230  wnlc_.ibss_leave();
1231  } catch (...) {};
1232 
1233  closeDataSocket();
1234 }
1235 
1237 {
1238  // need to cache sndBufSize_ so we can (re-)apply the value in v_enable()
1239  sndBufSize_ = std::max(sndbuf, 2048u);
1240  HardwareWLANInterfaceNet::sndBuf( sndBufSize_);
1241 }
1242 
1244 {
1245  // need to cache sndBufSize_ so we can (re-)apply the value in v_enable()
1246  return sndBufSize_ = HardwareWLANInterfaceNet::sndBuf();
1247 }
1248 
1250 {
1251  // need to cache rcvBufSize_ so we can (re-)apply the value in v_enable()
1252  rcvBufSize_ = std::max(rcvbuf, 4096u);
1253  HardwareWLANInterfaceNet::rcvBuf( rcvBufSize_);
1254 }
1255 
1257 {
1258  // need to cache rcvBufSize_ so we can (re-)apply the value in v_enable()
1259  return rcvBufSize_ = HardwareWLANInterfaceNet::rcvBuf();
1260 }
1261 
1263  const
1264 {
1265  return qlen_;
1266 }
1267 
1269 {
1270  if (qlen == qlen_)
1271  return;
1272  qlen_ = qlen;
1273  if (enabled()) {
1274  close_sockets();
1275  init_sockets();
1276  }
1277 }
1278 
1280 {
1281  if (HardwareWLANInterfaceNet::monSocket) {
1282  return monSource.dropped();
1283  }
1284 
1285  return source.dropped();
1286 }
1287 
1288 prefix_ std::tuple<unsigned,unsigned,unsigned> senf::emu::HardwareWLANInterface::txDropped()
1289 {
1290  return sink.dropped();
1291 }
1292 
1294  const
1295 {
1296  return source.maxBurst();
1297 }
1298 
1300 {
1301  source.maxBurst(maxBurst);
1302 }
1303 
1305 {
1306  unsigned freq (wnlc_.frequency() / 1000);
1307  spectralScanner_.frequency(freq, bandwidth / 1000, frequencyOffset() / 1000);
1308  monitorDataFilter.frequency(freq);
1309 }
1310 
1312 {
1313  monitorDataFilter.airTime(a);
1314 }
1315 
1317 {
1318  spectralScanner_.callback(cb);
1319 }
1320 
1322 {
1323  spectralScanner_.disable();
1324 }
1325 
1327 {
1328  spectralScanner_.stats(os);
1329 }
1330 
1332 {
1333  return wifiStatistics_.statisticsMap(tag, maxAge);
1334 }
1335 
1337 {
1338  os << "=== Current (cached since last read) WifiStatsitics map, #" << wifiStatistics_.map().size() << " ===" << std::endl;
1339  for (auto const & m: wifiStatistics_.map()) {
1340  os << m.first << " ==> pkts " << m.second.total << ", lastSeen " << senf::ClockService::in_seconds(m.second.lastSeen) << "s"
1341  << ", signal " << m.second.signal << ", type " << (unsigned) m.second.type << std::endl;
1342  }
1343 }
1344 
1345 
1346 prefix_ std::pair<senf::emu::WirelessNLController::DFSState::Enum,std::uint32_t> senf::emu::HardwareWLANInterface::dfsState(unsigned freq, unsigned bandwidth)
1347 {
1348  if (freq == 0 or bandwidth == 0)
1349  return std::make_pair(WirelessNLController::DFSState::NoDFS, 0);
1350 
1351  if (bandwidth == MHZ_TO_KHZ(20))
1352  return wnlc_.dfsState(freq - frequencyOffset_);
1353 
1354  if (bandwidth == MHZ_TO_KHZ(40)) {
1355  /* | noDFS | usable | available | unavailable
1356  * noDFS | noDFS | usable | available | unavailable
1357  * usable | | usable | usable | unavailable
1358  * available | | | available | unavailable
1359  * unavailable | | | | unavailable
1360  */
1361  auto state1 (wnlc_.dfsState(freq - frequencyOffset_ - MHZ_TO_KHZ(10)));
1362  auto state2 (wnlc_.dfsState(freq - frequencyOffset_ + MHZ_TO_KHZ(10)));
1363  if (state1.first == WirelessNLController::DFSState::NoDFS and state2.first == WirelessNLController::DFSState::NoDFS)
1364  return std::make_pair(WirelessNLController::DFSState::NoDFS, 0);
1366  return std::make_pair(WirelessNLController::DFSState::Unavailable, std::min(state1.second, state2.second));
1368  return std::make_pair(WirelessNLController::DFSState::Usable, std::min(state1.second, state2.second));
1369  return std::make_pair(WirelessNLController::DFSState::Available, std::min(state1.second, state2.second));
1370  }
1371 
1372  if (bandwidth == MHZ_TO_KHZ(80)) {
1373  /* | noDFS | usable | available | unavailable
1374  * noDFS | noDFS | usable | available | unavailable
1375  * usable | | usable | usable | unavailable
1376  * available | | | available | unavailable
1377  * unavailable | | | | unavailable
1378  */
1379  auto state1 (wnlc_.dfsState(freq - frequencyOffset_ - MHZ_TO_KHZ(30)));
1380  auto state2 (wnlc_.dfsState(freq - frequencyOffset_ - MHZ_TO_KHZ(10)));
1381  auto state3 (wnlc_.dfsState(freq - frequencyOffset_ + MHZ_TO_KHZ(10)));
1382  auto state4 (wnlc_.dfsState(freq - frequencyOffset_ + MHZ_TO_KHZ(30)));
1383 
1384  if (state1.first == WirelessNLController::DFSState::NoDFS and
1385  state2.first == WirelessNLController::DFSState::NoDFS and
1386  state3.first == WirelessNLController::DFSState::NoDFS and
1387  state4.first == WirelessNLController::DFSState::NoDFS)
1388  return std::make_pair(WirelessNLController::DFSState::NoDFS, 0);
1389 
1390  if (state1.first == WirelessNLController::DFSState::Unavailable or
1394  return std::make_pair(WirelessNLController::DFSState::Unavailable, std::min({state1.second, state2.second, state3.second, state4.second}));
1395 
1396  if (state1.first == WirelessNLController::DFSState::Usable or
1397  state2.first == WirelessNLController::DFSState::Usable or
1398  state3.first == WirelessNLController::DFSState::Usable or
1400  return std::make_pair(WirelessNLController::DFSState::Usable, std::min({state1.second, state2.second, state3.second, state4.second}));
1401 
1402  return std::make_pair(WirelessNLController::DFSState::Available, std::min({state1.second, state2.second, state3.second, state4.second}));
1403  }
1404 
1405  throw InvalidArgumentException("invalid bandwidth: ") << bandwidth;
1406 }
1407 
1409 {
1410  if (! enabled())
1411  throw senf::SystemException(
1412  "startCAC() failed: Interface (" + device() + ") is down ", ENETDOWN);
1413 
1415  switch (bandwidth) {
1416  case MHZ_TO_KHZ(20):
1417  channelMode = (htMode_ == HTMode::Disabled
1420  break;
1421  case MHZ_TO_KHZ(40):
1423  freq -= MHZ_TO_KHZ(10);
1424  break;
1425  case MHZ_TO_KHZ(80):
1427  freq -= MHZ_TO_KHZ(30);
1428  break;
1429  default:
1430  throw InvalidArgumentException("invalid bandwidth: ") << bandwidth;
1431  }
1432 
1433  // reset device (CAC)
1434  netctl_.down();
1435  netctl_.up();
1436 
1437  wnlc_.start_radarDetection(freq-frequencyOffset_, channelMode);
1438 }
1439 
1441 {
1442  try {
1443  netctl_.down();
1444  } catch (...) {};
1445 }
1446 
1448 {
1449  return wnlc_.radarEvent;
1450 }
1451 
1453 {
1454  return wnlc_.scanEvent;
1455 }
1456 
1458 {
1459  return wnlc_;
1460 }
1461 
1463 {
1464  os << "Lastest survey data, sorted by frequency" << std::endl;
1465 
1466  for( auto const & survey : wnlc_.survey()) {
1467  os << survey.frequency << ": inUse " << survey.inUse << ", noise " << unsigned(survey.noise) << ", channelTime " << survey.channelTime
1468  << ", channelTimeBusy " << survey.channelTimeBusy << ", channelTimeExtBusy " << survey.channelTimeExtBusy
1469  << ", channelTimeRx " << survey.channelTimeRx << ", channelTimeTx " << survey.channelTimeTx << std::endl;
1470  }
1471 }
1472 
1473 prefix_ void senf::emu::HardwareWLANInterface::triggerScan(std::ostream & os, std::set<WirelessNLController::frequency_type> const & frequencies)
1474 {
1475  os << "Triggering new scan on frequencies " << (frequencies.empty() ? "all" : "(" + senf::stringJoin(frequencies, " ") + ")") << std::endl;
1476  wnlc_.do_trigger_scan(frequencies);
1477 }
1478 
1480 {
1481  os << "Lastest scan data, sorted by bssId" << std::endl;
1482 
1483  for (auto const & sd : wnlc_.getScan()){
1484  os << sd.bssId << ": tsf " << sd.tsf << ", frequency " << sd.frequency << ", signal " << sd.signal
1485  << ", beaconIELength " << sd.beaconInformationElementsLength << ", IELength " << sd.informationElementsLength << std::endl;
1486  }
1487 }
1488 
1489 
1490 #undef MHZ_TO_KHZ
1491 #undef IGNORE_EXCPETION
1492 
1493 //-/////////////////////////////////////////////////////////////////////////////////////////////////
1494 #undef prefix_
1495 
1496 
1497 // Local Variables:
1498 // mode: c++
1499 // fill-column: 100
1500 // comment-column: 40
1501 // c-file-style: "senf"
1502 // indent-tabs-mode: nil
1503 // ispell-local-dictionary: "american"
1504 // compile-command: "scons -u test"
1505 // End:
bool promisc() const
Get interface promiscuous status.
WirelessNLController::MeshJoinParameters::ptrM joinMesh(std::string const &meshId, unsigned int freq, unsigned int bandwidth, bool &success)
config::time_type clock_type
#define SENF_EMU_MAXMTU
Definition: config.hh:40
Interface API base class
std::pair< senf::emu::WirelessNLController::DFSState::Enum, std::uint32_t > dfsState(unsigned freq, unsigned bw)
senf::emu::WirelessNLController::NetlinkEvent< ScanEvent > & scanEvent()
VLanId const & pvid() const
#define MHZ_TO_KHZ(freq)
#define SENF_MEMBINDFNP(ret, cls, fn, args)
void addVLAN(std::uint16_t vlanId)
unsigned index() const
Get interface index.
void startCAC(unsigned int freq, unsigned int bandwidth)
static unsigned getRate(std::uint8_t mcsIndex, unsigned bandwidth, bool shortGI)
ModulationParameter::id_t parameterIdByMCS_HT(unsigned htMcsIndex, unsigned bandwidth, bool shortGI) const
void set_bitrates(BitrateParameters parameters)
ModulationParameter::id_t parameterIdAuto() const
bool enabled() const
true, if interface enabled
std::tuple< unsigned, unsigned, unsigned > txDropped()
ModulationParameter::id_t parameterIdByLegacyRate(unsigned rate) const
u8 type
#define SENF_MEMFNP(ret, cls, fn, args)
void flushRxQueues()
Flush Rx Queues.
void registerFrequency(unsigned frequency, unsigned bandwidth)
register single frequency/bandwidth combination
static unsigned distanceToCoverageClass(unsigned distance)
std::set< Band_t > const & supportedBands()
std::string const & monitorDevice() const
Get current monitor interface.
void do_trigger_scan(std::set< frequency_type > const &frequencies, std::set< std::string > const &ssids={})
WifiStatisticsMap const & statisticsMap(std::uint32_t tag, senf::ClockService::clock_type const &maxAge)
boost::function< R(Args)> membind(R(T::*fn)(Args), T *ob)
boost::optional< MCSIndexSet > mcs_24
std::string const & v_device() const override
Get name of physical device.
char ssid[36]
bool enable(bool on=true)
Annotations public header.
std::int32_t min
noinit
__u8 band
Definition: nl80211-new.h:128
std::set< LegacyBitrate > LegacyBitrateSet
std::int32_t max
bool callback(AthSpectralScanCallback const &cb)
MonitorDataFilterStatistics filterStats()
std::pair< DFSState::Enum, std::uint32_t > dfsState(frequency_type freq)
BitrateParameters const & bitrates()
Return valid bitrates.
boost::optional< LegacyBitrateSet > legacy_5
void clearRegisteredModulations()
remove all registered modulations
std::array< VHT_MCSBitmap, NL80211_VHT_NSS_MAX > VHT_MCSBitmapTable
NetlinkEvent< ScanEvent > scanEvent
boost::optional< VHT_MCSBitmapTable > vht_mcs_table_24
unsigned rate
Bitrate in kbit/s.
ModulationParameter::id_t parameterIdByMCS_VHT(unsigned vhtMcsIndex, unsigned streams, unsigned bandwidth, bool shortGI) const
console::DirectoryNode & consoleDir() const
Access interface console directory.
bool stag() const
std::string const & device() const
std::multiset< ScanResults > const & getScan()
NodeType & add(std::string const &name, boost::shared_ptr< NodeType > node)
WifiStatisticsMap const & map() const
NetlinkEvent< RadarEvent > radarEvent
void set_txpower(TxPowerSetting::Enum setting, unsigned int mBm)
std::function< void(std::uint64_t tsft, std::uint16_t frequency, unsigned numBins, void *spectralSample)> AthSpectralScanCallback
#define prefix_
WirelessNLController & wirelessNLController()
boost::optional< MCSIndexSet > mcs_5
WirelessNLController::IbssJoinParameters::ptrI joinAdhoc(std::string const &ssid, unsigned int freq, unsigned int bandwidth, bool &success)
VHTCapabilitiesInfo const & vhtCapabilities()
void triggerScan(std::ostream &os, std::set< WirelessNLController::frequency_type > const &frequencies)
ModulationParameter::id_t parameterIdUnknown() const
std::pair< unsigned, unsigned > rxDropped()
boost::unordered_map< senf::MACAddress, WifiStatisticsData > WifiStatisticsMap
ProtocolClientSocketHandle< ConnectedMMapPacketSocketProtocol< QueueReadPolicy > > ConnectedMMapReadPacketSocketHandle
boost::optional< VHT_MCSBitmapTable > vht_mcs_table_5
MACAddress hardwareAddress() const
void delVLAN(std::uint16_t vlanId)
senf::emu::WirelessNLController::NetlinkEvent< RadarEvent > & radarEvent()
unsigned bandwidth() const
Get current bandwidth.
console::DirectoryNode & interfaceDir()
HTCapabilitiesInfo const & htCapabilities()
ProtocolClientSocketHandle< ConnectedMMapPacketSocketProtocol< QueueReadPolicy, QueueWritePolicy > > ConnectedMMapPacketSocketHandle
static WLANModulationParameterRegistry & instance()
std::set< Survey > const & survey()
void frequency(std::uint32_t freq, std::uint32_t bandwidth, std::int32_t offset=0)
WifiStatisticsMap const & statisticsMap(std::uint32_t tag, senf::ClockService::clock_type const &maxAge)
void set_frequency(frequency_type freq, ChannelMode::Enum=ChannelMode::NoHT20)
SENF_CONSOLE_REGISTER_ENUM_MEMBER(HardwareWLANInterface::HTMode, Enum,(Disabled)(Enabled)(HT20only)(HT40only))
MonitorDataFilterStatistics stats()
static void filterMonitorTxFrames(BSDSocket sock)
static SENF_CLOCKSERVICE_CONSTEXPR int64_type in_seconds(clock_type const &v)
void start_radarDetection(unsigned int freq, ChannelMode::Enum=ChannelMode::NoHT20)
std::string const & phyName() const
Log public header.
HardwareWLANInterface(std::pair< std::string, std::string > interfaces)
void modulationSet(std::set< ModulationParameter::id_t > const &ids={})
#define SENF_LOG(args)
boost::optional< LegacyBitrateSet > legacy_24
void clearRegisteredFrequencies()
remove all registered frequencies
FrequenciesRange frequencies() const
Get valid frequency intervals.
HardwareWLANInterface public header.
void stats(std::ostream &os)
void registerModulation(ModulationParameter::id_t id)
register modulation configuration
__be16 freq
boost::iterator_range< Frequencies_iterator > FrequencyRange
#define NL80211_VHT_NSS_MAX
Definition: nl80211-new.h:3808