INET Framework for OMNeT++/OMNEST
ChannelControl.cc
Go to the documentation of this file.
00001 /***************************************************************************
00002  * file:        ChannelControl.cc
00003  *
00004  * copyright:   (C) 2005 Andras Varga
00005  *
00006  *              This program is free software; you can redistribute it
00007  *              and/or modify it under the terms of the GNU General Public
00008  *              License as published by the Free Software Foundation; either
00009  *              version 2 of the License, or (at your option) any later
00010  *              version.
00011  *              For further information see file COPYING
00012  *              in the top level directory
00013  ***************************************************************************
00014  * part of:     framework implementation developed by tkn
00015  **************************************************************************/
00016 
00017 
00018 #include "ChannelControl.h"
00019 #include "FWMath.h"
00020 #include <cassert>
00021 
00022 
00023 #define coreEV (ev.isDisabled()||!coreDebug) ? ev : ev << "ChannelControl: "
00024 
00025 Define_Module(ChannelControl);
00026 
00027 
00028 std::ostream& operator<<(std::ostream& os, const ChannelControl::HostEntry& h)
00029 {
00030     os << h.host->getFullPath() << " (x=" << h.pos.x << ",y=" << h.pos.y << "), "
00031        << h.neighbors.size() << " neighbor(s)";
00032     return os;
00033 }
00034 
00035 std::ostream& operator<<(std::ostream& os, const ChannelControl::TransmissionList& tl)
00036 {
00037     for (ChannelControl::TransmissionList::const_iterator it = tl.begin(); it != tl.end(); ++it)
00038         os << endl << *it;
00039     return os;
00040 }
00041 
00042 ChannelControl::ChannelControl()
00043 {
00044 }
00045 
00046 ChannelControl::~ChannelControl()
00047 {
00048     for (unsigned int i = 0; i < transmissions.size(); i++)
00049         for (TransmissionList::iterator it = transmissions[i].begin(); it != transmissions[i].end(); it++)
00050             delete *it;
00051 }
00052 
00053 ChannelControl *ChannelControl::get()
00054 {
00055     ChannelControl *cc = dynamic_cast<ChannelControl *>(simulation.getModuleByPath("channelcontrol"));
00056     if (!cc)
00057         cc = dynamic_cast<ChannelControl *>(simulation.getModuleByPath("channelControl"));
00058     if (!cc)
00059         throw cRuntimeError("Could not find ChannelControl module");
00060     return cc;
00061 }
00062 
00069 void ChannelControl::initialize()
00070 {
00071     coreDebug = hasPar("coreDebug") ? (bool) par("coreDebug") : false;
00072 
00073     coreEV << "initializing ChannelControl\n";
00074 
00075     playgroundSize.x = par("playgroundSizeX");
00076     playgroundSize.y = par("playgroundSizeY");
00077 
00078     numChannels = par("numChannels");
00079     transmissions.resize(numChannels);
00080 
00081     lastOngoingTransmissionsUpdate = 0;
00082 
00083     maxInterferenceDistance = calcInterfDist();
00084 
00085     WATCH(maxInterferenceDistance);
00086     WATCH_LIST(hosts);
00087     WATCH_VECTOR(transmissions);
00088 
00089     updateDisplayString(getParentModule());
00090 }
00091 
00096 void ChannelControl::updateDisplayString(cModule *playgroundMod)
00097 {
00098     cDisplayString& d = playgroundMod->getDisplayString();
00099     d.setTagArg("bgp", 0, 0L);
00100     d.setTagArg("bgp", 1, 0L);
00101     d.setTagArg("bgb", 0, (long) playgroundSize.x);
00102     d.setTagArg("bgb", 1, (long) playgroundSize.y);
00103 }
00104 
00113 double ChannelControl::calcInterfDist()
00114 {
00115     double SPEED_OF_LIGHT = 300000000.0;
00116     double interfDistance;
00117 
00118     //the carrier frequency used
00119     double carrierFrequency = par("carrierFrequency");
00120     //maximum transmission power possible
00121     double pMax = par("pMax");
00122     //signal attenuation threshold
00123     double sat = par("sat");
00124     //path loss coefficient
00125     double alpha = par("alpha");
00126 
00127     double waveLength = (SPEED_OF_LIGHT / carrierFrequency);
00128     //minimum power level to be able to physically receive a signal
00129     double minReceivePower = pow(10.0, sat / 10.0);
00130 
00131     interfDistance = pow(waveLength * waveLength * pMax /
00132                          (16.0 * M_PI * M_PI * minReceivePower), 1.0 / alpha);
00133 
00134     coreEV << "max interference distance:" << interfDistance << endl;
00135 
00136     return interfDistance;
00137 }
00138 
00139 ChannelControl::HostRef ChannelControl::registerHost(cModule *host, const Coord& initialPos, cGate *radioInGate)
00140 {
00141     Enter_Method_Silent();
00142     if (lookupHost(host) != NULL)
00143         error("ChannelControl::registerHost(): host (%s)%s already registered",
00144               host->getClassName(), host->getFullPath().c_str());
00145     if (!radioInGate)
00146         radioInGate = host->gate("radioIn"); // throws error if gate does not exist
00147 
00148     HostEntry he;
00149     he.host = host;
00150     he.radioInGate = radioInGate;
00151     he.pos = initialPos;
00152     he.isNeighborListValid = false;
00153     he.channel = 0;  // for now
00154     hosts.push_back(he);
00155     return &hosts.back(); // last element
00156 }
00157 
00158 ChannelControl::HostRef ChannelControl::lookupHost(cModule *host)
00159 {
00160     Enter_Method_Silent();
00161     for (HostList::iterator it = hosts.begin(); it != hosts.end(); it++)
00162         if (it->host == host)
00163             return &(*it);
00164     return 0;
00165 }
00166 
00167 const ChannelControl::HostRefVector& ChannelControl::getNeighbors(HostRef h)
00168 {
00169     Enter_Method_Silent();
00170     if (!h->isNeighborListValid)
00171     {
00172         h->neighborList.clear();
00173         for (std::set<HostRef>::const_iterator it = h->neighbors.begin(); it != h->neighbors.end(); it++)
00174             h->neighborList.push_back(*it);
00175         h->isNeighborListValid = true;
00176     }
00177     return h->neighborList;
00178 }
00179 
00180 void ChannelControl::updateConnections(HostRef h)
00181 {
00182     Coord& hpos = h->pos;
00183     double maxDistSquared = maxInterferenceDistance * maxInterferenceDistance;
00184     for (HostList::iterator it = hosts.begin(); it != hosts.end(); ++it)
00185     {
00186         HostEntry *hi = &(*it);
00187         if (hi == h)
00188             continue;
00189 
00190         // get the distance between the two hosts.
00191         // (omitting the square root (calling sqrdist() instead of distance()) saves about 5% CPU)
00192         bool inRange = hpos.sqrdist(hi->pos) < maxDistSquared;
00193 
00194         if (inRange)
00195         {
00196             // nodes within communication range: connect
00197             if (h->neighbors.insert(hi).second == true)
00198             {
00199                 hi->neighbors.insert(h);
00200                 h->isNeighborListValid = hi->isNeighborListValid = false;
00201             }
00202         }
00203         else
00204         {
00205             // out of range: disconnect
00206             if (h->neighbors.erase(hi))
00207             {
00208                 hi->neighbors.erase(h);
00209                 h->isNeighborListValid = hi->isNeighborListValid = false;
00210             }
00211         }
00212     }
00213 }
00214 
00215 void ChannelControl::checkChannel(const int channel)
00216 {
00217     if (channel >= numChannels || channel < 0)
00218         error("Invalid channel, must be between 0 and %d", numChannels);
00219 }
00220 
00221 void ChannelControl::updateHostPosition(HostRef h, const Coord& pos)
00222 {
00223     Enter_Method_Silent();
00224     h->pos = pos;
00225     updateConnections(h);
00226 }
00227 
00228 void ChannelControl::updateHostChannel(HostRef h, const int channel)
00229 {
00230     Enter_Method_Silent();
00231     checkChannel(channel);
00232 
00233     h->channel = channel;
00234 }
00235 
00236 const ChannelControl::TransmissionList& ChannelControl::getOngoingTransmissions(const int channel)
00237 {
00238     Enter_Method_Silent();
00239 
00240     checkChannel(channel);
00241     purgeOngoingTransmissions();
00242     return transmissions[channel];
00243 }
00244 
00245 void ChannelControl::addOngoingTransmission(HostRef h, AirFrame *frame)
00246 {
00247     Enter_Method_Silent();
00248 
00249     // we only keep track of ongoing transmissions so that we can support
00250     // NICs switching channels -- so there's no point doing it if there's only
00251     // one channel
00252     if (numChannels==1)
00253     {
00254         delete frame;
00255         return;
00256     }
00257 
00258     // purge old transmissions from time to time
00259     if (simTime() - lastOngoingTransmissionsUpdate > TRANSMISSION_PURGE_INTERVAL)
00260     {
00261         purgeOngoingTransmissions();
00262         lastOngoingTransmissionsUpdate = simTime();
00263     }
00264 
00265     // register ongoing transmission
00266     take(frame);
00267     frame->setTimestamp(); // store time of transmission start
00268     transmissions[frame->getChannelNumber()].push_back(frame);
00269 }
00270 
00271 void ChannelControl::purgeOngoingTransmissions()
00272 {
00273     for (int i = 0; i < numChannels; i++)
00274     {
00275         for (TransmissionList::iterator it = transmissions[i].begin(); it != transmissions[i].end();)
00276         {
00277             TransmissionList::iterator curr = it;
00278             AirFrame *frame = *it;
00279             it++;
00280 
00281             if (frame->getTimestamp() + frame->getDuration() + TRANSMISSION_PURGE_INTERVAL < simTime())
00282             {
00283                 delete frame;
00284                 transmissions[i].erase(curr);
00285             }
00286         }
00287     }
00288 }
00289 
00290 void ChannelControl::sendToChannel(cSimpleModule *srcRadioMod, HostRef srcHost, AirFrame *airFrame)
00291 {
00292     // NOTE: no Enter_Method()! We pretend this method is part of ChannelAccess
00293 
00294     // loop through all hosts in range
00295     const HostRefVector& neighbors = getNeighbors(srcHost);
00296     int n = neighbors.size();
00297     int channel = airFrame->getChannelNumber();
00298     for (int i=0; i<n; i++)
00299     {
00300         HostRef h = neighbors[i];
00301         if (h->channel == channel)
00302         {
00303             coreEV << "sending message to host listening on the same channel\n";
00304             // account for propagation delay, based on distance in meters
00305             // Over 300m, dt=1us=10 bit times @ 10Mbps
00306             simtime_t delay = srcHost->pos.distance(h->pos) / LIGHT_SPEED;
00307             srcRadioMod->sendDirect(airFrame->dup(), delay, airFrame->getDuration(), h->radioInGate);
00308         }
00309         else
00310             coreEV << "skipping host listening on a different channel\n";
00311     }
00312 
00313     // register transmission
00314     addOngoingTransmission(srcHost, airFrame);
00315 }
00316 
00317