WirelessNLController.hh
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 #ifndef HH_SENF_Ext_NetEmu_WLAN_WirelessNLController_
18 #define HH_SENF_Ext_NetEmu_WLAN_WirelessNLController_ 1
19 
20 // Custom includes
21 #include <array>
22 #include <boost/enable_shared_from_this.hpp>
23 #include <boost/shared_ptr.hpp>
24 #include <boost/signals2.hpp>
25 #include <boost/optional.hpp>
28 #include <senf/Utils/Logger/Log.hh>
29 
30 extern "C" {
31 #include "nl80211-new.h"
32 #include "ieee80211.h"
33 }
34 
35 #include "Regulatory.hh"
36 
37 //#include "WirelessNLController.ih"
38 //-/////////////////////////////////////////////////////////////////////////////////////////////////
39 
40 // forward declarations:
41 struct nl_msg;
42 struct nl_cb;
43 struct nlattr;
44 struct nl_sock;
45 struct nl_cache;
46 struct genl_family;
47 
48 
49 namespace senf {
50 namespace emu {
51 
52  class HardwareWLANInterface;
53  class WirelessNLController;
54 
55 
57  {
58  // Indicates support for receiving LDPC coded packets
59  bool rxLDPC;
60  // Supported Channel Width
61  enum ChannelWidth { HT20, HT20_40=2 };
63  // spatial multiplexing power save mode
66  // Indicates support for the reception of PPDUs with HT-greenfield format
68  // Indicates short GI support for 20 MHz
69  bool rxHT20SGI;
70  // Indicates short GI support for 40 MHz
71  bool rxHT40SGI;
72  // Indicates support for the transmission of PPDUs using STBC
73  bool txSTBC;
74  // Indicates support for the reception of PPDUs using STBC
77  // Indicates support for HT delayed Block Ack operation
79  // maximum AMSDU length in bytes
82  // DSSS/CCK Mode in 40 MHz
84  // Indicates whether APs receiving this information or reports of this
85  // information are required to prohibit 40 MHz transmissions
87  // Indicates support for the LSIG TXOP protection mechanism
89  };
90 
92  {
93  enum MaxMPDULength { MaxMPDULength_3895, MaxMPDULength_7991, MaxMPDULength_11454 };
94  enum MaxMPDULength maxMPDULength;
98  SupportedChannelWidth_160_8080MHz };
99  enum SupportedChannelWidth supportedChannelWidth;
100  bool rxLDPC;
103  bool txSTBC;
112  };
113 
114 
116  {
117  enum Enum { Config, Scan, Regulatory, Mlme, Vendor };
118  };
119 
120  struct RadarEvent
121  {
123 
124  enum Type {
125  RadarDetected = NL80211_RADAR_DETECTED,
128  RadarNopFinished = NL80211_RADAR_NOP_FINISHED };
129 
131  unsigned frequency;
132  };
133 
135  {
137 
138  enum Type {
143 
145  };
146 
147  struct ScanEvent
148  {
150 
151  enum Type {
152  COMPLETED = 0, ABORTED = 1 };
153 
155  };
156 
158  {
159  /* VHT MCS */
160  typedef std::bitset<10> VHT_MCSBitmap;
161  typedef std::array<VHT_MCSBitmap, NL80211_VHT_NSS_MAX> VHT_MCSBitmapTable;
162  boost::optional<VHT_MCSBitmapTable> vht_mcs_table_24;
163  boost::optional<VHT_MCSBitmapTable> vht_mcs_table_5;
164  /* HT MCS */
165  typedef uint8_t MCSIndex;
166  typedef std::set<MCSIndex> MCSIndexSet;
167  boost::optional<MCSIndexSet> mcs_24;
168  boost::optional<MCSIndexSet> mcs_5;
169  /* Legacy */
170  typedef uint32_t LegacyBitrate; // Bitrate in kbps
171  typedef std::set<LegacyBitrate> LegacyBitrateSet;
172  boost::optional<LegacyBitrateSet> legacy_24;
173  boost::optional<LegacyBitrateSet> legacy_5;
174  /* GI */
175  enum GICfg {
179  };
180  boost::optional<GICfg> gi_24;
181  boost::optional<GICfg> gi_5;
182  };
183 
185  {
186  public:
188 
189  public:
190  struct IfaceType {
191  enum Enum { Unspecified, AdHoc, Station, AP, APVLan, WDS, Monitor, MeshPoint, Unknown };
192  static std::string str(Enum type);
193  };
194  struct MonitorFlags {
195  enum Enum {
196  None = 0, // no special flags
197  FCSFail = 1 << NL80211_MNTR_FLAG_FCSFAIL, // pass frames with FCS errors
198  PLCPFail = 1 << NL80211_MNTR_FLAG_PLCPFAIL, // pass frames with bad PLCP
199  Control = 1 << NL80211_MNTR_FLAG_CONTROL, // pass control frames
200  OtherBSS = 1 << NL80211_MNTR_FLAG_OTHER_BSS // show frames from other BSSes
201  };
202  };
203  struct ChannelMode {
204  enum Enum {
210  };
211  };
212  struct DFSState {
213  enum Enum {
214  NoDFS = -1,
216  Unavailable = NL80211_DFS_UNAVAILABLE,
218  };
219  static std::string str(Enum state);
220  };
221  struct TxPowerSetting {
222  enum Enum {
226  };
227  };
228  enum Band_t {
229  BAND_2GHZ = NL80211_BAND_2GHZ,
230  BAND_5GHZ = NL80211_BAND_5GHZ
231  };
232 
233  typedef unsigned bitrate_type;
234  typedef unsigned frequency_type;
235 
236  struct Survey {
237  Survey (bool inuse) :
238  frequency(0), noise(0), channelTime(0), channelTimeBusy(0), channelTimeExtBusy(0),
239  channelTimeRx(0), channelTimeTx(0), inUse(inuse) {
240  };
241 
242  frequency_type frequency;
243  std::uint8_t noise;
244  std::uint64_t channelTime;
245  std::uint64_t channelTimeBusy;
246  std::uint64_t channelTimeExtBusy;
247  std::uint64_t channelTimeRx;
248  std::uint64_t channelTimeTx;
249  bool inUse;
250 
251  bool operator<(Survey const & other) const {
252  return frequency < other.frequency;
253  };
254 
255  };
256 
257  struct ScanResults {
259  frequency(0), tsf (0), bssId(bssid), beaconInterval(0), capability(0), signal(0),
260  signalUnspec(0), status(0), seenMsAgo(0), informationElementsLength(0), beaconInformationElementsLength(0) {
261  memset(informationElements, 0, sizeof(informationElements));
262  memset(beaconInformationElements, 0, sizeof(beaconInformationElements));
263  };
264 
265  frequency_type frequency;
266  std::uint64_t tsf;
268  std::uint16_t beaconInterval;
269  std::uint16_t capability;
270  std::int32_t signal;
271  std::uint8_t signalUnspec;
272  std::uint32_t status;
273  std::uint32_t seenMsAgo;
276  std::uint8_t informationElements[4096];
277  std::uint8_t beaconInformationElements[4096];
278 
279  bool operator<(ScanResults const & other) const {
280  return bssId < other.bssId;
281  };
282  };
283 
284  private:
285  typedef std::multimap<Band_t, frequency_type> Frequencies;
286  typedef boost::transform_iterator< ::__gnu_cxx::select2nd<Frequencies::value_type>,
287  Frequencies::const_iterator> Frequencies_iterator;
288  typedef std::vector<bitrate_type> BitrateList;
289 
290  class JoinParameters : boost::noncopyable,
291  public boost::enable_shared_from_this<JoinParameters>
292  {
293  typedef boost::function<void (JoinParameters const &)> Callback;
294  typedef boost::shared_ptr<JoinParameters> ptr;
295 
296  JoinParameters(Callback cb, frequency_type freq, ChannelMode::Enum channelMode, bool & success);
297 
298  void initHTCapabilities();
299 
300  Callback callback_;
301  bool handleDFS_;
302  frequency_type freq_;
303  ChannelMode::Enum channelMode_;
304  bool & success_;
305  std::vector<unsigned char> ies_;
306  boost::optional<ieee80211_ht_cap> htCapabilities_;
307  boost::optional<ieee80211_ht_cap> htCapabilitiesMask_;
308  boost::optional<boost::uint32_t> beaconInterval_;
309 
310  friend class WirelessNLController;
311  friend class HardwareWLANInterface;
312 
313  public:
314  ~JoinParameters();
315 
316  template <typename ForwardReadableRange>
317  JoinParameters::ptr informationElements(ForwardReadableRange const & ies);
318  JoinParameters::ptr ampduFactor(unsigned factor);
319  JoinParameters::ptr beaconInterval(boost::optional<boost::uint32_t> interval);
320  JoinParameters::ptr handleDFS(bool flag);
321  };
322 
323  class IbssJoinParameters : public JoinParameters
324  {
325  typedef boost::shared_ptr<IbssJoinParameters> ptrI;
326  IbssJoinParameters(Callback cb, std::string const & ssid, frequency_type freq, ChannelMode::Enum channelMode, bool & success);
327 
328  std::string ssid_;
329  senf::MACAddress bssid_;
330 
331  friend class WirelessNLController;
332  friend class HardwareWLANInterface;
333 
334  public:
335  IbssJoinParameters::ptrI bssid(senf::MACAddress const & mac);
336  };
337 
338  class MeshJoinParameters : public JoinParameters
339  {
340  typedef boost::shared_ptr<MeshJoinParameters> ptrM;
341  MeshJoinParameters(Callback cb, std::string const & meshId, frequency_type freq, ChannelMode::Enum channelMode, bool & success);
342 
343  std::string meshId_;
344  boost::optional<boost::uint8_t> vendorMetric_;
345  boost::optional<boost::uint8_t> vendorPathSelection_;
346  boost::optional<boost::uint8_t> vendorSynchronization_;
347 
348  friend class WirelessNLController;
349  friend class HardwareWLANInterface;
350 
351  public:
352 
353  MeshJoinParameters::ptrM vendorMetric(bool enable);
354  MeshJoinParameters::ptrM vendorPathSelection(bool enable);
355  MeshJoinParameters::ptrM vendorSynchronization(bool enable);
356  };
357 
358  public:
359  typedef boost::iterator_range<Frequencies_iterator> FrequencyRange;
360  typedef boost::function<int (nl_msg *)> NetlinkMsgCallback;
361 
362  WirelessNLController(bool disableSeqNoCheck = true);
363  WirelessNLController(std::string const & interface);
364 
365  JoinParameters::ptr ibss_join(std::string const & ssid, frequency_type freq, ChannelMode::Enum channelMode, bool & success);
366  void ibss_leave();
367 
368  JoinParameters::ptr mesh_join(std::string const & meshId, frequency_type freq, ChannelMode::Enum channelMode, bool & success);
369  void mesh_leave();
370 
371  void set_frequency(frequency_type freq, ChannelMode::Enum = ChannelMode::NoHT20);
372  void set_txpower(TxPowerSetting::Enum setting, unsigned int mBm);
373 
374  void add_monInterface(std::string const & name, int flags = MonitorFlags::None);
375  void add_adhocInterface(std::string const & name);
376  void add_apInterface(std::string const & name);
377  void add_meshInterface(std::string const & name, std::string const & meshId = "");
378 
379  void del_interface(std::string const & name);
380 
381  void set_retryLimit(boost::uint8_t shortLimit, boost::uint8_t longLimit);
382 
383  void set_txQueueParameters(boost::uint8_t queue, boost::uint16_t cwMin, boost::uint16_t cwMax, boost::uint8_t aifs, boost::uint16_t txop);
384 
385  std::pair<DFSState::Enum,std::uint32_t> dfsState(frequency_type freq);
386  void start_radarDetection(unsigned int freq, ChannelMode::Enum = ChannelMode::NoHT20);
387 
388  template <typename ForwardReadableRange>
389  void trigger_scan(ForwardReadableRange const & frequencies);
390  void do_trigger_scan(std::set<frequency_type> const & frequencies, std::set<std::string> const & ssids = {});
391 
392  void set_regulatory_request(std::string const & alpha2Country);
393  void set_regulatory(RegulatoryDomain const & regDomain);
394  RegulatoryDomain get_regulatory();
395 
396  static unsigned distanceToCoverageClass(unsigned distance);
397  void coverageClass(unsigned coverage);
398  unsigned coverageClass();
399 
400  bool hasHTCapabilities();
401  HTCapabilitiesInfo const & htCapabilities();
402 
403  bool hasVHTCapabilities();
404  VHTCapabilitiesInfo const & vhtCapabilities();
405 
406  typedef std::set<std::string> IfaceNameSet;
407  IfaceNameSet all_interfaces() const;
408 
409  std::string const & phyName() const;
410  int phyIndex() const;
411 
412  static int if_nameto_phy_index(std::string const & ifname);
413  static std::string if_nameto_phy_name(std::string const & ifname);
414  static int phy_nametoindex(std::string const & phyname);
415  static std::string macToPhy(senf::MACAddress const & mac);
416 
417  static int channelWidth(ChannelMode::Enum channelMode);
418  static int channelType(ChannelMode::Enum channelMode);
419  static frequency_type centerFreq(frequency_type freq, ChannelMode::Enum channelMode);
420 
421  std::multiset<ScanResults> const & getScan();
422  std::set<Survey> const & survey();
423  frequency_type frequency();
424  FrequencyRange frequencies();
425  FrequencyRange frequencies(Band_t band);
426 
427  void set_bitrates(BitrateParameters parameters);
428  BitrateParameters const & bitrates();
429 
431  void type(IfaceType::Enum);
432 
433  std::set<Band_t> const & supportedBands();
434 
435  template <typename EventType>
437  {
438  public:
439  boost::signals2::signal<void (EventType)> signal;
440  void enable();
441  void disable();
442 
443  private:
445  WirelessNLController & wnlc_;
446  friend class WirelessNLController;
447  };
448 
452 
453  private:
454  typedef boost::shared_ptr<nl_msg> nl_msg_ptr;
455  typedef std::unique_ptr<nl_sock, void(*)(nl_sock *)> nl_sock_ptr;
456  typedef std::unique_ptr<nl_cb, void(*)(nl_cb *)> nl_cb_ptr;
457  typedef std::unique_ptr<nl_cache, void(*)(nl_cache *)> nl_cache_ptr;
458  typedef int (WirelessNLController::* CallbackMemPtr)(nl_msg *);
459  enum CmdIdBy { CIB_NONE, CIB_PHY, CIB_IF };
460 
461  void init(bool disableSeqNoCheck = true);
462  void initNlSock(nl_sock_ptr & sock, bool disableSeqNoCheck = true);
463  void initNlCache(nl_sock_ptr & sock, nl_cache_ptr & cache);
464  void initNlCb(nl_sock_ptr & sock, nl_cb_ptr & cb, NetlinkMsgCallback & msgcb);
465 
466  static nl_msg_ptr nlMsg();
467  static void nlPutChannelDef(nl_msg_ptr msg, frequency_type freq, ChannelMode::Enum channelMode);
468  nl_msg_ptr nlMsgHeader(uint8_t cmd, CmdIdBy idBy, int flags=0) const;
469  void send_and_wait4response(nl_msg_ptr const & msg, CallbackMemPtr cb = nullptr);
470  void send(nl_msg_ptr const & msg);
471 
472  void do_ibss_join(JoinParameters const & parameters);
473  void do_mesh_join(JoinParameters const & parameters);
474 
475  int processScanResponse(std::uint8_t cmd, nlattr ** msgAttr);
476  int getScan_cb(nl_msg * msg);
477 
478  void getWiphy();
479 
480  // netlink callbacks
481  int netlink_cb(nl_msg * msg);
482  int netlink_event_cb(nl_msg * msg);
483 
484  int getWiphy_cb(nl_msg * msg);
485  int getSurvey_cb(nl_msg * msg);
486  int getIface_cb(nl_msg * msg);
487  int getMCGroups_cb(nl_msg * msg);
488  int getRegDomain_cb(nl_msg * msg);
489 
490  int multicastGroupId(NetlinkMulticastGroup::Enum group);
491  void join_multicastGroup(NetlinkMulticastGroup::Enum group);
492  void leave_multicastGroup(NetlinkMulticastGroup::Enum group);
493  void get_multicastGroups();
494  void initEventHandling();
495  void deinitEventHandling();
496  void processReadEvent(int eventMask);
497 
498  int processRadarEvent(nlattr ** msgAttr);
499  int processRegDomainEvent(nlattr ** msgAttr);
500 
501  Frequencies frequencies_;
502  BitrateParameters bitrates_;
503  bool firstMutlipartMsg_;
504  std::set<Survey> survey_;
505  std::multiset<ScanResults> scanResults_;
506  IfaceType::Enum ifaceType_;
507  unsigned coverageClass_;
508  bool hasHTCapabilities_;
509  HTCapabilitiesInfo htCapabilities_;
510  bool hasVHTCapabilities_;
511  VHTCapabilitiesInfo vhtCapabilities_;
512  std::set<Band_t> supportedBands_;
513 
514  int ifIndex_;
515  int phyIndex_;
516  std::string phyName_;
517  nl_sock_ptr nl_sock_;
518  nl_cache_ptr nl_cache_;
519  nl_cb_ptr nl_cb_;
520  int nl80211Id_;
521  CallbackMemPtr callback_;
522  NetlinkMsgCallback netlinkMsgCb_;
523  NetlinkMsgCallback netlinkEventCb_;
524  int bandtype_;
525  typedef std::map<frequency_type, std::pair<DFSState::Enum,std::uint32_t>> DFSStateMap;
526  DFSStateMap dfsStates_;
527  RegulatoryDomain regDomain_;
528  boost::optional<std::set<BitrateParameters::MCSIndex> > tmpMCSRates_;
529  boost::optional<std::set<BitrateParameters::LegacyBitrate> > tmpLegacyRates_;
530 
531  nl_sock_ptr nl_event_sock_;
532  nl_cb_ptr nl_event_cb_;
533  std::set<NetlinkMulticastGroup::Enum> joinedMCGroups_;
534  std::map<std::string, int> multicastGroups_;
535  boost::scoped_ptr<scheduler::FdEvent> nlEvent_;
536 
537  friend class HardwareWLANInterface;
538  };
539 
540 
542  {
543  public:
544  NetlinkException(int code, std::string const & descr = "");
545 
546  int errorNumber() const;
547  char const * errorString() const;
548 
549  private:
550  int code_;
551  };
552 }}
553 
554 //-/////////////////////////////////////////////////////////////////////////////////////////////////
555 //#include "WirelessNLController.cci"
556 #include "WirelessNLController.ct"
557 //#include "WirelessNLController.cti"
558 #endif
559 
560 
561 // Local Variables:
562 // mode: c++
563 // fill-column: 100
564 // comment-column: 40
565 // c-file-style: "senf"
566 // indent-tabs-mode: nil
567 // ispell-local-dictionary: "american"
568 // compile-command: "scons -u test"
569 // End:
void init()
std::uint8_t mac[6]
std::string str(T const &t)
u8 type
#define SENF_LOG_CLASS_AREA()
bool operator<(Survey const &other) const
Regulatory header.
boost::function< int(nl_msg *)> NetlinkMsgCallback
boost::optional< MCSIndexSet > mcs_24
char ssid[36]
__u8 band
Definition: nl80211-new.h:128
std::set< LegacyBitrate > LegacyBitrateSet
boost::optional< LegacyBitrateSet > legacy_5
std::array< VHT_MCSBitmap, NL80211_VHT_NSS_MAX > VHT_MCSBitmapTable
NetlinkEvent< ScanEvent > scanEvent
StatsDataCollectorKernel signal
boost::optional< VHT_MCSBitmapTable > vht_mcs_table_24
boost::signals2::signal< void(EventType)> signal
NetlinkEvent< RadarEvent > radarEvent
boost::optional< MCSIndexSet > mcs_5
std::uint8_t bssid[6]
bool operator<(ScanResults const &other) const
std::set< std::string > IfaceNameSet
boost::optional< VHT_MCSBitmapTable > vht_mcs_table_5
boost::optional< GICfg > gi_5
__be64 tsf
boost::optional< GICfg > gi_24
NetlinkEvent< RegulatoryDomainChangeEvent > regulatoryDomainChangeEvent
boost::optional< LegacyBitrateSet > legacy_24
s8 noise
__be16 freq
boost::iterator_range< Frequencies_iterator > FrequencyRange