21 #include <boost/lambda/lambda.hpp> 22 #include <boost/lambda/bind.hpp> 34 prefix_ void senf::emu::detail::EmulatedWirelessInterfaceTransmitFilter::request()
37 if (iface_.basei::interface().modulationParameterIds().empty())
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();
51 prefix_ void senf::emu::detail::EmulatedWirelessInterfaceReceiveFilter::request()
56 if (iface_.basei::interface().frequency() != p->frequency() ||
57 iface_.basei::interface().bandwidth() != p->bandwidth())
return;
62 if (! senf::contains(iface_.basei::interface().modulationParameterIds(), p->modulationId())) {
66 p.annotation<annotations::WirelessModulation>().
id = p->modulationId();
67 if (! iface_.v_emulatedWirelessQuality(n, p.annotation<annotations::Quality>()))
80 namespace l = boost::lambda;
81 using boost::lambda::_1;
83 checkCollisionOk(frequency, bandwidth);
86 entries_.get<ByFrequency>().find(boost::make_tuple(frequency,bandwidth)));
87 if (i == entries_.end()) {
88 Entry e (frequency, bandwidth);
94 i = entries_.insert(e).first;
96 users_.insert(User(i, interfaceId, cb));
103 if (! server_ && group_)
109 namespace l = boost::lambda;
110 using boost::lambda::_1;
114 "senf::emu::EmulatedFrequencyRegistry::release(): " 115 "No registration for interface" );
117 if (i->entry->nUsers > 0 && running_) {
123 entries_.get<ByFrequency>().erase(i->entry);
131 prefix_ senf::emu::EmulatedFrequencyRegistry::EmulatedFrequencyRegistry()
132 : socket_ (), group_ (
"239.202.104.1:4701"), server_ (),
133 schedulerStart_ (
"senf::emu::EmulatedFrequencyRegistry::schedulerStart",
136 entries_ (), users_ (), running_ (
false)
138 namespace fty = console::factory;
140 console::sysdir().add(
"emu", dir_);
142 dir_.
add(
"consoleGroup",
145 dir_.
add(
"consoleGroup",
149 typedef std::pair<INet4Network, unsigned> AddressPair;
150 dir_.
add(
"addressRange",
153 dir_.
add(
"addressRange",
157 dir_.
add(
"list", fty::Command(&EmulatedFrequencyRegistry::consoleList,
this));
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));
175 server_->root(dir_[
"ipc"]).emptyReplies(
false);
179 prefix_ void senf::emu::EmulatedFrequencyRegistry::consoleList(std::ostream & os)
182 boost::format fmt (
"%10d %10d %-21s%5d %10d ");
183 os << fmt %
"FREQUENCY" %
"BANDWIDTH" %
"ADDRESS" %
"NODES" %
"OWNER" <<
" USERS\n";
185 for (EntriesRange::iterator i (e.begin()); i != e.end(); ++i) {
193 for (UsersRange::iterator j (u.begin()); j != u.end(); ++j)
197 os << (running_ ?
" running\n" :
" halted\n");
200 prefix_ void senf::emu::EmulatedFrequencyRegistry::add(
unsigned nodeId,
unsigned frequency,
202 UDPClientHandle::Address address)
204 namespace l = boost::lambda;
205 using boost::lambda::_1;
211 entries_.get<ByFrequency>().find(boost::make_tuple(frequency,bandwidth)));
214 if (fi != entries_.get<ByFrequency>().end()
215 && ai != entries_.get<ByAddress>().end()
218 if (nodeId < fi->ownerNodeId)
223 if (ai != entries_.get<ByAddress>().end()) {
228 if (nodeId < ai->ownerNodeId) {
229 UDPClientHandle::Address newAddr;
233 newAddr = getAddress();
236 entries_.get<ByAddress>().modify_key(ai, _1 = newAddr);
243 if (fi != entries_.get<ByFrequency>().end()) {
246 if (! fi->address || (fi->address != address && nodeId <= fi->ownerNodeId)) {
247 entries_.get<ByFrequency>().modify(
253 entries_.insert(
Entry(frequency, bandwidth, address, 0, nodeId));
256 prefix_ void senf::emu::EmulatedFrequencyRegistry::del(
unsigned nodeId,
unsigned frequency,
259 namespace l = boost::lambda;
260 using boost::lambda::_1;
266 entries_.get<ByFrequency>().find(boost::make_tuple(frequency,bandwidth)));
267 if (i == entries_.get<ByFrequency>().end())
270 if (nodeId != i->ownerNodeId)
272 if (users_.get<ByEntry>().count(i) > 0) {
274 "Active entry " << frequency <<
"," << bandwidth <<
275 " removed by " << nodeId));
276 entries_.get<ByFrequency>().modify(
282 entries_.get<ByFrequency>().erase(i);
285 prefix_ void senf::emu::EmulatedFrequencyRegistry::join(
unsigned nodeId,
unsigned frequency,
288 namespace l = boost::lambda;
289 using boost::lambda::_1;
295 entries_.get<ByFrequency>().find(boost::make_tuple(frequency,bandwidth)));
296 if (i == entries_.end()) {
299 i = entries_.insert(
Entry(frequency, bandwidth, UDPClientHandle::Address(), 1, 0)).first;
306 prefix_ void senf::emu::EmulatedFrequencyRegistry::leave(
unsigned nodeId,
unsigned frequency,
309 namespace l = boost::lambda;
310 using boost::lambda::_1;
316 entries_.get<ByFrequency>().find(boost::make_tuple(frequency,bandwidth)));
317 if (i == entries_.end())
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 <<
329 entries_.get<ByFrequency>().modify(
338 entries_.get<ByFrequency>().erase(i);
343 prefix_ int senf::emu::EmulatedFrequencyRegistry::poll(
unsigned nodeId,
unsigned frequency,
350 entries_.get<ByFrequency>().find(boost::make_tuple(frequency,bandwidth)));
351 if (i == entries_.end())
354 users_.get<ByEntry>().equal_range(i));
355 return std::distance(e.first, e.second);
360 namespace l = boost::lambda;
361 using boost::lambda::_1;
363 if (! server_ && group_)
368 for (Entries::iterator i (entries_.begin()), i_end (entries_.end()); i != i_end; ++i) {
369 unsigned users (users_.get<ByEntry>().count(i));
371 if (! i->ownerNodeId && ! i->address) {
389 namespace l = boost::lambda;
390 using boost::lambda::_1;
395 if (entries_.empty()) {
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(),
407 if (users_.get<ByEntry>().count(i) == 0)
415 prefix_ void senf::emu::EmulatedFrequencyRegistry::sendAdd(
unsigned nodeId,
unsigned frequency,
417 UDPClientHandle::Address address)
419 socket_.writeto(group_, (boost::format(
"add %d %d %d %s")
420 % nodeId % frequency % bandwidth % address).
str());
423 prefix_ void senf::emu::EmulatedFrequencyRegistry::sendDel(
unsigned nodeId,
unsigned frequency,
426 socket_.writeto(group_, (boost::format(
"del %d %d %d")
427 % nodeId % frequency % bandwidth).
str());
430 prefix_ void senf::emu::EmulatedFrequencyRegistry::sendJoin(
unsigned nodeId,
434 socket_.writeto(group_, (boost::format(
"join %d %d %d")
435 % nodeId % frequency % bandwidth).
str());
438 prefix_ void senf::emu::EmulatedFrequencyRegistry::sendLeave(
unsigned nodeId,
442 socket_.writeto(group_, (boost::format(
"leave %d %d %d")
443 % nodeId % frequency % bandwidth).
str());
446 prefix_ void senf::emu::EmulatedFrequencyRegistry::sendPoll(
unsigned nodeId,
450 socket_.writeto(group_, (boost::format(
"poll %d %d %d")
451 % nodeId % frequency % bandwidth).
str());
454 prefix_ senf::emu::UDPClientHandle::Address senf::emu::EmulatedFrequencyRegistry::getAddress()
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())
465 return UDPClientHandle::Address();
468 prefix_ void senf::emu::EmulatedFrequencyRegistry::updateAddress(
Entry const & entry)
471 boost::tie(i, i_end) = users_.get<ByEntry>().equal_range(&entry);
472 for (; i != i_end; ++i)
478 inline bool frequencyOverlap(
unsigned f1,
unsigned b1,
unsigned f2,
unsigned b2)
480 return 2*f1-b1 <= 2*f2+b2 && 2*f2-b2 <= 2*f1+b1;
485 prefix_ void senf::emu::EmulatedFrequencyRegistry::checkCollisionOk(
unsigned frequency,
491 i_end (entries_.get<ByFrequency>().end()); i != i_end; ++i)
492 if (frequencyOverlap(frequency, bandwidth, i->frequency, i->bandwidth)) {
493 cb_(frequency, bandwidth);
510 Ranges const & bandwidths)
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);
521 namespace fty = console::factory;
522 interface().consoleDir()
523 .add(
"registerFrequency",
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" 532 "The statement will register all combinations of any frequency with any bandwidth.\n" 535 " registerFrequency 2412000 20000;\n" 536 " Register a single frequency/bandwidth combination.\n" 538 " registerFrequency 1000000:2000000 5000:20000;\n" 539 " Register a single frequency/bandwidth range combination.\n" 541 " registerFrequency (2412000 2417000 2422000) 20000;\n" 542 " Register 3 frequency/bandwidth combinations;\n" 544 " registerFrequency (1000000:2000000 3000000:4000000) (5000 10000:12000 20000);" 545 " Register 6 frequency/bandwidth combinations.") );
551 frequency_ = frequency;
552 bandwidth_ = bandwidth;
554 index_ = interface().index();
556 index_, frequency, bandwidth,
558 emulationAddress, (UDPClientHandle::Address
const &)));
573 namespace fty = console::factory;
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") );
591 if (!emui::interface().distanceCallback_) {
599 double d = emui::interface().distanceCallback_(ph->nodeId());
607 unsigned f = (*this).basei::interface().frequency();
613 double fsl = 20 * log10( 4*d*M_PI*f/3.0e2);
615 short rssi = short(ewph->txPower()-fsl);
617 if (rssiRandomnessRange_ != 0)
618 rssi += rand() % rssiRandomnessRange_;
620 if (rssi <= minRssi) {
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") );
633 int defaultNoiseValue = -110;
634 if (noiseRandomnessRange_ !=0)
635 defaultNoiseValue=defaultNoiseValue + (rand()%noiseRandomnessRange_);
639 quality.
noise = defaultNoiseValue;
643 quality.
flags.
frameCorrupt = (rand() % ((rssi-minRssi)*(rssi-minRssi))) > 1 ? false :
true;
654 for (Ranges::const_iterator i (powers.begin()), i_end (powers.end()); i != i_end; ++i)
655 registerTxPower(i->lower, i->upper);
662 namespace fty = console::factory;
664 basei::interface().consoleDir()
665 .add(
"registerTxPower",
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" 672 " registerTxPower 4;\n" 673 " Register single txpower value\n\n" 674 " registerTxPower (-4:-1 1:10);\n" 675 " Register two txpower ranges\n") );
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's using a channel.
unsigned frameRetransmitted
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.
short minRssi
Minimum RSSI value.
UDPClientHandle::Address consoleGroup() const
Get control channel multicast group/port.
UDPClientHandle::Address address
Assigned multicast address.
Wireless spectrum management.
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()
Channel allocation entry.
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.
unsigned ownerNodeId
Channel master.
ConcretePacket< EmulatedWirelessPacketHeaderType > EmulatedWirelessPacketHeader
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.
void release(unsigned interfaceId)
Release channel registration.
unsigned prefix_len() const
UsersRange users(EntriesRange::iterator i) const
Get interface id's of local users of a given channel.
static ModulationParameterRegistry & instance()
void stop()
Stop multicast address/port allocation.
void emulatedCoverageRange(unsigned distance)
INet4Address host(boost::uint32_t number)
boost::function< void(UDPClientHandle::Address const &address)> UserCallback
Callback type called to set channel address.
EmulatedWirelessInterface public header.
EntriesRange entries() const
Get all channel entries.
NodeType & add(std::string const &name, boost::shared_ptr< NodeType > node)
~EmulatedWirelessInterface()