|
INET Framework for OMNeT++/OMNEST
|
00001 // 00002 // Copyright (C) 2006 Andras Varga, Levente Meszaros 00003 // Based on the Mobility Framework's SnrEval by Marc Loebbers 00004 // 00005 // This program is free software; you can redistribute it and/or 00006 // modify it under the terms of the GNU Lesser General Public License 00007 // as published by the Free Software Foundation; either version 2 00008 // of the License, or (at your option) any later version. 00009 // 00010 // This program is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU Lesser General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU Lesser General Public License 00016 // along with this program; if not, see <http://www.gnu.org/licenses/>. 00017 // 00018 00019 00020 #include "AbstractRadio.h" 00021 #include "FWMath.h" 00022 #include "PhyControlInfo_m.h" 00023 #include "Ieee80211Consts.h" //XXX for the COLLISION and BITERROR msg kind constants 00024 00025 00026 #define MK_TRANSMISSION_OVER 1 00027 #define MK_RECEPTION_COMPLETE 2 00028 00029 00030 AbstractRadio::AbstractRadio() : rs(this->getId()) 00031 { 00032 radioModel = NULL; 00033 receptionModel = NULL; 00034 } 00035 00036 void AbstractRadio::initialize(int stage) 00037 { 00038 ChannelAccess::initialize(stage); 00039 00040 EV << "Initializing AbstractRadio, stage=" << stage << endl; 00041 00042 if (stage == 0) 00043 { 00044 gate("radioIn")->setDeliverOnReceptionStart(true); 00045 00046 uppergateIn = findGate("uppergateIn"); 00047 uppergateOut = findGate("uppergateOut"); 00048 00049 // read parameters 00050 transmitterPower = par("transmitterPower"); 00051 if (transmitterPower > (double) (cc->par("pMax"))) 00052 error("transmitterPower cannot be bigger than pMax in ChannelControl!"); 00053 rs.setBitrate(par("bitrate")); 00054 rs.setChannelNumber(par("channelNumber")); 00055 thermalNoise = FWMath::dBm2mW(par("thermalNoise")); 00056 carrierFrequency = cc->par("carrierFrequency"); // taken from ChannelControl 00057 sensitivity = FWMath::dBm2mW(par("sensitivity")); 00058 00059 // initialize noiseLevel 00060 noiseLevel = thermalNoise; 00061 00062 EV << "Initialized channel with noise: " << noiseLevel << " sensitivity: " << sensitivity << 00063 endl; 00064 00065 // initialize the pointer of the snrInfo with NULL to indicate 00066 // that currently no message is received 00067 snrInfo.ptr = NULL; 00068 00069 // no channel switch pending 00070 newChannel = -1; 00071 00072 // Initialize radio state. If thermal noise is already to high, radio 00073 // state has to be initialized as RECV 00074 rs.setState(RadioState::IDLE); 00075 if (noiseLevel >= sensitivity) 00076 rs.setState(RadioState::RECV); 00077 00078 WATCH(noiseLevel); 00079 WATCH(rs); 00080 00081 receptionModel = createReceptionModel(); 00082 receptionModel->initializeFrom(this); 00083 00084 radioModel = createRadioModel(); 00085 radioModel->initializeFrom(this); 00086 } 00087 else if (stage == 1) 00088 { 00089 // tell initial values to MAC; must be done in stage 1, because they 00090 // subscribe in stage 0 00091 nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); 00092 nb->fireChangeNotification(NF_RADIO_CHANNEL_CHANGED, &rs); 00093 } 00094 else if (stage == 2) 00095 { 00096 // tell initial channel number to ChannelControl; should be done in 00097 // stage==2 or later, because base class initializes myHostRef in that stage 00098 cc->updateHostChannel(myHostRef, rs.getChannelNumber()); 00099 } 00100 } 00101 00102 void AbstractRadio::finish() 00103 { 00104 } 00105 00106 AbstractRadio::~AbstractRadio() 00107 { 00108 delete radioModel; 00109 delete receptionModel; 00110 00111 // delete messages being received 00112 for (RecvBuff::iterator it = recvBuff.begin(); it!=recvBuff.end(); ++it) 00113 delete it->first; 00114 } 00115 00131 void AbstractRadio::handleMessage(cMessage *msg) 00132 { 00133 // handle commands 00134 if (msg->getArrivalGateId()==uppergateIn && !msg->isPacket() /*FIXME XXX ENSURE REALLY PLAIN cMessage ARE SENT AS COMMANDS!!! && msg->getBitLength()==0*/) 00135 { 00136 cPolymorphic *ctrl = msg->removeControlInfo(); 00137 if (msg->getKind()==0) 00138 error("Message '%s' with length==0 is supposed to be a command, but msg kind is also zero", msg->getName()); 00139 handleCommand(msg->getKind(), ctrl); 00140 delete msg; 00141 return; 00142 } 00143 00144 if (msg->getArrivalGateId() == uppergateIn) 00145 { 00146 AirFrame *airframe = encapsulatePacket(PK(msg)); 00147 handleUpperMsg(airframe); 00148 } 00149 else if (msg->isSelfMessage()) 00150 { 00151 handleSelfMsg(msg); 00152 } 00153 else if (check_and_cast<AirFrame *>(msg)->getChannelNumber() == getChannelNumber()) 00154 { 00155 // must be an AirFrame 00156 AirFrame *airframe = (AirFrame *) msg; 00157 handleLowerMsgStart(airframe); 00158 bufferMsg(airframe); 00159 } 00160 else 00161 { 00162 EV << "listening to different channel when receiving message -- dropping it\n"; 00163 delete msg; 00164 } 00165 } 00166 00173 void AbstractRadio::bufferMsg(AirFrame *airframe) //FIXME: add explicit simtime_t atTime arg? 00174 { 00175 // set timer to indicate transmission is complete 00176 cMessage *endRxTimer = new cMessage("endRx", MK_RECEPTION_COMPLETE); 00177 endRxTimer->setContextPointer(airframe); 00178 airframe->setContextPointer(endRxTimer); 00179 00180 // NOTE: use arrivalTime instead of simTime, because we might be calling this 00181 // function during a channel change, when we're picking up ongoing transmissions 00182 // on the channel -- and then the message's arrival time is in the past! 00183 scheduleAt(airframe->getArrivalTime() + airframe->getDuration(), endRxTimer); 00184 } 00185 00186 AirFrame *AbstractRadio::encapsulatePacket(cPacket *frame) 00187 { 00188 PhyControlInfo *ctrl = dynamic_cast<PhyControlInfo *>(frame->removeControlInfo()); 00189 ASSERT(!ctrl || ctrl->getChannelNumber()==-1); // per-packet channel switching not supported 00190 00191 // Note: we don't set length() of the AirFrame, because duration will be used everywhere instead 00192 AirFrame *airframe = createAirFrame(); 00193 airframe->setName(frame->getName()); 00194 airframe->setPSend(transmitterPower); 00195 airframe->setChannelNumber(getChannelNumber()); 00196 airframe->encapsulate(frame); 00197 airframe->setBitrate(ctrl ? ctrl->getBitrate() : rs.getBitrate()); 00198 airframe->setDuration(radioModel->calculateDuration(airframe)); 00199 airframe->setSenderPos(getMyPosition()); 00200 delete ctrl; 00201 00202 EV << "Frame (" << frame->getClassName() << ")" << frame->getName() 00203 << " will be transmitted at " << (airframe->getBitrate()/1e6) << "Mbps\n"; 00204 return airframe; 00205 } 00206 00207 void AbstractRadio::sendUp(AirFrame *airframe) 00208 { 00209 cPacket *frame = airframe->decapsulate(); 00210 delete airframe; 00211 EV << "sending up frame " << frame->getName() << endl; 00212 send(frame, uppergateOut); 00213 } 00214 00215 void AbstractRadio::sendDown(AirFrame *airframe) 00216 { 00217 sendToChannel(airframe); 00218 } 00219 00224 AirFrame *AbstractRadio::unbufferMsg(cMessage *msg) 00225 { 00226 AirFrame *airframe = (AirFrame *) msg->getContextPointer(); 00227 //delete the self message 00228 delete msg; 00229 00230 return airframe; 00231 } 00232 00243 void AbstractRadio::handleUpperMsg(AirFrame *airframe) 00244 { 00245 if (rs.getState() == RadioState::TRANSMIT) 00246 error("Trying to send a message while already transmitting -- MAC should " 00247 "take care this does not happen"); 00248 00249 // if a packet was being received, it is corrupted now as should be treated as noise 00250 if (snrInfo.ptr != NULL) 00251 { 00252 EV << "Sending a message while receiving another. The received one is now corrupted.\n"; 00253 00254 // remove the snr information stored for the message currently being 00255 // received. This message is treated as noise now and the 00256 // receive power has to be added to the noiseLevel 00257 00258 // delete the pointer to indicate that no message is being received 00259 snrInfo.ptr = NULL; 00260 // clear the snr list 00261 snrInfo.sList.clear(); 00262 // add the receive power to the noise level 00263 noiseLevel += snrInfo.rcvdPower; 00264 } 00265 00266 // now we are done with all the exception handling and can take care 00267 // about the "real" stuff 00268 00269 // change radio status 00270 EV << "sending, changing RadioState to TRANSMIT\n"; 00271 setRadioState(RadioState::TRANSMIT); 00272 00273 cMessage *timer = new cMessage(NULL, MK_TRANSMISSION_OVER); 00274 scheduleAt(simTime() + airframe->getDuration(), timer); 00275 sendDown(airframe); 00276 } 00277 00278 void AbstractRadio::handleCommand(int msgkind, cPolymorphic *ctrl) 00279 { 00280 if (msgkind==PHY_C_CONFIGURERADIO) 00281 { 00282 // extract new channel number 00283 PhyControlInfo *phyCtrl = check_and_cast<PhyControlInfo *>(ctrl); 00284 int newChannel = phyCtrl->getChannelNumber(); 00285 double newBitrate = phyCtrl->getBitrate(); 00286 delete ctrl; 00287 00288 if (newChannel!=-1) 00289 { 00290 EV << "Command received: change to channel #" << newChannel << "\n"; 00291 00292 // do it 00293 if (rs.getChannelNumber()==newChannel) 00294 EV << "Right on that channel, nothing to do\n"; // fine, nothing to do 00295 else if (rs.getState()==RadioState::TRANSMIT) { 00296 EV << "We're transmitting right now, remembering to change after it's completed\n"; 00297 this->newChannel = newChannel; 00298 } else 00299 changeChannel(newChannel); // change channel right now 00300 } 00301 if (newBitrate!=-1) 00302 { 00303 EV << "Command received: change bitrate to " << (newBitrate/1e6) << "Mbps\n"; 00304 00305 // do it 00306 if (rs.getBitrate()==newBitrate) 00307 EV << "Right at that bitrate, nothing to do\n"; // fine, nothing to do 00308 else if (rs.getState()==RadioState::TRANSMIT) { 00309 EV << "We're transmitting right now, remembering to change after it's completed\n"; 00310 this->newBitrate = newBitrate; 00311 } else 00312 setBitrate(newBitrate); // change bitrate right now 00313 } 00314 } 00315 else 00316 { 00317 error("unknown command (msgkind=%d)", msgkind); 00318 } 00319 } 00320 00321 void AbstractRadio::handleSelfMsg(cMessage *msg) 00322 { 00323 if (msg->getKind()==MK_RECEPTION_COMPLETE) 00324 { 00325 EV << "frame is completely received now\n"; 00326 00327 // unbuffer the message 00328 AirFrame *airframe = unbufferMsg(msg); 00329 00330 handleLowerMsgEnd(airframe); 00331 } 00332 else if (msg->getKind() == MK_TRANSMISSION_OVER) 00333 { 00334 // Transmission has completed. The RadioState has to be changed 00335 // to IDLE or RECV, based on the noise level on the channel. 00336 // If the noise level is bigger than the sensitivity switch to receive mode, 00337 // otherwise to idle mode. 00338 if (noiseLevel < sensitivity) 00339 { 00340 // set the RadioState to IDLE 00341 EV << "transmission over, switch to idle mode (state:IDLE)\n"; 00342 setRadioState(RadioState::IDLE); 00343 } 00344 else 00345 { 00346 // set the RadioState to RECV 00347 EV << "transmission over but noise level too high, switch to recv mode (state:RECV)\n"; 00348 setRadioState(RadioState::RECV); 00349 } 00350 00351 // delete the timer 00352 delete msg; 00353 00354 // switch channel if it needs be 00355 if (newChannel!=-1) 00356 { 00357 changeChannel(newChannel); 00358 newChannel = -1; 00359 } 00360 } 00361 else 00362 { 00363 error("Internal error: unknown self-message `%s'", msg->getName()); 00364 } 00365 } 00366 00367 00391 void AbstractRadio::handleLowerMsgStart(AirFrame * airframe) 00392 { 00393 // Calculate the receive power of the message 00394 00395 // calculate distance 00396 const Coord& myPos = getMyPosition(); 00397 const Coord& framePos = airframe->getSenderPos(); 00398 double distance = myPos.distance(framePos); 00399 00400 // calculate receive power 00401 double rcvdPower = receptionModel->calculateReceivedPower(airframe->getPSend(), carrierFrequency, distance); 00402 00403 // store the receive power in the recvBuff 00404 recvBuff[airframe] = rcvdPower; 00405 00406 // if receive power is bigger than sensitivity and if not sending 00407 // and currently not receiving another message and the message has 00408 // arrived in time 00409 // NOTE: a message may have arrival time in the past here when we are 00410 // processing ongoing transmissions during a channel change 00411 if (airframe->getArrivalTime() == simTime() && rcvdPower >= sensitivity && rs.getState() != RadioState::TRANSMIT && snrInfo.ptr == NULL) 00412 { 00413 EV << "receiving frame " << airframe->getName() << endl; 00414 00415 // Put frame and related SnrList in receive buffer 00416 SnrList snrList; 00417 snrInfo.ptr = airframe; 00418 snrInfo.rcvdPower = rcvdPower; 00419 snrInfo.sList = snrList; 00420 00421 // add initial snr value 00422 addNewSnr(); 00423 00424 if (rs.getState() != RadioState::RECV) 00425 { 00426 // publish new RadioState 00427 EV << "publish new RadioState:RECV\n"; 00428 setRadioState(RadioState::RECV); 00429 } 00430 } 00431 // receive power is too low or another message is being sent or received 00432 else 00433 { 00434 EV << "frame " << airframe->getName() << " is just noise\n"; 00435 //add receive power to the noise level 00436 noiseLevel += rcvdPower; 00437 00438 // if a message is being received add a new snr value 00439 if (snrInfo.ptr != NULL) 00440 { 00441 // update snr info for currently being received message 00442 EV << "adding new snr value to snr list of message being received\n"; 00443 addNewSnr(); 00444 } 00445 00446 // update the RadioState if the noiseLevel exceeded the threshold 00447 // and the radio is currently not in receive or in send mode 00448 if (noiseLevel >= sensitivity && rs.getState() == RadioState::IDLE) 00449 { 00450 EV << "setting radio state to RECV\n"; 00451 setRadioState(RadioState::RECV); 00452 } 00453 } 00454 } 00455 00456 00467 void AbstractRadio::handleLowerMsgEnd(AirFrame * airframe) 00468 { 00469 // check if message has to be send to the decider 00470 if (snrInfo.ptr == airframe) 00471 { 00472 EV << "reception of frame over, preparing to send packet to upper layer\n"; 00473 // get Packet and list out of the receive buffer: 00474 SnrList list; 00475 list = snrInfo.sList; 00476 00477 // delete the pointer to indicate that no message is currently 00478 // being received and clear the list 00479 snrInfo.ptr = NULL; 00480 snrInfo.sList.clear(); 00481 00482 // delete the frame from the recvBuff 00483 recvBuff.erase(airframe); 00484 00485 //XXX send up the frame: 00486 //if (radioModel->isReceivedCorrectly(airframe, list)) 00487 // sendUp(airframe); 00488 //else 00489 // delete airframe; 00490 if (!radioModel->isReceivedCorrectly(airframe, list)) 00491 { 00492 airframe->getEncapsulatedPacket()->setKind(list.size()>1 ? COLLISION : BITERROR); 00493 airframe->setName(list.size()>1 ? "COLLISION" : "BITERROR"); 00494 } 00495 sendUp(airframe); 00496 } 00497 // all other messages are noise 00498 else 00499 { 00500 EV << "reception of noise message over, removing recvdPower from noiseLevel....\n"; 00501 // get the rcvdPower and subtract it from the noiseLevel 00502 noiseLevel -= recvBuff[airframe]; 00503 00504 // delete message from the recvBuff 00505 recvBuff.erase(airframe); 00506 00507 // update snr info for message currently being received if any 00508 if (snrInfo.ptr != NULL) 00509 { 00510 addNewSnr(); 00511 } 00512 00513 // message should be deleted 00514 delete airframe; 00515 EV << "message deleted\n"; 00516 } 00517 00518 // check the RadioState and update if necessary 00519 // change to idle if noiseLevel smaller than threshold and state was 00520 // not idle before 00521 // do not change state if currently sending or receiving a message!!! 00522 if (noiseLevel < sensitivity && rs.getState() == RadioState::RECV && snrInfo.ptr == NULL) 00523 { 00524 // publish the new RadioState: 00525 EV << "new RadioState is IDLE\n"; 00526 setRadioState(RadioState::IDLE); 00527 } 00528 } 00529 00530 void AbstractRadio::addNewSnr() 00531 { 00532 SnrListEntry listEntry; // create a new entry 00533 listEntry.time = simTime(); 00534 listEntry.snr = snrInfo.rcvdPower / noiseLevel; 00535 snrInfo.sList.push_back(listEntry); 00536 } 00537 00538 void AbstractRadio::changeChannel(int channel) 00539 { 00540 if (channel == rs.getChannelNumber()) 00541 return; 00542 if (channel < 0 || channel >= cc->getNumChannels()) 00543 error("changeChannel(): channel number %d is out of range (hint: numChannels is a parameter of ChannelControl)", channel); 00544 if (rs.getState() == RadioState::TRANSMIT) 00545 error("changing channel while transmitting is not allowed"); 00546 00547 // if we are currently receiving, must clean that up before moving to different channel 00548 if (rs.getState() == RadioState::RECV) 00549 { 00550 // delete messages being received, and cancel associated self-messages 00551 for (RecvBuff::iterator it = recvBuff.begin(); it!=recvBuff.end(); ++it) 00552 { 00553 AirFrame *airframe = it->first; 00554 cMessage *endRxTimer = (cMessage *)airframe->getContextPointer(); 00555 delete airframe; 00556 delete cancelEvent(endRxTimer); 00557 } 00558 recvBuff.clear(); 00559 } 00560 00561 // clear snr info 00562 snrInfo.ptr = NULL; 00563 snrInfo.sList.clear(); 00564 00565 // do channel switch 00566 EV << "Changing to channel #" << channel << "\n"; 00567 00568 rs.setChannelNumber(channel); 00569 cc->updateHostChannel(myHostRef, channel); 00570 ChannelControl::TransmissionList tl = cc->getOngoingTransmissions(channel); 00571 00572 cModule *myHost = findHost(); 00573 cGate *radioGate = myHost->gate("radioIn"); 00574 00575 // pick up ongoing transmissions on the new channel 00576 EV << "Picking up ongoing transmissions on new channel:\n"; 00577 for (ChannelControl::TransmissionList::const_iterator it = tl.begin(); it != tl.end(); ++it) 00578 { 00579 AirFrame *airframe = *it; 00580 // time for the message to reach us 00581 double distance = myHostRef->pos.distance(airframe->getSenderPos()); 00582 simtime_t propagationDelay = distance / LIGHT_SPEED; 00583 00584 // if this transmission is on our new channel and it would reach us in the future, then schedule it 00585 if (channel == airframe->getChannelNumber()) 00586 { 00587 EV << " - (" << airframe->getClassName() << ")" << airframe->getName() << ": "; 00588 00589 // if there is a message on the air which will reach us in the future 00590 if (airframe->getTimestamp() + propagationDelay >= simTime()) 00591 { 00592 EV << "will arrive in the future, scheduling it\n"; 00593 00594 // we need to send to each radioIn[] gate of this host 00595 for (int i = 0; i < radioGate->size(); i++) 00596 sendDirect(airframe->dup(), airframe->getTimestamp() + propagationDelay - simTime(), airframe->getDuration(), myHost, radioGate->getId() + i); 00597 } 00598 // if we hear some part of the message 00599 else if (airframe->getTimestamp() + airframe->getDuration() + propagationDelay > simTime()) 00600 { 00601 EV << "missed beginning of frame, processing it as noise\n"; 00602 00603 AirFrame *frameDup = airframe->dup(); 00604 frameDup->setArrivalTime(airframe->getTimestamp() + propagationDelay); 00605 handleLowerMsgStart(frameDup); 00606 bufferMsg(frameDup); 00607 } 00608 else 00609 { 00610 EV << "in the past\n"; 00611 } 00612 } 00613 } 00614 00615 // notify other modules about the channel switch; and actually, radio state has changed too 00616 nb->fireChangeNotification(NF_RADIO_CHANNEL_CHANGED, &rs); 00617 nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); 00618 } 00619 00620 void AbstractRadio::setBitrate(double bitrate) 00621 { 00622 if (rs.getBitrate() == bitrate) 00623 return; 00624 if (bitrate < 0) 00625 error("setBitrate(): bitrate cannot be negative (%g)", bitrate); 00626 if (rs.getState() == RadioState::TRANSMIT) 00627 error("changing the bitrate while transmitting is not allowed"); 00628 00629 EV << "Setting bitrate to " << (bitrate/1e6) << "Mbps\n"; 00630 rs.setBitrate(bitrate); 00631 00632 //XXX fire some notification? 00633 } 00634 00635 void AbstractRadio::setRadioState(RadioState::State newState) 00636 { 00637 rs.setState(newState); 00638 nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); 00639 } 00640