EmulatedWirelessInterface.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 
18 
19 // Custom includes
20 #include <unistd.h>
21 #include <boost/lambda/lambda.hpp>
22 #include <boost/lambda/bind.hpp>
26 #include <senf/Utils/algorithm.hh>
27 
28 #define prefix_
29 //-/////////////////////////////////////////////////////////////////////////////////////////////////
30 
31 //-/////////////////////////////////////////////////////////////////////////////////////////////////
32 // senf::emu::detail::EmulatedWirelessInterfaceTransmitFilter
33 
34 prefix_ void senf::emu::detail::EmulatedWirelessInterfaceTransmitFilter::request()
35 {
36  Packet p (input());
37  if (iface_.basei::interface().modulationParameterIds().empty())
38  return;
39  EmulatedWirelessPacketHeader h (EmulatedWirelessPacketHeader::createBefore(p));
40  h->modulationId() = iface_.basei::interface().transmitter().modulation();
41  h->txPower() = iface_.basei::interface().transmitter().txPower() / 100;
42  h->frequency() = iface_.basei::interface().frequency();
43  h->bandwidth() = iface_.basei::interface().bandwidth();
44  h.finalizeThis();
45  output(h);
46 }
47 
48 //-/////////////////////////////////////////////////////////////////////////////////////////////////
49 // senf::emu::detail::EmulatedWirelessInterfaceReceiveFilter
50 
51 prefix_ void senf::emu::detail::EmulatedWirelessInterfaceReceiveFilter::request()
52 {
53  EmulatedWirelessPacketHeader p (input());
54 
55  // filter packets which are sent before the channel is changed
56  if (iface_.basei::interface().frequency() != p->frequency() ||
57  iface_.basei::interface().bandwidth() != p->bandwidth()) return;
58 
59  Packet n (p.next(senf::nothrow));
60  if (!n)
61  return;
62  if (! senf::contains(iface_.basei::interface().modulationParameterIds(), p->modulationId())) {
63  SENF_LOG((senf::log::IMPORTANT)("Dropping packet with unknown wireless modulation parameter " << p->modulationId()));
64  return;
65  }
66  p.annotation<annotations::WirelessModulation>().id = p->modulationId();
67  if (! iface_.v_emulatedWirelessQuality(n, p.annotation<annotations::Quality>()))
68  return;
69 
70  output(n);
71 }
72 
73 //-/////////////////////////////////////////////////////////////////////////////////////////////////
74 // senf::emu::EmulatedFrequencyRegistry
75 
77  unsigned frequency,
78  unsigned bandwidth, UserCallback cb)
79 {
80  namespace l = boost::lambda;
81  using boost::lambda::_1;
82 
83  checkCollisionOk(frequency, bandwidth);
84 
86  entries_.get<ByFrequency>().find(boost::make_tuple(frequency,bandwidth)));
87  if (i == entries_.end()) {
88  Entry e (frequency, bandwidth);
89  if (running_) {
90  e.address = getAddress();
92  sendAdd(Interface::nodeId(), frequency, bandwidth, e.address);
93  }
94  i = entries_.insert(e).first;
95  }
96  users_.insert(User(i, interfaceId, cb));
97  if (running_) {
98  sendJoin(Interface::nodeId(), frequency, bandwidth);
99  entries_.modify(i, (++ l::bind(&Entry::nUsers, _1)));
101  }
102  cb(i->address);
103  if (! server_ && group_)
104  schedulerStart_.enable();
105 }
106 
108 {
109  namespace l = boost::lambda;
110  using boost::lambda::_1;
111 
112  Users::index_iterator<ByInterfaceId>::type i (users_.get<ByInterfaceId>().find(interfaceId));
113  SENF_ASSERT( i != users_.end(),
114  "senf::emu::EmulatedFrequencyRegistry::release(): "
115  "No registration for interface" );
116  sendLeave(Interface::nodeId(), i->entry->frequency, i->entry->bandwidth);
117  if (i->entry->nUsers > 0 && running_) {
118  entries_.modify(i->entry, -- l::bind(&Entry::nUsers, _1));
120  } // Otherwise there was a stop/release race
121  if (i->entry->nUsers == 0 && i->entry->ownerNodeId == Interface::nodeId()) {
122  sendDel(Interface::nodeId(), i->entry->frequency, i->entry->bandwidth);
123  entries_.get<ByFrequency>().erase(i->entry);
124  }
125  users_.erase(i);
126 }
127 
128 //-/////////////////////////////////////////////////////////////////////////////////////////////////
129 // private members
130 
131 prefix_ senf::emu::EmulatedFrequencyRegistry::EmulatedFrequencyRegistry()
132  : socket_ (), group_ ("239.202.104.1:4701"), server_ (),
133  schedulerStart_ ("senf::emu::EmulatedFrequencyRegistry::schedulerStart",
135  channelGroupRange_ ("239.202.108.0/22"), portbase_ (11264u), lastAddress_ (perturb(Interface::nodeId())),
136  entries_ (), users_ (), running_ (false)
137 {
138  namespace fty = console::factory;
139 
140  console::sysdir().add("emu", dir_);
141 
142  dir_.add("consoleGroup",
143  fty::Command(SENF_MEMBINDFNP(UDPClientHandle::Address, EmulatedFrequencyRegistry,
144  consoleGroup, () const)));
145  dir_.add("consoleGroup",
146  fty::Command(SENF_MEMBINDFNP(void, EmulatedFrequencyRegistry,
147  consoleGroup, (UDPClientHandle::Address const &))));
148 
149  typedef std::pair<INet4Network, unsigned> AddressPair;
150  dir_.add("addressRange",
151  fty::Command(SENF_MEMBINDFNP(AddressPair, EmulatedFrequencyRegistry,
152  addressRange, () const)));
153  dir_.add("addressRange",
154  fty::Command(SENF_MEMBINDFNP(void, EmulatedFrequencyRegistry,
155  addressRange, (INet4Network const &, unsigned))));
156 
157  dir_.add("list", fty::Command(&EmulatedFrequencyRegistry::consoleList, this));
158  dir_.add("nodeId", fty::Command( SENF_FNP( unsigned, Interface::nodeId, ())) );
159 
160  console::DirectoryNode & ipcdir (dir_.add("ipc",fty::Directory()));
161  ipcdir.add("add", fty::Command(&EmulatedFrequencyRegistry::add, this));
162  ipcdir.add("del", fty::Command(&EmulatedFrequencyRegistry::del, this));
163  ipcdir.add("join", fty::Command(&EmulatedFrequencyRegistry::join, this));
164  ipcdir.add("leave", fty::Command(&EmulatedFrequencyRegistry::leave, this));
165  ipcdir.add("poll", fty::Command(&EmulatedFrequencyRegistry::poll, this));
166  ipcdir.add("start", fty::Command(&EmulatedFrequencyRegistry::start, this));
167  ipcdir.add("stop", fty::Command(&EmulatedFrequencyRegistry::stop, this));
168 }
169 
171 {
172  schedulerStart_.disable();
173  if (group_) {
174  server_.reset(new console::UDPServer(group_));
175  server_->root(dir_["ipc"]).emptyReplies(false);
176  }
177 }
178 
179 prefix_ void senf::emu::EmulatedFrequencyRegistry::consoleList(std::ostream & os)
180  const
181 {
182  boost::format fmt ("%10d %10d %-21s%5d %10d ");
183  os << fmt % "FREQUENCY" % "BANDWIDTH" % "ADDRESS" % "NODES" % "OWNER" << " USERS\n";
184  EntriesRange e (entries());
185  for (EntriesRange::iterator i (e.begin()); i != e.end(); ++i) {
186  os << fmt
187  % i->frequency
188  % i->bandwidth
189  % i->address
190  % i->nUsers
191  % i->ownerNodeId;
192  UsersRange u (users(i));
193  for (UsersRange::iterator j (u.begin()); j != u.end(); ++j)
194  os << " " << *j;
195  os << '\n';
196  }
197  os << (running_ ? " running\n" : " halted\n");
198 }
199 
200 prefix_ void senf::emu::EmulatedFrequencyRegistry::add(unsigned nodeId, unsigned frequency,
201  unsigned bandwidth,
202  UDPClientHandle::Address address)
203 {
204  namespace l = boost::lambda;
205  using boost::lambda::_1;
206 
207  if (nodeId == Interface::nodeId())
208  // drop looped commands
209  return;
211  entries_.get<ByFrequency>().find(boost::make_tuple(frequency,bandwidth)));
212  Entries::index_iterator<ByAddress>::type ai (entries_.get<ByAddress>().find(address));
213 
214  if (fi != entries_.get<ByFrequency>().end()
215  && ai != entries_.get<ByAddress>().end()
216  && &*fi == &*ai) {
217  // special case: Exact same entry already exists. Just update owner if necessary
218  if (nodeId < fi->ownerNodeId)
219  entries_.modify(fi, l::bind(&Entry::ownerNodeId, _1) = nodeId);
220  return;
221  }
222 
223  if (ai != entries_.get<ByAddress>().end()) {
224  // Same address is already in use by a different entry.
225  // The lower nodeId will get the requested address.
226  // If the loser is me (the losing entry has my own nodeId), select a new address and send
227  // a new 'add' message
228  if (nodeId < ai->ownerNodeId) {
229  UDPClientHandle::Address newAddr;
230  if (ai->ownerNodeId == Interface::nodeId()) {
231  // getAddress() here will find an address *different* from address since that address
232  // is still in the table ...
233  newAddr = getAddress();
234  sendAdd(Interface::nodeId(), ai->frequency, ai->bandwidth, newAddr);
235  }
236  entries_.get<ByAddress>().modify_key(ai, _1 = newAddr);
237  updateAddress(*ai);
238  }
239  else
240  return;
241  }
242 
243  if (fi != entries_.get<ByFrequency>().end()) {
244  // Entry exists for this frequency but possibly with different address.
245  // We use the address of the lower nodeId.
246  if (! fi->address || (fi->address != address && nodeId <= fi->ownerNodeId)) {
247  entries_.get<ByFrequency>().modify(
248  fi, (l::bind(&Entry::address,_1) = address,
249  l::bind(&Entry::ownerNodeId,_1) = nodeId));
250  updateAddress(*fi);
251  }
252  } else
253  entries_.insert(Entry(frequency, bandwidth, address, 0, nodeId));
254 }
255 
256 prefix_ void senf::emu::EmulatedFrequencyRegistry::del(unsigned nodeId, unsigned frequency,
257  unsigned bandwidth)
258 {
259  namespace l = boost::lambda;
260  using boost::lambda::_1;
261 
262  if (nodeId == Interface::nodeId())
263  // drop looped commands
264  return;
266  entries_.get<ByFrequency>().find(boost::make_tuple(frequency,bandwidth)));
267  if (i == entries_.get<ByFrequency>().end())
268  return;
269  // Only the owner may remove an entry
270  if (nodeId != i->ownerNodeId)
271  return;
272  if (users_.get<ByEntry>().count(i) > 0) {
274  "Active entry " << frequency << "," << bandwidth <<
275  " removed by " << nodeId));
276  entries_.get<ByFrequency>().modify(
277  i, (l::bind(&Entry::address,_1) = UDPClientHandle::Address(),
278  l::bind(&Entry::ownerNodeId,_1) = 0));
279  updateAddress(*i);
280  }
281  else
282  entries_.get<ByFrequency>().erase(i);
283 }
284 
285 prefix_ void senf::emu::EmulatedFrequencyRegistry::join(unsigned nodeId, unsigned frequency,
286  unsigned bandwidth)
287 {
288  namespace l = boost::lambda;
289  using boost::lambda::_1;
290 
291  if (nodeId == Interface::nodeId())
292  // drop looped commands
293  return;
295  entries_.get<ByFrequency>().find(boost::make_tuple(frequency,bandwidth)));
296  if (i == entries_.end()) {
297  // Probably out-of-order packets: Create an entry with empty address. This will
298  // later be filled with a valid address
299  i = entries_.insert(Entry(frequency, bandwidth, UDPClientHandle::Address(), 1, 0)).first;
300  return;
301  } else
302  entries_.modify(i, ++ l::bind(&Entry::nUsers, _1));
303  channelPopulationChanged(*i, nodeId, JOIN);
304 }
305 
306 prefix_ void senf::emu::EmulatedFrequencyRegistry::leave(unsigned nodeId, unsigned frequency,
307  unsigned bandwidth)
308 {
309  namespace l = boost::lambda;
310  using boost::lambda::_1;
311 
312  if (nodeId == Interface::nodeId())
313  // drop looped commands
314  return;
316  entries_.get<ByFrequency>().find(boost::make_tuple(frequency,bandwidth)));
317  if (i == entries_.end())
318  return;
319  if (i->nUsers > 0) {
320  entries_.modify(i, -- l::bind(&Entry::nUsers, _1));
321  channelPopulationChanged(*i, nodeId, LEAVE);
322  } // Otherwise there was a stop/leave race
323  if (i->nUsers == 0 && (i->ownerNodeId == Interface::nodeId() || i->ownerNodeId == 0)) {
324  if (users_.get<ByEntry>().count(i) > 0) {
326  "Disabling active entry " << frequency << "," << bandwidth <<
327  ": no users?"));
328  if (i->address) {
329  entries_.get<ByFrequency>().modify(
330  i, (l::bind(&Entry::address,_1) = UDPClientHandle::Address(),
331  l::bind(&Entry::ownerNodeId,_1) = 0));
332  updateAddress(*i);
333  }
334  }
335  else {
336  if (i->ownerNodeId == Interface::nodeId())
337  sendDel( Interface::nodeId(), i->frequency, i->bandwidth);
338  entries_.get<ByFrequency>().erase(i);
339  }
340  }
341 }
342 
343 prefix_ int senf::emu::EmulatedFrequencyRegistry::poll(unsigned nodeId, unsigned frequency,
344  unsigned bandwidth)
345 {
346  if (nodeId == Interface::nodeId())
347  // drop looped commands
348  return 0;
350  entries_.get<ByFrequency>().find(boost::make_tuple(frequency,bandwidth)));
351  if (i == entries_.end())
352  return 0;
354  users_.get<ByEntry>().equal_range(i));
355  return std::distance(e.first, e.second);
356 }
357 
359 {
360  namespace l = boost::lambda;
361  using boost::lambda::_1;
362 
363  if (! server_ && group_)
364  schedulerStart();
365  if (running_)
366  return;
367  SENF_LOG((senf::log::NOTICE)("Starting frequency allocation"));
368  for (Entries::iterator i (entries_.begin()), i_end (entries_.end()); i != i_end; ++i) {
369  unsigned users (users_.get<ByEntry>().count(i));
370  if (users > 0) {
371  if (! i->ownerNodeId && ! i->address) {
372  entries_.modify(i, (l::bind(&Entry::address,_1) = getAddress(),
373  l::bind(&Entry::ownerNodeId,_1) = Interface::nodeId()));
374  updateAddress(*i);
375  sendAdd(Interface::nodeId(), i->frequency, i->bandwidth, i->address);
376  }
377  for (; users > 0; --users) {
378  sendJoin(Interface::nodeId(), i->frequency, i->bandwidth);
379  entries_.modify(i, ++ l::bind(&Entry::nUsers, _1));
381  }
382  }
383  }
384  running_ = true;
385 }
386 
388 {
389  namespace l = boost::lambda;
390  using boost::lambda::_1;
391 
392  if (! running_)
393  return;
394  SENF_LOG((senf::log::NOTICE)("Stopping frequency allocation"));
395  if (entries_.empty()) {
396  running_ = false;
397  return;
398  }
399  Entries::iterator i (entries_.begin());
400  Entries::iterator i_next (boost::next(i));
401  Entries::iterator const i_end (entries_.end());
402  for (;i != i_end; i = i_next, ++ i_next) {
403  entries_.modify(i, (l::bind(&Entry::address,_1) = UDPClientHandle::Address(),
404  l::bind(&Entry::ownerNodeId,_1) = 0,
405  l::bind(&Entry::nUsers,_1) = 0));
407  if (users_.get<ByEntry>().count(i) == 0)
408  entries_.erase(i);
409  else
410  updateAddress(*i);
411  }
412  running_ = false;
413 }
414 
415 prefix_ void senf::emu::EmulatedFrequencyRegistry::sendAdd(unsigned nodeId, unsigned frequency,
416  unsigned bandwidth,
417  UDPClientHandle::Address address)
418 {
419  socket_.writeto(group_, (boost::format("add %d %d %d %s")
420  % nodeId % frequency % bandwidth % address).str());
421 }
422 
423 prefix_ void senf::emu::EmulatedFrequencyRegistry::sendDel(unsigned nodeId, unsigned frequency,
424  unsigned bandwidth)
425 {
426  socket_.writeto(group_, (boost::format("del %d %d %d")
427  % nodeId % frequency % bandwidth).str());
428 }
429 
430 prefix_ void senf::emu::EmulatedFrequencyRegistry::sendJoin(unsigned nodeId,
431  unsigned frequency,
432  unsigned bandwidth)
433 {
434  socket_.writeto(group_, (boost::format("join %d %d %d")
435  % nodeId % frequency % bandwidth).str());
436 }
437 
438 prefix_ void senf::emu::EmulatedFrequencyRegistry::sendLeave(unsigned nodeId,
439  unsigned frequency,
440  unsigned bandwidth)
441 {
442  socket_.writeto(group_, (boost::format("leave %d %d %d")
443  % nodeId % frequency % bandwidth).str());
444 }
445 
446 prefix_ void senf::emu::EmulatedFrequencyRegistry::sendPoll(unsigned nodeId,
447  unsigned frequency,
448  unsigned bandwidth)
449 {
450  socket_.writeto(group_, (boost::format("poll %d %d %d")
451  % nodeId % frequency % bandwidth).str());
452 }
453 
454 prefix_ senf::emu::UDPClientHandle::Address senf::emu::EmulatedFrequencyRegistry::getAddress()
455 {
456  for (;;) {
457  lastAddress_ = (lastAddress_+1) & ((1u<<(32-channelGroupRange_.prefix_len()))-1);
458  UDPClientHandle::Address addr (channelGroupRange_.host(lastAddress_),
459  portbase_ + lastAddress_);
461  entries_.get<ByAddress>().find(addr));
462  if (i == entries_.get<ByAddress>().end())
463  return addr;
464  }
465  return UDPClientHandle::Address();
466 }
467 
468 prefix_ void senf::emu::EmulatedFrequencyRegistry::updateAddress(Entry const & entry)
469 {
471  boost::tie(i, i_end) = users_.get<ByEntry>().equal_range(&entry);
472  for (; i != i_end; ++i)
473  i->callback(entry.address);
474 }
475 
476 namespace {
477 
478  inline bool frequencyOverlap(unsigned f1, unsigned b1, unsigned f2, unsigned b2)
479  {
480  return 2*f1-b1 <= 2*f2+b2 && 2*f2-b2 <= 2*f1+b1;
481  }
482 
483 }
484 
485 prefix_ void senf::emu::EmulatedFrequencyRegistry::checkCollisionOk(unsigned frequency,
486  unsigned bandwidth)
487 {
488  if (! cb_)
489  return;
490  for (Entries::index_iterator<ByFrequency>::type i (entries_.get<ByFrequency>().begin()),
491  i_end (entries_.get<ByFrequency>().end()); i != i_end; ++i)
492  if (frequencyOverlap(frequency, bandwidth, i->frequency, i->bandwidth)) {
493  cb_(frequency, bandwidth);
494  return;
495  }
496 }
497 
498 //-/////////////////////////////////////////////////////////////////////////////////////////////////
499 // senf::emu::EmulatedWirelessInterface
500 
502 {
503  // Need to use cached index_ value since interface() is not accessible from
504  // the destructor
505  if (index_)
507 }
508 
510  Ranges const & bandwidths)
511 {
512  for (Ranges::const_iterator i (frequencies.begin()), i_end (frequencies.end()); i != i_end; ++i)
513  for (Ranges::const_iterator j (bandwidths.begin()), j_end (bandwidths.end()); j != j_end; ++j)
514  registerFrequency(i->lower, i->upper, j->lower, j->upper);
515 }
516 
518 {
520 
521  namespace fty = console::factory;
522  interface().consoleDir()
523  .add("registerFrequency",
524  fty::Command(SENF_MEMBINDFNP(void, EmulatedWirelessInterface, registerFrequency,
525  (Ranges const &, Ranges const &)))
526  .arg("frequencies","channel frequencies in kHz")
527  .arg("bandwidths", "channel bandwidths in kHz")
528  .doc("Register valid frequency/bandwidth combinations.\n"
529  "Both parameters /frequencies/ and /bandwidths/ may be either a single value or\n"
530  "range or a list of values or ranges.\n"
531  "\n"
532  "The statement will register all combinations of any frequency with any bandwidth.\n"
533  "\n"
534  "Examples:\n"
535  " registerFrequency 2412000 20000;\n"
536  " Register a single frequency/bandwidth combination.\n"
537  "\n"
538  " registerFrequency 1000000:2000000 5000:20000;\n"
539  " Register a single frequency/bandwidth range combination.\n"
540  "\n"
541  " registerFrequency (2412000 2417000 2422000) 20000;\n"
542  " Register 3 frequency/bandwidth combinations;\n"
543  "\n"
544  " registerFrequency (1000000:2000000 3000000:4000000) (5000 10000:12000 20000);"
545  " Register 6 frequency/bandwidth combinations.") );
546 }
547 
549  unsigned bandwidth)
550 {
551  frequency_ = frequency;
552  bandwidth_ = bandwidth;
553  // cache index value for destructor
554  index_ = interface().index();
556  index_, frequency, bandwidth,
558  emulationAddress, (UDPClientHandle::Address const &)));
559 }
560 
562 {
563  // not supported.
564 }
565 
566 //-/////////////////////////////////////////////////////////////////////////////////////////////////
567 // senf::emu::EmulatedWirelessReceiver
568 
570 {
572 
573  namespace fty = console::factory;
574 
575  (*this).basei::interface().consoleDir()
576  .add("rssiRandomnessRange",
577  fty::Variable(rssiRandomnessRange_)
578  .doc("Set the range of the random variation of the RSSI value") );
579  (*this).basei::interface().consoleDir()
580  .add("noiseRandomnessRange",
581  fty::Variable(noiseRandomnessRange_)
582  .doc("Set the range of the random variation of the Noise value") );
583 }
584 
585 
586 prefix_ bool
588  annotations::Quality & quality)
589 {
590  //we need the distance between two nodes otherwise we can't calculate the attenuation
591  if (!emui::interface().distanceCallback_) {
592  SENF_LOG( (senf::log::VERBOSE) ("no distance callback function given") );
593  return true;
594  }
595 
596  PacketHeader ph = packet.rfind<PacketHeader>();
598 
599  double d = emui::interface().distanceCallback_(ph->nodeId());
600 
601  //distances equal to or smaller than 0 are invalid
602  if (d <=0 )
603  return true;
604 
607  unsigned f = (*this).basei::interface().frequency();
608 
609  //free space loss
610  // d in km
611  // f in khz
612  // 3.0e2 equals to c [1e3*1e3/c=3.0e2]
613  double fsl = 20 * log10( 4*d*M_PI*f/3.0e2);
614 
615  short rssi = short(ewph->txPower()-fsl);
616 
617  if (rssiRandomnessRange_ != 0)
618  rssi += rand() % rssiRandomnessRange_; // add some randomness
619 
620  if (rssi <= minRssi) {
621  SENF_LOG( (senf::log::VERBOSE) ("FSL to high. Packet is dropped"));
623  "minRSSI " << minRssi << "\n"
624  << "txpower: " << ewph->txPower() << "\n"
625  << "frequency (in KHz): " << f<< "\n"
626  << "transmitter node:" << ph->nodeId() << "\n"
627  << "distance " << emui::interface().distanceCallback_(ph->nodeId()) << " km\n"
628  << "Free Space Loss: " << fsl << " dB\n"
629  << "RSSI: " << rssi << " dB\n") );
630  return false;
631  }
632 
633  int defaultNoiseValue = -110;
634  if (noiseRandomnessRange_ !=0)
635  defaultNoiseValue=defaultNoiseValue + (rand()%noiseRandomnessRange_);
636 
637  //annotate packet with calculated values
638  quality.rssi = rssi;
639  quality.noise = defaultNoiseValue;
640  quality.snr = quality.rssi - quality.noise;
641 
642  //set fake flags. we need a better algo here
643  quality.flags.frameCorrupt = (rand() % ((rssi-minRssi)*(rssi-minRssi))) > 1 ? false : true;
644  quality.flags.frameRetransmitted = (rand() % ((rssi-minRssi)*(rssi-minRssi))) > 2 ? false : true;
645  quality.flags.frameLength = ewph.next().size();
646  return true;
647 }
648 
649 //-/////////////////////////////////////////////////////////////////////////////////////////////////
650 // senf::emu::EmulatedWirelessTransmitter
651 
653 {
654  for (Ranges::const_iterator i (powers.begin()), i_end (powers.end()); i != i_end; ++i)
655  registerTxPower(i->lower, i->upper);
656 }
657 
659 {
661 
662  namespace fty = console::factory;
663 
664  basei::interface().consoleDir()
665  .add("registerTxPower",
666  fty::Command(SENF_MEMBINDFNP(void, EmulatedWirelessTransmitter,
667  registerTxPower, (Ranges const &)))
668  .arg("powers", "transmit power values or ranges")
669  .doc("Register valid txpower values or ranges.\n"
670  "The /powers/ parameter may be either a single value or range or a list of values\n"
671  "or ranges:\n\n"
672  " registerTxPower 4;\n"
673  " Register single txpower value\n\n"
674  " registerTxPower (-4:-1 1:10);\n"
675  " Register two txpower ranges\n") );
676 }
677 
678 //-/////////////////////////////////////////////////////////////////////////////////////////////////
679 #undef prefix_
680 //#include "EmulatedWirelessInterface.mpp"
681 
682 
683 // Local Variables:
684 // mode: c++
685 // fill-column: 100
686 // comment-column: 40
687 // c-file-style: "senf"
688 // indent-tabs-mode: nil
689 // ispell-local-dictionary: "american"
690 // compile-command: "scons -u test"
691 // End:
void allocate(unsigned interfaceId, unsigned frequency, unsigned bandwidth, UserCallback cb)
Register for a wireless channel.
boost::uint16_t perturb(boost::uint16_t value)
std::vector< console::ValueRange< int > > Ranges
#define SENF_FNP(ret, fn, args)
#define SENF_MEMBINDFNP(ret, cls, fn, args)
void registerFrequency(unsigned frequency, unsigned bandwidth)
Register single frequency/bandwidth combination.
std::string str(T const &t)
boost::iterator_range< InterfaceIdIterator > UsersRange
Iterator range of interface id&#39;s using a channel.
u8 type
OtherPacket rfind() const
Emulated wireless transmitter base-class.
ModulationParameter const & findModulationById(ModulationParameter::id_t id) const
unsigned nUsers
Number of active channel users.
boost::function< R(Args)> membind(R(T::*fn)(Args), T *ob)
void registerTxPower(int power)
Register single txpower value.
#define prefix_
short minRssi
Minimum RSSI value.
UDPClientHandle::Address consoleGroup() const
Get control channel multicast group/port.
UDPClientHandle::Address address
Assigned multicast address.
static unsigned nodeId()
Get unique node id.
boost::iterator_range< Entries::index_iterator< ByFrequency >::type > EntriesRange
Iterator range of channel entries.
NodeType & add(std::string const &name, boost::shared_ptr< NodeType > node)
EmulatedFrequencyRegistry & emulatedFrequencyRegistry()
std::vector< console::ValueRange< unsigned > > Ranges
boost::signals2::signal< void(Entry const &, unsigned nodeId, ChangeType type)> channelPopulationChanged
Channel population changed signal.
Annotation & annotation()
virtual bool v_emulatedWirelessQuality(Packet packet, annotations::Quality &quality)
Overload to define wireless characteristics.
ConcretePacket< EmulatedWirelessPacketHeaderType > EmulatedWirelessPacketHeader
Definition: Packets.hh:179
nothrow
std::pair< INet4Network, unsigned > addressRange() const
Get address/port range of channel multicast addresses.
Emulated wireless interface base-class.
void start()
Start multicast address/port allocation.
#define SENF_ASSERT(x, comment)
unsigned emulatedFrequency() const
Get current emulated frequency.
s8 rssi
void release(unsigned interfaceId)
Release channel registration.
unsigned prefix_len() const
UsersRange users(EntriesRange::iterator i) const
Get interface id&#39;s of local users of a given channel.
static ModulationParameterRegistry & instance()
void stop()
Stop multicast address/port allocation.
INet4Address host(boost::uint32_t number)
boost::function< void(UDPClientHandle::Address const &address)> UserCallback
Callback type called to set channel address.
#define SENF_LOG(args)
EmulatedWirelessInterface public header.
EntriesRange entries() const
Get all channel entries.
NodeType & add(std::string const &name, boost::shared_ptr< NodeType > node)