dfstest.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 #include <boost/filesystem.hpp>
18 #include <senf/Utils/String.hh>
19 #include <senf/Utils/algorithm.hh>
20 #include <senf/Utils/Logger.hh>
24 
25 //-/////////////////////////////////////////////////////////////////////////////////////////////////
26 namespace {
27 
29  {
30  std::cerr << "usage: dfstest \n"
31  << " -i, --interface=<adhoc_iface>\n"
32  << " -n --nloops=<loops over frequency range>\n"
33  << " -w, --wait=<wait time in sec per frequency>\n"
34  << " -t, --time=<total time in sec (0 for endless)>\n"
35  << " -f, --frequencies=<frequencies to scan>\n"
36  << " --htmode=<NoHT|HT20|HT40Minus|HT40Plus>\n" << std::endl;
37  exit(1);
38  }
39 
40  void runScheduler(senf::ClockService::clock_type timeout)
41  {
42  senf::scheduler::TimerEvent timeoutEvent (
43  "dfstest timeout", senf::scheduler::terminate, senf::ClockService::now() + timeout);
44  senf::scheduler::process();
45  }
46 
47  void handleRadarEvent(senf::emu::RadarEvent event)
48  {
49  SENF_LOG_BLOCK( ({
50  log << "RadarEvent received for frequency " << event.frequency
51  << "000 type: ";
52  switch (event.type) {
53  case senf::emu::RadarEvent::RadarDetected:
54  log << "Radar Detected";
55  break;
56  case senf::emu::RadarEvent::CACFinished:
57  log << "CAC Finished";
58  senf::scheduler::terminate();
59  break;
60  case senf::emu::RadarEvent::CACAborted:
61  log << "CAC Aborted";
62  senf::scheduler::terminate();
63  break;
64  case senf::emu::RadarEvent::RadarNopFinished:
65  log << "Radar-Nop Finished";
66  break;
67  default:
68  log << "Unknown: " << int(event.type);
69  break;
70  }
71  }) );
72  }
73 }
74 
75 namespace senf { namespace emu {
76 
78  WirelessNLController::ChannelType, Enum, (NoHT)(HT20)(HT40Minus)(HT40Plus) );
79 }}
80 
81 namespace emu = senf::emu;
82 
83 int run(int argc, char const * argv[])
84 {
85  std::string iface;
86  unsigned nloops = 100000000;
87  unsigned waitTime = 60;
88  unsigned totalTime = 0;
89  senf::console::ValueRange<unsigned> frequencyRange = { 0, 0 };
90  emu::WirelessNLController::ChannelType::Enum htMode = emu::WirelessNLController::ChannelType::NoHT;
91 
92  namespace fty = senf::console::factory;
93  senf::console::root().add("help", fty::Command(&print_usage_and_exit));
94  senf::console::root().add("interface", fty::Variable(iface));
95  senf::console::root().add("nloops", fty::Variable(nloops));
96  senf::console::root().add("wait", fty::Variable(waitTime));
97  senf::console::root().add("time", fty::Variable(totalTime));
98  senf::console::root().add("frequencies", fty::Variable(frequencyRange));
99  senf::console::root().add("htmode", fty::Variable(htMode));
100  senf::console::root().add("crda", emu::CRDA::instance().dir);
101 
102  std::vector<std::string> nonOptions;
103  senf::console::ProgramOptions cmdlineOptions (argc, argv);
104  cmdlineOptions
105  .alias('i', "--interface", true)
106  .alias('n', "--nloops", true)
107  .alias('w', "--wait", true)
108  .alias('t', "--time", true)
109  .alias('f', "--frequencies", true)
110  .nonOptions(nonOptions);
111  try {
112  cmdlineOptions.parse();
113  } catch (senf::console::SyntaxErrorException const & e) {
114  std::cerr << e.message() << std::endl;
116  }
117  if (not nonOptions.empty())
119 
120  if (iface.empty())
122 
123  // only allow DFS channels
124  emu::RegulatoryDomain dfsRegDomain_;
125  dfsRegDomain_.alpha2Country = "XX";
127  dfsRegDomain_.rules.insert(emu::RegulatoryRule()
128  .frequencyRange(5250000, 5330000)
129  .maxBandwidth(40000)
130  .maxEIRP(3000)
131  .noIR(true)
132  .dfsRequired(true) );
133  dfsRegDomain_.rules.insert(emu::RegulatoryRule()
134  .frequencyRange(5490000, 5730000)
135  .maxBandwidth(40000)
136  .maxEIRP(3000)
137  .noIR(true)
138  .dfsRequired(true) );
139 
140  if (not emu::CRDA::instance().regDomain().isEqual(dfsRegDomain_)) {
141  std::cout << "Settings DFS-only regDomain...";
142  if (not emu::CRDA::instance().regDomain(dfsRegDomain_)) {
143  std::cout << "Failed !" << std::endl;
144  return 1;
145  } else {
146  std::cout << "OK" << std::endl;
147  }
148 
149  sleep(2);
150 
151  if (emu::CRDA::instance().equalsKernel()) {
152  std::cout << "Current regDomain updated to " << emu::CRDA::instance().regDomain() << std::endl;
153  } else {
154  std::cout << "Requested regDomain does not match the kernel's regDomain !!!" << std::endl;
155  return 1;
156  }
157  } else {
158  std::cout << "Current regDomain is already " << emu::CRDA::instance().regDomain() << std::endl;
159  }
160 
161  emu::WirelessNLController wnlc (iface);
162 
163  auto frequencies (wnlc.frequencies());
164  std::set<unsigned> dfsFreqs (frequencies.begin(), frequencies.end());
165  for (auto f = dfsFreqs.begin(); f != dfsFreqs.end();) {
166  if (*f < frequencyRange.lower) {
167  dfsFreqs.erase(f++);
168  continue;
169  }
170  if (frequencyRange.upper != 0 and *f > frequencyRange.upper) {
171  dfsFreqs.erase(f++);
172  continue;
173  }
175  dfsFreqs.erase(f++);
176  continue;
177  }
178  ++f;
179  }
180 
181  if (dfsFreqs.empty()) {
182  std::cout << "No DFS-required frequencies found; stopping test.";
183  return 1;
184  }
185 
186  auto & logTarget (senf::log::ConsoleTarget::instance());
187  logTarget.route<senf::log::MESSAGE>();
188  logTarget.tag("");
189  logTarget.showLevel(false);
190  logTarget.timeFormat("%Y-%m-%d %H:%M:%S");
191 
192  SENF_LOG( ("Running DFS Test on interface " << iface) );
193  SENF_LOG( ("Using Interfaces " << senf::stringJoin(dfsFreqs, ", ")) );
194 
195  {
196  senf::NetdeviceController ctrl (iface);
197  if (not ctrl.isUp())
198  ctrl.up();
199  if (not emu::WirelessExtController(iface).ssid().empty())
200  wnlc.ibss_leave();
201  }
202 
203  wnlc.radarEvent.signal.connect(&handleRadarEvent);
204  wnlc.radarEvent.enable();
205 
206  if (totalTime)
207  senf::scheduler::TimerEvent timeoutEvent (
208  "dfstest total timeout", boost::bind(::exit, 0),
210 
211  while (nloops-- > 0) {
212  for (unsigned freq : dfsFreqs) {
213  switch (wnlc.dfsState(freq)) {
215  SENF_LOG( ("Performing CAC for frequency " << freq << " (" << senf_console_format_enum(htMode) << ")") );
216  wnlc.start_radarDetection(freq, htMode);
217  runScheduler(senf::ClockService::seconds(61));
218  continue;
220  SENF_LOG( ("DFS state for frequency " << freq << " is Unavailable; skipping frequency.") );
221  continue;
223  SENF_LOG( ("Join cell on frequency " << freq << " (" << senf_console_format_enum(htMode)
224  << ") and wait " << waitTime << " seconds for radar events.") );
225  wnlc.ibss_join("DFS_test", freq, htMode)
226  ->handleDFS(true);
227  runScheduler(senf::ClockService::seconds(waitTime));
228  break;
229  default:
230  SENF_LOG( ("Unknown DFS state: " << int(wnlc.dfsState(freq))) );
231  return 1;
232  }
233  wnlc.ibss_leave();
234  }
235  }
236 
237  return 0;
238 }
239 
240 int main(int argc, char const * argv[])
241 {
242  if (boost::filesystem::path(argv[0]).filename() == emu::CRDA::instance().slaveName()) {
244  return emu::CRDA::instance().run(argc, argv);
245  }
246 
247  // true ==> MasterMode
248  if (!emu::CRDA::instance().init(true)) {
249  std::cerr << "Failed to init CRDA ?!?" << std::endl;
250  return 2;
251  }
252 
253  try {
254  return run( argc, argv);
255  } catch (senf::Exception & e) {
256  std::cerr << e.message() << std::endl;
257  return 2;
258  }
259 }
260 
261 //-/////////////////////////////////////////////////////////////////////////////////////////////////
config::time_type clock_type
#define SENF_LOG_BLOCK(args)
void init()
bool empty()
WirelessExtController public header.
void print_usage_and_exit()
Definition: wlanMon2Eth.cc:27
virtual void terminate() const
static SENF_CLOCKSERVICE_CONSTEXPR clock_type seconds(int64_type const &v)
char ssid[36]
std::pair< DFSState::Enum, std::uint32_t > dfsState(frequency_type freq)
SENF_CONSOLE_REGISTER_ENUM_MEMBER(DVBModulationParameter, fec_rate_t,(FEC_NONE)(FEC_1_2)(FEC_2_3)(FEC_3_4)(FEC_4_5)(FEC_5_6)(FEC_6_7)(FEC_7_8)(FEC_8_9)(FEC_AUTO)(FEC_3_5)(FEC_9_10))
ProgramOptions & nonOptions(Container &container)
std::set< RegulatoryRule > rules
Definition: Regulatory.hh:132
static CRDA & instance()
Definition: CRDA.cc:39
int run(int argc, char const **argv)
Definition: CRDA.cc:383
int run(int argc, char const *argv[])
Definition: dfstest.cc:83
NetlinkEvent< RadarEvent > radarEvent
int main(int argc, char const *argv[])
Definition: dfstest.cc:240
static ConsoleTarget & instance()
JoinParameters::ptr ibss_join(std::string const &ssid, frequency_type freq, ChannelMode::Enum channelMode, bool &success)
WirelessNLController public header.
bool init(bool MasterMode=false, std::string const &filename=DEFAULT_CRDA_SYNC_FILE)
Definition: CRDA.cc:154
bool regDomain(senf::emu::RegulatoryDomain regDomain)
Definition: CRDA.cc:232
std::string message() const
static clock_type now()
void start_radarDetection(unsigned int freq, ChannelMode::Enum=ChannelMode::NoHT20)
#define SENF_LOG(args)
ProgramOptions & alias(char letter, std::string const &longOpt, bool withArg=false)
__be16 freq