INET Framework for OMNeT++/OMNEST
|
Keeps track of the different snir levels when receiving a packet. More...
#include <SnrEval.h>
Classes | |
struct | SnrStruct |
Struct to store a pointer to the message, rcvdPower AND a SnrList, needed in SnrEval::addNewSnr. More... | |
Public Member Functions | |
SnrEval () | |
virtual void | changeChannel (int channel) |
change transmitter and receiver to a new channel. This method throws an error if the radio state is transmit. Messages that are already sent to the new channel and would reach us in the future - thus they are on the air - will be received correctly. | |
virtual void | setBitrate (double bitrate) |
change the bitrate to the given value. This method throws an error if the radio state is transmit. | |
Protected Types | |
enum | { TRANSM_OVER } |
Enum to store self message getKind()s. More... | |
typedef std::map< AirFrame *, double > | RecvBuff |
Typedef used to store received messages together with receive power. | |
Protected Member Functions | |
virtual void | initialize (int) |
Initialize variables and publish the radio status. | |
virtual void | finish () |
virtual | ~SnrEval () |
virtual void | handleMessage (cMessage *msg) |
Called every time a message arrives. | |
virtual void | handleUpperMsg (AirFrame *) |
virtual void | handleSelfMsg (cMessage *) |
virtual void | handleCommand (int msgkind, cPolymorphic *ctrl) |
virtual void | handleLowerMsgStart (AirFrame *) |
Buffer the frame and update noise levels and snr information. | |
virtual void | handleLowerMsgEnd (AirFrame *) |
Unbuffer the frame and update noise levels and snr information. | |
virtual double | calcRcvdPower (double pSend, double distance) |
Calculates the power with which a packet is received. | |
virtual int | getChannelNumber () const |
virtual void | addNewSnr () |
updates the snr information of the relevant AirFrames | |
Protected Attributes | |
SnrStruct | snrInfo |
State: SnrInfo stores the snrList and the the recvdPower for the message currently being received, together with a pointer to the message. | |
RecvBuff | recvBuff |
State: A buffer to store a pointer to a message and the related receive power. | |
RadioState | rs |
State: the current RadioState of the NIC; includes channel number. | |
int | newChannel |
State: if not -1, we have to switch to that channel once we finished transmitting. | |
double | newBitrate |
State: if not -1, we have to switch to that bitrate once we finished transmitting. | |
double | noiseLevel |
State: the current noise level of the channel. | |
double | carrierFrequency |
Configuration: The carrier frequency used. It is read from the ChannelControl module. | |
double | thermalNoise |
Configuration: Thermal noise on the channel. Can be specified in omnetpp.ini. Default: -100 dBm. | |
double | sensitivity |
Configuration: Defines up to what Power level (in dBm) a message can be understood. If the level of a received packet is lower, it is only treated as noise. Can be specified in omnetpp.ini. Default: | |
double | pathLossAlpha |
Configuration: Path loss coefficient. Can be specified in omnetpp.ini. If not it is read from the ChannelControl module. This value CANNOT be smaller than the one specified in the ChannelControl module, or the simulation will exit with an error! |
Keeps track of the different snir levels when receiving a packet.
This module keeps track of the noise level of the channel.
When receiving a packet this module updates the noise level of the channel. Based on the receive power of the packet it is processed and handed to upper layers or just treated as noise.
After the packet is completely received the snir information is attached and it is handed to the decider module.
The snir information is a SnrList that lists all different snr levels together with the point of time (simTime()) when they started.
On top of that this module manages the RadioState, and posts notifications on NotificationBoard whenever it changes. The radio state gives information about whether this module is sending a packet, receiving a packet or idle. This information can be accessed via the NotificationBoard by other modules, e.g. a CSMAMacLayer.
typedef std::map<AirFrame*,double> SnrEval::RecvBuff [protected] |
Typedef used to store received messages together with receive power.
anonymous enum [protected] |
Enum to store self message getKind()s.
{ TRANSM_OVER };
SnrEval::SnrEval | ( | ) |
: rs(this->getId()) { }
SnrEval::~SnrEval | ( | ) | [protected, virtual] |
void SnrEval::addNewSnr | ( | ) | [protected, virtual] |
updates the snr information of the relevant AirFrames
The Snr information of the buffered message is updated.
Referenced by handleLowerMsgEnd(), GilbertElliotSnr::handleLowerMsgEnd(), handleLowerMsgStart(), and GilbertElliotSnr::handleLowerMsgStart().
{ SnrListEntry listEntry; // create a new entry listEntry.time = simTime(); listEntry.snr = snrInfo.rcvdPower / noiseLevel; snrInfo.sList.push_back(listEntry); }
double SnrEval::calcRcvdPower | ( | double | pSend, |
double | distance | ||
) | [protected, virtual] |
Calculates the power with which a packet is received.
This function simply calculates with how much power the signal arrives "here". If a different way of computing the path loss is required this function can be redefined.
Referenced by handleLowerMsgStart(), and GilbertElliotSnr::handleLowerMsgStart().
{ double speedOfLight = 300000000.0; double waveLength = speedOfLight / carrierFrequency; return (pSend * waveLength * waveLength / (16 * M_PI * M_PI * pow(distance, pathLossAlpha))); }
void SnrEval::changeChannel | ( | int | channel | ) | [virtual] |
change transmitter and receiver to a new channel. This method throws an error if the radio state is transmit. Messages that are already sent to the new channel and would reach us in the future - thus they are on the air - will be received correctly.
Referenced by handleCommand(), and handleSelfMsg().
{ if (channel == rs.getChannelNumber()) return; if (channel < 0 || channel >= cc->getNumChannels()) error("changeChannel(): channel number %d is out of range (hint: numChannels is a parameter of ChannelControl)", channel); if (rs.getState() == RadioState::TRANSMIT) error("changing channel while transmitting is not allowed"); // if we are currently receiving, must clean that up before moving to different channel if (rs.getState() == RadioState::RECV) { // delete messages being received, and cancel associated self-messages for (RecvBuff::iterator it = recvBuff.begin(); it!=recvBuff.end(); ++it) { AirFrame *frame = it->first; cMessage *endRxTimer = (cMessage *)frame->getContextPointer(); delete frame; delete cancelEvent(endRxTimer); } recvBuff.clear(); } // clear snr info snrInfo.ptr = NULL; snrInfo.sList.clear(); // do channel switch EV << "Changing channel to " << channel << "\n"; rs.setChannelNumber(channel); cc->updateHostChannel(myHostRef, channel); ChannelControl::TransmissionList tl = cc->getOngoingTransmissions(channel); // pick up ongoing transmissions on the new channel EV << "Picking up ongoing transmissions on new channel:\n"; for (ChannelControl::TransmissionList::const_iterator it = tl.begin(); it != tl.end(); ++it) { AirFrame *frame = *it; // time for the message to reach us double distance = myHostRef->pos.distance(frame->getSenderPos()); simtime_t propagationDelay = distance / LIGHT_SPEED; // if this transmission is on our new channel and it would reach us in the future, then schedule it if (channel == frame->getChannelNumber()) { EV << " - (" << frame->getClassName() << ")" << frame->getName() << ": "; // if there is a message on the air which will reach us in the future if (frame->getTimestamp() + propagationDelay >= simTime()) { EV << "will arrive in the future, scheduling it\n"; // we need to send to each radioIn[] gate cGate *radioGate = gate("radioIn"); for (int i = 0; i < radioGate->size(); i++) sendDirect((cMessage*)frame->dup(), frame->getTimestamp() + propagationDelay - simTime(), frame->getDuration(), this, radioGate->getId() + i); } // if we hear some part of the message else if (frame->getTimestamp() + frame->getDuration() + propagationDelay > simTime()) { EV << "missed beginning of frame, processing it as noise\n"; AirFrame *frameDup = (AirFrame*)frame->dup(); frameDup->setArrivalTime(frame->getTimestamp() + propagationDelay); handleLowerMsgStart(frameDup); bufferMsg(frameDup); } else { EV << "in the past\n"; } } } // notify other modules about the channel switch; and actually, radio state has changed too nb->fireChangeNotification(NF_RADIO_CHANNEL_CHANGED, &rs); nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); }
void SnrEval::finish | ( | ) | [protected, virtual] |
{ BasicSnrEval::finish(); }
virtual int SnrEval::getChannelNumber | ( | ) | const [inline, protected, virtual] |
void SnrEval::handleCommand | ( | int | msgkind, |
cPolymorphic * | ctrl | ||
) | [protected, virtual] |
Referenced by handleMessage().
{ if (msgkind==PHY_C_CONFIGURERADIO) { // extract new channel number PhyControlInfo *phyCtrl = check_and_cast<PhyControlInfo *>(ctrl); int newChannel = phyCtrl->getChannelNumber(); double newBitrate = phyCtrl->getBitrate(); delete ctrl; if (newChannel!=-1) { EV << "Command received: change to channel " << newChannel << "\n"; // do it if (rs.getChannelNumber()==newChannel) EV << "Right on that channel, nothing to do\n"; // fine, nothing to do else if (rs.getState()==RadioState::TRANSMIT) { EV << "We're transmitting right now, remembering to change after it's completed\n"; this->newChannel = newChannel; } else changeChannel(newChannel); // change channel right now } if (newBitrate!=-1) { EV << "Command received: change bitrate to " << (newBitrate/1e6) << "Mbps\n"; // do it if (rs.getBitrate()==newBitrate) EV << "Right at that bitrate, nothing to do\n"; // fine, nothing to do else if (rs.getState()==RadioState::TRANSMIT) { EV << "We're transmitting right now, remembering to change after it's completed\n"; this->newBitrate = newBitrate; } else setBitrate(newBitrate); // change bitrate right now } } else error("unknown command (msgkind=%d)", msgkind); }
void SnrEval::handleLowerMsgEnd | ( | AirFrame * | frame | ) | [protected, virtual] |
Unbuffer the frame and update noise levels and snr information.
This function is called right after the transmission is over, i.e. right after unbuffering. The noise level of the channel and the snr information of the buffered messages have to be updated.
Additionally the RadioState has to be updated.
If the corresponding AirFrame was not only noise the corresponding SnrList and the AirFrame are sent to the decider.
Reimplemented from BasicSnrEval.
Reimplemented in GilbertElliotSnr.
{ // check if message has to be send to the decider if (snrInfo.ptr == frame) { EV << "reception of frame over, preparing to send packet to upper layer\n"; // get Packet and list out of the receive buffer: SnrList list; list = snrInfo.sList; // delete the pointer to indicate that no message is currently // being received and clear the list snrInfo.ptr = NULL; snrInfo.sList.clear(); // delete the frame from the recvBuff recvBuff.erase(frame); //Don't forget to send: sendUp(frame, list); EV << "packet sent to the decider\n"; } // all other messages are noise else { EV << "reception of noise message over, removing recvdPower from noiseLevel....\n"; // get the rcvdPower and subtract it from the noiseLevel noiseLevel -= recvBuff[frame]; // delete message from the recvBuff recvBuff.erase(frame); // update snr info for message currently being received if any if (snrInfo.ptr != NULL) { addNewSnr(); } // message should be deleted delete frame; EV << "message deleted\n"; } // check the RadioState and update if necessary // change to idle if noiseLevel smaller than threshold and state was // not idle before // do not change state if currently sending or receiving a message!!! if (noiseLevel < sensitivity && rs.getState() == RadioState::RECV && snrInfo.ptr == NULL) { // publish the new RadioState: EV << "new RadioState is IDLE\n"; rs.setState(RadioState::IDLE); nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); } }
void SnrEval::handleLowerMsgStart | ( | AirFrame * | frame | ) | [protected, virtual] |
Buffer the frame and update noise levels and snr information.
This function is called right after a packet arrived, i.e. right before it is buffered for 'transmission time'.
First the receive power of the packet has to be calculated and is stored in the recvBuff. Afterwards it has to be decided whether the packet is just noise or a "real" packet that needs to be received.
The message is not treated as noise if all of the following conditions apply:
If all conditions apply a new SnrList is created and the RadioState is changed to RECV.
If the packet is just noise the receive power is added to the noise Level of the channel. Additionally the snr information of the currently being received message (if any) has to be updated as well as the RadioState.
Reimplemented from BasicSnrEval.
Reimplemented in GilbertElliotSnr.
Referenced by changeChannel().
{ // Calculate the receive power of the message // calculate distance const Coord& myPos = getMyPosition(); const Coord& framePos = frame->getSenderPos(); double distance = myPos.distance(framePos); // calculate receive power double rcvdPower = calcRcvdPower(frame->getPSend(), distance); // store the receive power in the recvBuff recvBuff[frame] = rcvdPower; // if receive power is bigger than sensitivity and if not sending // and currently not receiving another message and the message has // arrived in time // NOTE: a message may have arrival time in the past here when we are // processing ongoing transmissions during a channel change if (frame->getArrivalTime() == simTime() && rcvdPower >= sensitivity && rs.getState() != RadioState::TRANSMIT && snrInfo.ptr == NULL) { EV << "receiving frame " << frame->getName() << endl; // Put frame and related SnrList in receive buffer SnrList snrList; //defined in SnrList.h!! snrInfo.ptr = frame; snrInfo.rcvdPower = rcvdPower; snrInfo.sList = snrList; // add initial snr value addNewSnr(); if (rs.getState() != RadioState::RECV) { // publish new RadioState rs.setState(RadioState::RECV); EV << "publish new RadioState:RECV\n"; nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); } } // receive power is too low or another message is being sent or received else { EV << "frame " << frame->getName() << " is just noise\n"; //add receive power to the noise level noiseLevel += rcvdPower; // if a message is being received add a new snr value if (snrInfo.ptr != NULL) { // update snr info for currently being received message EV << "add new snr value to snr list of message being received\n"; addNewSnr(); } // update the RadioState if the noiseLevel exceeded the threshold // and the radio is currently not in receive or in send mode if (noiseLevel >= sensitivity && rs.getState() == RadioState::IDLE) { // publish new RadioState rs.setState(RadioState::RECV); EV << "publish new RadioState:RECV\n"; nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); } } }
void SnrEval::handleMessage | ( | cMessage * | msg | ) | [protected, virtual] |
Called every time a message arrives.
The basic handle message function.
Depending on the gate a message arrives handleMessage just calls different handle*Msg functions to further process the message.
Messages from the channel are also buffered here in order to simulate a transmission delay
You should not make any changes in this function but implement all your functionality into the handle*Msg functions called from here.
Reimplemented from BasicSnrEval.
{ if (msg->getArrivalGateId()==uppergateIn && !msg->isPacket()) { cPolymorphic *ctrl = msg->removeControlInfo(); handleCommand(msg->getKind(), ctrl); delete msg; } else { BasicSnrEval::handleMessage(msg); // let base class do it } }
void SnrEval::handleSelfMsg | ( | cMessage * | msg | ) | [protected, virtual] |
The only self message that can arrive is a timer to indicate that sending of a message is completed.
The RadioState has to be changed based on the noise level on the channel. If the noise level is bigger than the sensitivity switch to receive mode odtherwise to idle mode.
Reimplemented from BasicSnrEval.
Reimplemented in GilbertElliotSnr.
{ if (msg->getKind() == TRANSM_OVER) { if (noiseLevel < sensitivity) { // set the RadioState to IDLE rs.setState(RadioState::IDLE); EV << "transmission over, switch to idle mode (state:IDLE)\n"; nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); } else { // set the RadioState to RECV rs.setState(RadioState::RECV); EV << "transmission over but noise level too high, switch to recv mode (state:RECV)\n"; nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); } // delete the timer delete msg; // switch channel if it needs be if (newChannel!=-1) { changeChannel(newChannel); newChannel = -1; } } else error("Internal error: unknown self-message `%s'", msg->getName()); }
void SnrEval::handleUpperMsg | ( | AirFrame * | frame | ) | [protected, virtual] |
If a message is already being transmitted, an error is raised.
Otherwise the RadioState is set to TRANSMIT and a timer is started. When this timer expires the RadioState will be set back to RECV (or IDLE respectively) again.
If the host is receiving a packet this packet is from now on only considered as noise.
Reimplemented from BasicSnrEval.
{ if (rs.getState() == RadioState::TRANSMIT) error("Trying to send a message while already transmitting -- MAC should " "take care this does not happen"); if (frame->getControlInfo()!=NULL) error("Setting control info (here: %s) on frames is not supported", frame->getControlInfo()->getClassName()); // if a packet was being received, it is corrupted now as should be treated as noise if (snrInfo.ptr != NULL) { EV << "Sending a message while receiving another. The received one is now corrupted.\n"; // remove the snr information stored for the message currently being // received. This message is treated as noise now and the // receive power has to be added to the noiseLevel // delete the pointer to indicate that no message is being received snrInfo.ptr = NULL; // clear the snr list snrInfo.sList.clear(); // add the receive power to the noise level noiseLevel += snrInfo.rcvdPower; } // now we are done with all the exception handling and can take care // about the "real" stuff // change radio status rs.setState(RadioState::TRANSMIT); EV << "sending, changing RadioState to TRANSMIT\n"; nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); cMessage *timer = new cMessage(NULL, TRANSM_OVER); scheduleAt(simTime() + frame->getDuration(), timer); sendDown(frame); }
void SnrEval::initialize | ( | int | stage | ) | [protected, virtual] |
Initialize variables and publish the radio status.
Reimplemented from BasicSnrEval.
Reimplemented in GilbertElliotSnr, and SnrEval80211.
{ BasicSnrEval::initialize(stage); if (stage == 0) { gate("radioIn")->setDeliverOnReceptionStart(true); // read parameters rs.setChannelNumber(par("channelNumber")); thermalNoise = FWMath::dBm2mW(par("thermalNoise")); carrierFrequency = cc->par("carrierFrequency"); // taken from ChannelControl sensitivity = FWMath::dBm2mW(par("sensitivity")); pathLossAlpha = par("pathLossAlpha"); if (pathLossAlpha < (double) (cc->par("alpha"))) error("SnrEval::initialize(): pathLossAlpha can't be smaller than in " "ChannelControl. Please adjust your omnetpp.ini file accordingly"); // initialize noiseLevel noiseLevel = thermalNoise; EV << "Initialized channel with noise: " << noiseLevel << " sensitivity: " << sensitivity << endl; // initialize the pointer of the snrInfo with NULL to indicate // that currently no message is received snrInfo.ptr = NULL; // no channel switch pending newChannel = -1; // Initialize radio state. If thermal noise is already to high, radio // state has to be initialized as RECV rs.setState(RadioState::IDLE); if (noiseLevel >= sensitivity) rs.setState(RadioState::RECV); WATCH(noiseLevel); WATCH(rs); } else if (stage == 1) { // tell initial value to MAC; must be done in stage 1, because they // subscribe in stage 0 nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); nb->fireChangeNotification(NF_RADIO_CHANNEL_CHANGED, &rs); } else if (stage == 2) { // tell initial channel number to ChannelControl; should be done in // stage==2 or later, because base class initializes myHostRef in that stage cc->updateHostChannel(myHostRef, rs.getChannelNumber()); } }
void SnrEval::setBitrate | ( | double | bitrate | ) | [virtual] |
change the bitrate to the given value. This method throws an error if the radio state is transmit.
Referenced by handleCommand().
{ if (this->bitrate == bitrate) return; if (bitrate < 0) error("setBitrate(): bitrate cannot be negative (%g)", bitrate); if (rs.getState() == RadioState::TRANSMIT) error("changing the bitrate while transmitting is not allowed"); EV << "Setting bitrate to " << (bitrate/1e6) << "Mbps\n"; this->bitrate = bitrate; //XXX fire some notification? }
double SnrEval::carrierFrequency [protected] |
Configuration: The carrier frequency used. It is read from the ChannelControl module.
Referenced by calcRcvdPower(), and initialize().
double SnrEval::newBitrate [protected] |
State: if not -1, we have to switch to that bitrate once we finished transmitting.
Referenced by handleCommand().
int SnrEval::newChannel [protected] |
State: if not -1, we have to switch to that channel once we finished transmitting.
Referenced by handleCommand(), handleSelfMsg(), and initialize().
double SnrEval::noiseLevel [protected] |
State: the current noise level of the channel.
Referenced by addNewSnr(), handleLowerMsgEnd(), GilbertElliotSnr::handleLowerMsgEnd(), handleLowerMsgStart(), GilbertElliotSnr::handleLowerMsgStart(), handleSelfMsg(), GilbertElliotSnr::handleSelfMsg(), handleUpperMsg(), and initialize().
double SnrEval::pathLossAlpha [protected] |
Configuration: Path loss coefficient. Can be specified in omnetpp.ini. If not it is read from the ChannelControl module. This value CANNOT be smaller than the one specified in the ChannelControl module, or the simulation will exit with an error!
Referenced by calcRcvdPower(), and initialize().
RecvBuff SnrEval::recvBuff [protected] |
State: A buffer to store a pointer to a message and the related receive power.
Referenced by changeChannel(), handleLowerMsgEnd(), GilbertElliotSnr::handleLowerMsgEnd(), handleLowerMsgStart(), GilbertElliotSnr::handleLowerMsgStart(), GilbertElliotSnr::handleSelfMsg(), and ~SnrEval().
RadioState SnrEval::rs [protected] |
State: the current RadioState of the NIC; includes channel number.
Referenced by changeChannel(), handleCommand(), handleLowerMsgEnd(), GilbertElliotSnr::handleLowerMsgEnd(), handleLowerMsgStart(), GilbertElliotSnr::handleLowerMsgStart(), handleSelfMsg(), GilbertElliotSnr::handleSelfMsg(), handleUpperMsg(), initialize(), and setBitrate().
double SnrEval::sensitivity [protected] |
Configuration: Defines up to what Power level (in dBm) a message can be understood. If the level of a received packet is lower, it is only treated as noise. Can be specified in omnetpp.ini. Default:
-85 dBm
Referenced by handleLowerMsgEnd(), GilbertElliotSnr::handleLowerMsgEnd(), handleLowerMsgStart(), GilbertElliotSnr::handleLowerMsgStart(), handleSelfMsg(), GilbertElliotSnr::handleSelfMsg(), and initialize().
SnrStruct SnrEval::snrInfo [protected] |
State: SnrInfo stores the snrList and the the recvdPower for the message currently being received, together with a pointer to the message.
Referenced by addNewSnr(), changeChannel(), handleLowerMsgEnd(), GilbertElliotSnr::handleLowerMsgEnd(), handleLowerMsgStart(), GilbertElliotSnr::handleLowerMsgStart(), handleUpperMsg(), and initialize().
double SnrEval::thermalNoise [protected] |
Configuration: Thermal noise on the channel. Can be specified in omnetpp.ini. Default: -100 dBm.
Referenced by initialize().