Provides some base functionality for most common deciders. More...
#include <BaseDecider.h>
Inherits Decider.
Inherited by Decider80211, Decider802154Narrow, and SNRThresholdDecider.
Classes | |
struct | CSRInfo |
Data about an currently ongoing ChannelSenseRequest. More... | |
Public Types | |
enum | BaseDeciderControlKinds { PACKET_DROPPED = 22100, LAST_BASE_DECIDER_CONTROL_KIND } |
The kinds of ControlMessages this Decider sends. More... | |
Public Member Functions | |
BaseDecider (DeciderToPhyInterface *phy, double sensitivity, int myIndex, bool debug) | |
Initializes the decider with the passed values. | |
virtual simtime_t | processSignal (AirFrame *frame) |
Processes an AirFrame given by the PhyLayer. | |
virtual ChannelState | getChannelState () |
A function that returns information about the channel state. | |
virtual simtime_t | handleChannelSenseRequest (ChannelSenseRequest *request) |
This function is called by the PhyLayer to hand over a ChannelSenseRequest. | |
Protected Types | |
enum | SignalState { NEW, EXPECT_HEADER, EXPECT_END } |
The current state of processing for a signal. More... | |
typedef std::pair< AirFrame *, int > | ReceivedSignal |
Pair of a AirFrame and the state it is in. | |
Protected Member Functions | |
virtual simtime_t | processNewSignal (AirFrame *frame) |
Processes a new Signal. Returns the time it wants to handle the signal again. | |
virtual simtime_t | processSignalHeader (AirFrame *frame) |
Processes the end of the header of a received Signal. | |
virtual simtime_t | processSignalEnd (AirFrame *frame) |
Processes the end of a received Signal. | |
virtual simtime_t | processUnknownSignal (AirFrame *frame) |
Processes any Signal for which no state could be found. (is an error case). | |
virtual int | getSignalState (AirFrame *frame) |
Returns the SignalState for the passed AirFrame. | |
virtual simtime_t | handleNewSenseRequest (ChannelSenseRequest *request) |
Handles a new incoming ChannelSenseRequest and returns the next (or latest) time to handle the request again. | |
virtual void | handleSenseRequestEnd (CSRInfo &requestInfo) |
Handles the timeout or end of a ChannelSenseRequest by calculating the ChannelState and returning the request to the mac layer. | |
virtual void | setChannelIdleStatus (bool isIdle) |
Changes the "isIdle"-status to the passed value. | |
virtual simtime_t | canAnswerCSR (const CSRInfo &requestInfo) |
Returns point in time when the ChannelSenseRequest of the passed CSRInfo can be answered (e.g. because channel state changed or timeout is reached). | |
virtual double | calcChannelSenseRSSI (simtime_t start, simtime_t end) |
Calculates the RSSI value for the passed interval. | |
virtual void | answerCSR (CSRInfo &requestInfo) |
Answers the ChannelSenseRequest (CSR) from the passed CSRInfo. | |
virtual void | channelStateChanged () |
Checks if the changed channel state enables us to answer any ongoing ChannelSenseRequests. | |
virtual void | getChannelInfo (simtime_t start, simtime_t end, AirFrameVector &out) |
Collects the AirFrame on the channel during the passed interval. | |
virtual Mapping * | calculateSnrMapping (AirFrame *frame) |
Calculates a SNR-Mapping for a Signal. | |
virtual Mapping * | calculateRSSIMapping (simtime_t start, simtime_t end, AirFrame *exclude=0) |
Calculates a RSSI-Mapping (or Noise-Strength-Mapping) for a Signal. | |
Protected Attributes | |
double | sensitivity |
sensitivity value for receiving an AirFrame | |
ReceivedSignal | currentSignal |
pointer to the currently received AirFrame | |
bool | isChannelIdle |
Stores the idle state of the channel. | |
CSRInfo | currentChannelSenseRequest |
pointer to the currently running ChannelSenseRequest and its start-time | |
int | myIndex |
index for this Decider-instance given by Phy-Layer (mostly Host-index) | |
bool | debug |
toggles display of debugging messages |
Provides some base functionality for most common deciders.
Forwards the AirFrame from "processSignal" to "processNewSignal", "processSignalHeader" or "processSignalEnd" depending on the state for that AirFrame returned by "getSignalState".
Provides answering of ChannelSenseRequests (instantaneous and over time).
Subclasses should define when they consider the channel as idle by calling "setChannelIdleStatus" because BaseDecider uses that to answer ChannelSenseRequests.
If a subclassing Decider only tries to receive one signal at a time it can use BaseDeciders "currentSignal" member which is a pair of the signal to receive and the state for that signal. The state is then used by BaseDeciders "getSignalState" to decide to which "process***" method to forward the signal. If a subclassing Decider needs states for more than one Signal it has to store these states by itself and should probably override the "getSignalState" method.
Definition at line 40 of file BaseDecider.h.
The kinds of ControlMessages this Decider sends.
Sub-classing decider should begin their own kind enumeration at the value of "LAST_BASE_DECIDER_CONTROL_KIND".
PACKET_DROPPED |
The phy has recognized a bit error in the packet. |
LAST_BASE_DECIDER_CONTROL_KIND |
Sub-classing decider should begin their own kinds at this value. |
Definition at line 48 of file BaseDecider.h.
{ PACKET_DROPPED = 22100, LAST_BASE_DECIDER_CONTROL_KIND };
enum BaseDecider::SignalState [protected] |
The current state of processing for a signal.
NEW |
Signal is received the first time. |
EXPECT_HEADER |
Waiting for the header of the signal. |
EXPECT_END |
Waiting for the end of the signal. |
Definition at line 59 of file BaseDecider.h.
{ NEW, EXPECT_HEADER, EXPECT_END, };
BaseDecider::BaseDecider | ( | DeciderToPhyInterface * | phy, | |
double | sensitivity, | |||
int | myIndex, | |||
bool | debug | |||
) | [inline] |
Initializes the decider with the passed values.
Needs a pointer to its physical layer, the sensitivity, the index of the host and the debug flag.
Definition at line 112 of file BaseDecider.h.
References currentChannelSenseRequest, and currentSignal.
: Decider(phy), sensitivity(sensitivity), isChannelIdle(true), myIndex(myIndex), debug(debug) { currentSignal.first = 0; currentSignal.second = NEW; currentChannelSenseRequest.first = 0; currentChannelSenseRequest.second = -1; currentChannelSenseRequest.canAnswerAt = -1; }
void BaseDecider::answerCSR | ( | CSRInfo & | requestInfo | ) | [protected, virtual] |
Answers the ChannelSenseRequest (CSR) from the passed CSRInfo.
Calculates the rssi value and the channel idle state and sends the CSR together with the result back to the mac layer.
Reimplemented in SNRThresholdDecider.
Definition at line 203 of file BaseDecider.cc.
References calcChannelSenseRSSI(), DeciderToPhyInterface::getSimTime(), isChannelIdle, Decider::phy, and DeciderToPhyInterface::sendControlMsg().
Referenced by channelStateChanged(), handleNewSenseRequest(), and handleSenseRequestEnd().
{ double rssiValue = calcChannelSenseRSSI(requestInfo.second, phy->getSimTime()); // put the sensing-result to the request and // send it to the Mac-Layer as Control-message (via Interface) requestInfo.first->setResult( ChannelState(isChannelIdle, rssiValue) ); phy->sendControlMsg(requestInfo.first); requestInfo.first = 0; requestInfo.second = -1; requestInfo.canAnswerAt = -1; }
double BaseDecider::calcChannelSenseRSSI | ( | simtime_t | start, | |
simtime_t | end | |||
) | [protected, virtual] |
Calculates the RSSI value for the passed interval.
This method is called by BaseDecider when it answers a ChannelSenseRequest or calculates the channel state. Can be overridden by sub classing Deciders.
Default implementation returns the maximum RSSI value inside the passed interval.
Reimplemented in Decider80211.
Definition at line 188 of file BaseDecider.cc.
References calculateRSSIMapping(), and MappingUtils::findMax().
Referenced by answerCSR(), SNRThresholdDecider::getChannelState(), getChannelState(), and Decider802154Narrow::processSignalEnd().
{ Mapping* rssiMap = calculateRSSIMapping(start, end); // the sensed RSSI-value is the maximum value between (and including) the interval-borders double rssi = MappingUtils::findMax(*rssiMap, Argument(start), Argument(end)); //"findMax()" returns "-DBL_MAX" on empty mappings if (rssi < 0) rssi = 0; delete rssiMap; return rssi; }
Mapping * BaseDecider::calculateRSSIMapping | ( | simtime_t | start, | |
simtime_t | end, | |||
AirFrame * | exclude = 0 | |||
) | [protected, virtual] |
Calculates a RSSI-Mapping (or Noise-Strength-Mapping) for a Signal.
This method can be used to calculate a RSSI-Mapping in case the parameter exclude is omitted OR to calculate a Noise-Strength-Mapping in case the AirFrame of the received Signal is passed as parameter exclude.
Definition at line 245 of file BaseDecider.cc.
References MappingUtils::createMapping(), getChannelInfo(), Signal::getReceivingPower(), Signal::getSignalLength(), Signal::getSignalStart(), DeciderToPhyInterface::getThermalNoise(), Decider::phy, and DimensionSet::timeDomain.
Referenced by Decider80211::calcChannelSenseRSSI(), calcChannelSenseRSSI(), calculateSnrMapping(), and SNRThresholdDecider::canAnswerCSR().
{ if(exclude) deciderEV << "Creating RSSI map excluding AirFrame with id " << exclude->getId() << endl; else deciderEV << "Creating RSSI map." << endl; AirFrameVector airFrames; // collect all AirFrames that intersect with [start, end] getChannelInfo(start, end, airFrames); //TODO: create a "MappingUtils:createMappingFrom()"-method and use it here instead //of abusing the add method // create an empty mapping Mapping* resultMap = MappingUtils::createMapping(0.0, DimensionSet::timeDomain); //add thermal noise ConstMapping* thermalNoise = phy->getThermalNoise(start, end); if(thermalNoise) { Mapping* tmp = resultMap; resultMap = MappingUtils::add(*resultMap, *thermalNoise); delete tmp; } // otherwise, iterate over all AirFrames (except exclude) // and sum up their receiving-power-mappings AirFrameVector::iterator it; for (it = airFrames.begin(); it != airFrames.end(); it++) { // the vector should not contain pointers to 0 assert (*it != 0); // if iterator points to exclude (that includes the default-case 'exclude == 0') // then skip this AirFrame if ( *it == exclude ) continue; // otherwise get the Signal and its receiving-power-mapping Signal& signal = (*it)->getSignal(); // backup pointer to result map // Mapping* resultMapOld = resultMap; // TODO1.1: for testing purposes, for now we don't specify an interval // and add the Signal's receiving-power-mapping to resultMap in [start, end], // the operation Mapping::add returns a pointer to a new Mapping ConstMapping* recvPowerMap = signal.getReceivingPower(); assert(recvPowerMap); // Mapping* resultMapNew = Mapping::add( *(signal.getReceivingPower()), *resultMap, start, end ); deciderEV << "Adding mapping of Airframe with ID " << (*it)->getId() << ". Starts at " << signal.getSignalStart() << " and ends at " << signal.getSignalStart() + signal.getSignalLength() << endl; Mapping* resultMapNew = MappingUtils::add( *recvPowerMap, *resultMap, 0.0 ); // discard old mapping delete resultMap; resultMap = resultMapNew; resultMapNew = 0; } return resultMap; }
Mapping * BaseDecider::calculateSnrMapping | ( | AirFrame * | frame | ) | [protected, virtual] |
Calculates a SNR-Mapping for a Signal.
A Noise-Strength-Mapping is calculated (by using the "calculateRSSIMapping()"-method) for the time-interval of the Signal and the Signal-Strength-Mapping is divided by the Noise-Strength-Mapping.
Note: 'divided' means here the special element-wise operation on mappings.
Definition at line 217 of file BaseDecider.cc.
References calculateRSSIMapping(), Signal::getReceivingPower(), Signal::getSignalLength(), and Signal::getSignalStart().
Referenced by Decider80211::checkIfSignalOk(), SNRThresholdDecider::processSignalEnd(), and Decider802154Narrow::processSignalEnd().
{ /* calculate Noise-Strength-Mapping */ Signal& signal = frame->getSignal(); simtime_t start = signal.getSignalStart(); simtime_t end = start + signal.getSignalLength(); Mapping* noiseMap = calculateRSSIMapping(start, end, frame); assert(noiseMap); ConstMapping* recvPowerMap = signal.getReceivingPower(); assert(recvPowerMap); //TODO: handle noise of zero (must not devide with zero!) Mapping* snrMap = MappingUtils::divide( *recvPowerMap, *noiseMap, 0.0 ); delete noiseMap; noiseMap = 0; return snrMap; }
void BaseDecider::channelStateChanged | ( | ) | [protected, virtual] |
Checks if the changed channel state enables us to answer any ongoing ChannelSenseRequests.
This method is ment to update only an already ongoing ChannelSenseRequests it can't handle a new one.
Definition at line 136 of file BaseDecider.cc.
References answerCSR(), canAnswerCSR(), DeciderToPhyInterface::cancelScheduledMessage(), currentChannelSenseRequest, DeciderToPhyInterface::getSimTime(), Decider::phy, and DeciderToPhyInterface::rescheduleMessage().
Referenced by Decider80211MultiChannel::channelChanged(), SNRThresholdDecider::processNewSignal(), and setChannelIdleStatus().
{ if(!currentChannelSenseRequest.getRequest()) return; //check if the point in time when we can answer the request has changed simtime_t canAnswerAt = canAnswerCSR(currentChannelSenseRequest); //check if answer time has changed if(canAnswerAt != currentChannelSenseRequest.canAnswerAt) { //can we answer it now? if(canAnswerAt == phy->getSimTime()) { phy->cancelScheduledMessage(currentChannelSenseRequest.getRequest()); answerCSR(currentChannelSenseRequest); } else { phy->rescheduleMessage(currentChannelSenseRequest.getRequest(), canAnswerAt); currentChannelSenseRequest.canAnswerAt = canAnswerAt; } } }
void BaseDecider::getChannelInfo | ( | simtime_t | start, | |
simtime_t | end, | |||
AirFrameVector & | out | |||
) | [protected, virtual] |
Collects the AirFrame on the channel during the passed interval.
Forwards to DeciderToPhyInterfaces "getChannelInfo" method. Subclassing deciders can override this method to filter the returned AirFrames for their own criteria, for example by removing AirFrames on another not interferring channel.
start | The start of the interval to collect AirFrames from. | |
end | The end of the interval to collect AirFrames from. | |
out | The output vector in which to put the AirFrames. |
Reimplemented in Decider80211MultiChannel.
Definition at line 239 of file BaseDecider.cc.
References DeciderToPhyInterface::getChannelInfo(), and Decider::phy.
Referenced by calculateRSSIMapping().
{ phy->getChannelInfo(start, end, out); }
ChannelState BaseDecider::getChannelState | ( | ) | [virtual] |
A function that returns information about the channel state.
It is an alternative for the MACLayer in order to obtain information immediately (in contrast to sending a ChannelSenseRequest, i.e. sending a cMessage over the OMNeT-control-channel)
Reimplemented from Decider.
Reimplemented in SNRThresholdDecider.
Definition at line 72 of file BaseDecider.cc.
References calcChannelSenseRSSI(), DeciderToPhyInterface::getSimTime(), isChannelIdle, and Decider::phy.
{ simtime_t now = phy->getSimTime(); double rssiValue = calcChannelSenseRSSI(now, now); return ChannelState(isChannelIdle, rssiValue); }
int BaseDecider::getSignalState | ( | AirFrame * | frame | ) | [protected, virtual] |
Returns the SignalState for the passed AirFrame.
The default implementation checks if the passed AirFrame is the "currentSignal" and returns its state or if not "NEW".
Definition at line 129 of file BaseDecider.cc.
References currentSignal.
Referenced by processSignal().
{ if(frame == currentSignal.first) return currentSignal.second; return NEW; }
simtime_t BaseDecider::handleChannelSenseRequest | ( | ChannelSenseRequest * | request | ) | [virtual] |
This function is called by the PhyLayer to hand over a ChannelSenseRequest.
The MACLayer is able to send a ChannelSenseRequest to the PhyLayer that calls this function with it and is returned a time point when to re-call this function with the specific ChannelSenseRequest.
The Decider puts the result (ChannelState) to the ChannelSenseRequest and "answers" by calling the "sendControlMsg"-function on the DeciderToPhyInterface, i.e. telling the PhyLayer to send it back.
Reimplemented from Decider.
Definition at line 81 of file BaseDecider.cc.
References currentChannelSenseRequest, handleNewSenseRequest(), handleSenseRequestEnd(), and Decider::notAgain.
{ assert(request); if (currentChannelSenseRequest.first == 0) { return handleNewSenseRequest(request); } if (currentChannelSenseRequest.first != request) { opp_error("Got a new ChannelSenseRequest while already handling another one!"); return notAgain; } handleSenseRequestEnd(currentChannelSenseRequest); // say that we don't want to have it again return notAgain; }
void BaseDecider::handleSenseRequestEnd | ( | CSRInfo & | requestInfo | ) | [protected, virtual] |
Handles the timeout or end of a ChannelSenseRequest by calculating the ChannelState and returning the request to the mac layer.
If this handler is reached the decider has to be able to answer the request. Either because the timeout is reached or because the channel state changed accordingly.
Definition at line 124 of file BaseDecider.cc.
References answerCSR(), canAnswerCSR(), DeciderToPhyInterface::getSimTime(), and Decider::phy.
Referenced by handleChannelSenseRequest().
{ assert(canAnswerCSR(requestInfo) == phy->getSimTime()); answerCSR(requestInfo); }
simtime_t BaseDecider::processNewSignal | ( | AirFrame * | frame | ) | [protected, virtual] |
Processes a new Signal. Returns the time it wants to handle the signal again.
Default implementation checks if the signals receiving power is above the sensitivity of the radio and we are not already trying to receive another AirFrame. If thats the case it waits for the end of the signal.
Reimplemented in Decider80211, Decider80211MultiChannel, Decider802154Narrow, and SNRThresholdDecider.
Definition at line 27 of file BaseDecider.cc.
References currentSignal, Signal::getReceivingPower(), Signal::getSignalLength(), Signal::getSignalStart(), Decider::notAgain, sensitivity, and setChannelIdleStatus().
Referenced by processSignal().
{ if(currentSignal.first != 0) { deciderEV << "Already receiving another AirFrame!" << endl; return notAgain; } // get the receiving power of the Signal at start-time Signal& signal = frame->getSignal(); double recvPower = signal.getReceivingPower()->getValue(Argument(signal.getSignalStart())); // check whether signal is strong enough to receive if ( recvPower < sensitivity ) { deciderEV << "Signal is to weak (" << recvPower << " < " << sensitivity << ") -> do not receive." << endl; // Signal too weak, we can't receive it, tell PhyLayer that we don't want it again return notAgain; } // Signal is strong enough, receive this Signal and schedule it deciderEV << "Signal is strong enough (" << recvPower << " > " << sensitivity << ") -> Trying to receive AirFrame." << endl; currentSignal.first = frame; currentSignal.second = EXPECT_END; //channel turned busy setChannelIdleStatus(false); return ( signal.getSignalStart() + signal.getSignalLength() ); }
simtime_t BaseDecider::processSignal | ( | AirFrame * | frame | ) | [virtual] |
Processes an AirFrame given by the PhyLayer.
Returns the time point when the decider wants to be given the AirFrame again.
Reimplemented from Decider.
Definition at line 10 of file BaseDecider.cc.
References EXPECT_END, EXPECT_HEADER, getSignalState(), NEW, processNewSignal(), processSignalEnd(), processSignalHeader(), and processUnknownSignal().
{ assert(frame); deciderEV << "Processing AirFrame..." << endl; switch(getSignalState(frame)) { case NEW: return processNewSignal(frame); case EXPECT_HEADER: return processSignalHeader(frame); case EXPECT_END: return processSignalEnd(frame); default: return processUnknownSignal(frame); } }
simtime_t BaseDecider::processSignalEnd | ( | AirFrame * | frame | ) | [protected, virtual] |
Processes the end of a received Signal.
Returns the time it wants to handle the signal again (most probably notAgain).
Default implementation just decides every signal as correct and passes it to the upper layer.
Reimplemented in Decider80211, Decider802154Narrow, and SNRThresholdDecider.
Definition at line 59 of file BaseDecider.cc.
References currentSignal, Decider::notAgain, Decider::phy, DeciderToPhyInterface::sendUp(), and setChannelIdleStatus().
Referenced by processSignal().
{ deciderEV << "packet was received correctly, it is now handed to upper layer...\n"; phy->sendUp(frame, new DeciderResult(true)); // we have processed this AirFrame and we prepare to receive the next one currentSignal.first = 0; //channel is idle now setChannelIdleStatus(true); return notAgain; }
virtual simtime_t BaseDecider::processSignalHeader | ( | AirFrame * | frame | ) | [inline, protected, virtual] |
Processes the end of the header of a received Signal.
Returns the time it wants to handle the signal again.
Default implementation does not handle signal headers.
Reimplemented in Decider802154Narrow.
Definition at line 182 of file BaseDecider.h.
References Decider::notAgain.
Referenced by processSignal().
{ opp_error("BaseDecider does not handle Signal headers!"); return notAgain; }
void BaseDecider::setChannelIdleStatus | ( | bool | isIdle | ) | [protected, virtual] |
Changes the "isIdle"-status to the passed value.
This method further checks if there are any ChannelSenseRequests which can be answered because of the idle state changed.
Reimplemented in Decider80211Battery.
Definition at line 158 of file BaseDecider.cc.
References channelStateChanged(), and isChannelIdle.
Referenced by Decider80211::processNewSignal(), processNewSignal(), Decider802154Narrow::processSignalEnd(), Decider80211::processSignalEnd(), processSignalEnd(), and Decider802154Narrow::processSignalHeader().
{ isChannelIdle = isIdle; channelStateChanged(); }