|
INET Framework for OMNeT++/OMNEST
|
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