An implementation of the 802.11b MAC. More...
#include <Mac80211.h>
Inherits BaseMacLayer.
Inherited by Mac80211MultiChannel.
Classes | |
struct | NeighborEntry |
Data about a neighbor host. More... | |
Public Types | |
enum | Mac80211MessageKinds { RTS = LAST_BASE_MAC_MESSAGE_KIND, CTS, ACK, DATA, BROADCAST, LAST_MAC_80211_MESSAGE_KIND } |
frame kinds | |
Public Member Functions | |
virtual void | initialize (int) |
Initialization of the module and some variables. | |
virtual void | finish () |
Called when the simulation has finished. | |
Protected Types | |
enum | timerType { TIMEOUT, NAV } |
enum | State { WFDATA = 0, QUIET = 1, IDLE = 2, CONTEND = 3, WFCTS = 4, WFACK = 5, BUSY = 6 } |
typedef std::list< Mac80211Pkt * > | MacPktList |
Type for a queue of Mac80211Pkts. | |
typedef std::list< NeighborEntry > | NeighborList |
Type for a list of NeighborEntries. | |
Protected Member Functions | |
virtual void | handleSelfMsg (cMessage *) |
Handle self messages such as timer... | |
virtual void | handleUpperMsg (cMessage *msg) |
Handle messages from upper layer. | |
virtual void | handleLowerMsg (cMessage *) |
Handle messages from lower layer. | |
virtual void | handleLowerControl (cMessage *) |
Handle messages from lower layer. | |
virtual void | handleEndContentionTimer () |
Called by the Blackboard whenever a change occurs we're interested in. | |
void | handleMsgNotForMe (cMessage *af, simtime_t duration) |
handle a message that is not for me or errornous | |
void | handleMsgForMe (Mac80211Pkt *) |
handle a message that was meant for me | |
void | handleBroadcastMsg (Mac80211Pkt *) |
void | handleEndTransmission () |
handle the end of a transmission... | |
void | handleEndSifsTimer () |
handle end of SIFS | |
void | handleTimeoutTimer () |
handle time out | |
void | handleNavTimer () |
NAV timer expired, the exchange of messages of other stations is done. | |
void | handleRTSframe (Mac80211Pkt *) |
void | handleDATAframe (Mac80211Pkt *) |
void | handleACKframe (Mac80211Pkt *) |
void | handleCTSframe (Mac80211Pkt *) |
void | dataTransmissionFailed () |
void | rtsTransmissionFailed () |
virtual void | sendDATAframe (Mac80211Pkt *) |
send data frame | |
void | sendACKframe (Mac80211Pkt *) |
send Acknoledgement | |
void | sendCTSframe (Mac80211Pkt *) |
send CTS frame | |
virtual void | sendRTSframe () |
send RTS frame | |
void | sendBROADCASTframe () |
send broadcast frame | |
Mac80211Pkt * | encapsMsg (cPacket *netw) |
encapsulate packet | |
cMessage * | decapsMsg (Mac80211Pkt *frame) |
decapsulate packet | |
virtual void | beginNewCycle () |
start a new contention period | |
simtime_t | backoff (bool rtscts=true) |
Compute a backoff value. | |
void | testMaxAttempts () |
Test if maximum number of retries to transmit is exceeded. | |
simtime_t | timeOut (Mac80211MessageKinds type, double br) |
return a timeOut value for a certain type of frame | |
simtime_t | packetDuration (double bits, double br) |
computes the duration of a transmission over the physical channel, given a certain bitrate | |
const char * | stateName (State state) |
Produce a readable name of the given state. | |
void | setState (State state) |
Sets the state, and produces a log message in between. | |
bool | rtsCts (Mac80211Pkt *m) |
Check whether the next packet should be send with RTS/CTS. | |
void | suspendContention () |
suspend an ongoing contention, pick it up again when the channel becomes idle | |
double | retrieveBitrate (int destAddress) |
figure out at which bitrate to send to this particular destination | |
void | addNeighbor (Mac80211Pkt *af) |
add a new entry to the neighbor list | |
NeighborList::iterator | findNeighbor (int id) |
find a neighbor based on his address | |
NeighborList::iterator | findOldestNeighbor () |
find the oldest neighbor -- usually in order to overwrite this entry | |
void | senseChannelWhileIdle (simtime_t duration) |
Starts a channel sense request which sense the channel for the passed duration or until the channel is busy. | |
Signal * | createSignal (simtime_t start, simtime_t length, double power, double bitrate) |
Creates the signal to be used for a packet to be sent. | |
Protected Attributes | |
cMessage * | timeout |
Timer used for time-outs after the transmission of a RTS, a CTS, or a DATA packet. | |
cMessage * | nav |
Timer used for the defer time of a node. Also called NAV : networks allocation vector. | |
ChannelSenseRequest * | contention |
Used to sense if the channel is idle for contention periods. | |
ChannelSenseRequest * | endSifs |
Timer used to indicate the end of a SIFS. | |
simtime_t | chSenseStart |
Stores the the time a channel sensing started. Used to calculate the quiet-time of the channel if the sensing was aborted. | |
State | state |
Current state of the MAC. | |
double | defaultBitrate |
Default bitrate. | |
double | txPower |
The power at which data is transmitted. | |
double | centerFreq |
Stores the center frequency the Mac uses. | |
double | bitrate |
Current bit rate at which data is transmitted. | |
int | catBitrate |
and category number | |
bool | autoBitrate |
Auto bit rate adaptation -- switch. | |
std::vector< double > | snrThresholds |
Hold RSSI thresholds at which to change the bitrates. | |
unsigned | queueLength |
Maximal number of packets in the queue; should be set in the omnetpp.ini. | |
bool | nextIsBroadcast |
Boolean used to know if the next packet is a broadcast packet. | |
MacPktList | fromUpperLayer |
Buffering of messages from upper layer. | |
unsigned | longRetryCounter |
Number of frame transmission attempt. | |
unsigned | shortRetryCounter |
Number of frame transmission attempt. | |
simtime_t | remainingBackoff |
remaining backoff time. If the backoff timer is interrupted, this variable holds the remaining backoff time. | |
simtime_t | currentIFS |
current IFS value (DIFS or EIFS) If an error has been detected, the next backoff requires EIFS, once a valid frame has been received, resets to DIFS. | |
int | rtsCtsThreshold |
Number of bits in a packet before RTS/CTS is used. | |
simtime_t | delta |
Very small value used in timer scheduling in order to avoid multiple changements of state in the same simulation time. | |
unsigned | neighborhoodCacheSize |
Keep information for this many neighbors. | |
simtime_t | neighborhoodCacheMaxAge |
Consider information in cache outdate if it is older than this. | |
NeighborList | neighbors |
A list of this hosts neighbors. | |
bool | switching |
int | fsc |
An implementation of the 802.11b MAC.
For more info, see the NED file.
Definition at line 39 of file Mac80211.h.
enum Mac80211::State [protected] |
Definition of the states
Definition at line 64 of file Mac80211.h.
{ WFDATA = 0, // waiting for data packet QUIET = 1, // waiting for the communication between two other nodes to end IDLE = 2, // no packet to send, no packet receiving CONTEND = 3,// contention state (battle for the channel) WFCTS = 4, // RTS sent, waiting for CTS WFACK = 5, // DATA packet sent, waiting for ACK BUSY = 6 // during transmission of an ACK or a BROADCAST packet };
enum Mac80211::timerType [protected] |
simtime_t Mac80211::backoff | ( | bool | rtscts = true |
) | [protected] |
Compute a backoff value.
Compute the backoff value.
Definition at line 1011 of file Mac80211.cc.
References longRetryCounter, and shortRetryCounter.
Referenced by handleACKframe(), handleEndTransmission(), and initialize().
{ unsigned rc = (rtscts) ? longRetryCounter : shortRetryCounter; unsigned cw = ((CW_MIN + 1) << rc) - 1; if(cw > CW_MAX) cw = CW_MAX; simtime_t value = ((double) intrand(cw + 1)) * ST; debugEV << simTime() << " random backoff = " << value << endl; return value; }
void Mac80211::beginNewCycle | ( | ) | [protected, virtual] |
start a new contention period
Start a new contention period if the channel is free and if there's a packet to send. Called at the end of a deferring period, a busy period, or after a failure. Called by the HandleMsgForMe(), HandleTimer() HandleUpperMsg(), and, without RTS/CTS, by handleMsgNotForMe().
Definition at line 956 of file Mac80211.cc.
References contention, currentIFS, fromUpperLayer, MacToPhyInterface::getChannelState(), ChannelState::info(), ChannelState::isIdle(), nav, nextIsBroadcast, BaseMacLayer::phy, remainingBackoff, senseChannelWhileIdle(), setState(), and testMaxAttempts().
Referenced by handleACKframe(), handleBroadcastMsg(), handleEndTransmission(), handleMsgNotForMe(), handleNavTimer(), handleTimeoutTimer(), and handleUpperMsg().
{ // before trying to send one more time a packet, test if the // maximum retry limit is reached. If it is the case, then // delete the packet and send the next packet. testMaxAttempts(); if (nav->isScheduled()) { debugEV << "cannot beginNewCycle until NAV expires at t " << nav->getArrivalTime() << endl; return; } /* if(timeout->isScheduled()) { cancelEvent(timeout); } */ if (!fromUpperLayer.empty()) { // look if the next packet is unicast or broadcast nextIsBroadcast = (fromUpperLayer.front()->getDestAddr() == L2BROADCAST); setState(CONTEND); if(!contention->isScheduled()) { ChannelState channel = phy->getChannelState(); debugEV << simTime() << " do contention: medium = " << channel.info() << ", backoff = " << remainingBackoff << endl; if(channel.isIdle()) { senseChannelWhileIdle(currentIFS + remainingBackoff); //scheduleAt(simTime() + currentIFS + remainingBackoff, contention); } } } else { // post-xmit backoff (minor nit: if random backoff=0, we punt) if(remainingBackoff > 0 && !contention->isScheduled()) { ChannelState channel = phy->getChannelState(); debugEV << simTime() << " do contention: medium = " << channel.info() << ", backoff = " << remainingBackoff << endl; if(channel.isIdle()) { senseChannelWhileIdle(currentIFS + remainingBackoff); //scheduleAt(simTime() + currentIFS + remainingBackoff, contention); } } setState(IDLE); } }
Mac80211Pkt * Mac80211::encapsMsg | ( | cPacket * | netw | ) | [protected, virtual] |
encapsulate packet
Encapsulates the received network-layer packet into a MacPkt and set all needed header fields.
Reimplemented from BaseMacLayer.
Definition at line 181 of file Mac80211.cc.
References fsc, NetwToMacControlInfo::getNextHopMac(), and BaseMacLayer::myMacAddr.
Referenced by handleUpperMsg().
{ Mac80211Pkt *pkt = new Mac80211Pkt(netw->getName()); // headerLength, including final CRC-field AND the phy header length! pkt->setBitLength(MAC80211_HEADER_LENGTH); pkt->setRetry(false); // this is not a retry pkt->setSequenceControl(fsc++); // add a unique fsc to it if(fsc <= 0) fsc = 1; // copy dest address from the Control Info attached to the network // mesage by the network layer NetwToMacControlInfo* cInfo = static_cast<NetwToMacControlInfo*>(netw->removeControlInfo()); debugEV <<"CInfo removed, mac addr="<< cInfo->getNextHopMac()<<endl; pkt->setDestAddr(cInfo->getNextHopMac()); //delete the control info delete cInfo; //set the src address to own mac address (nic module id()) pkt->setSrcAddr(myMacAddr); //encapsulate the network packet pkt->encapsulate(netw); debugEV <<"pkt encapsulated, length: " << pkt->getBitLength() << "\n"; return pkt; }
void Mac80211::handleACKframe | ( | Mac80211Pkt * | af | ) | [protected] |
Handle ACK and delete corresponding packet from queue
Definition at line 541 of file Mac80211.cc.
References backoff(), beginNewCycle(), fromUpperLayer, longRetryCounter, remainingBackoff, shortRetryCounter, and timeout.
Referenced by handleMsgForMe().
{ // cancel time-out event cancelEvent(timeout); // the transmission is acknowledged : initialize long_retry_counter longRetryCounter = 0; shortRetryCounter = 0; // post transmit backoff remainingBackoff = backoff(); // removes the acknowledged packet from the queue Mac80211Pkt *temp = fromUpperLayer.front(); fromUpperLayer.pop_front(); delete temp; // if thre's a packet to send and if the channel is free then start a new contention period beginNewCycle(); }
void Mac80211::handleBroadcastMsg | ( | Mac80211Pkt * | af | ) | [protected] |
Handle a broadcast packet. This packet is simply passed to the upper layer. No acknowledgement is needed. Called by handleLowerMsg(Mac80211Pkt *af)
Definition at line 583 of file Mac80211.cc.
References beginNewCycle(), contention, decapsMsg(), BaseLayer::sendUp(), state, and switching.
Referenced by handleLowerMsg().
{ debugEV << "handle broadcast\n"; if((state == BUSY) && (!switching)) { error("logic error: node is currently transmitting, can not receive " "(does the physical layer do its job correctly?)"); } sendUp(decapsMsg(af)); delete af; if (state == CONTEND) { assert(!contention->isScheduled()); //suspendContention(); beginNewCycle(); } }
void Mac80211::handleCTSframe | ( | Mac80211Pkt * | af | ) | [protected] |
Handle a CTS frame. Called by HandleMsgForMe(Mac80211Pkt* af)
Definition at line 564 of file Mac80211.cc.
References endSifs, BaseLayer::sendControlDown(), shortRetryCounter, and timeout.
Referenced by handleMsgForMe().
{ // cancel time-out event cancelEvent(timeout); shortRetryCounter = 0; // wait a short interframe space if(endSifs->isScheduled()) error("Mac80211::handleCTSframe when SIFS scheduled"); endSifs->setContextPointer(af); sendControlDown(endSifs); //scheduleAt(simTime() + SIFS, endSifs); }
void Mac80211::handleDATAframe | ( | Mac80211Pkt * | af | ) | [protected] |
Handle a frame which expected to be a DATA frame. Called by HandleMsgForMe()
Definition at line 514 of file Mac80211.cc.
References decapsMsg(), endSifs, findNeighbor(), neighbors, rtsCts(), BaseLayer::sendControlDown(), BaseLayer::sendUp(), and timeout.
Referenced by handleMsgForMe().
{ NeighborList::iterator it; if (rtsCts(af)) cancelEvent(timeout); // cancel time-out event it = findNeighbor(af->getSrcAddr()); if(it == neighbors.end()) error("Mac80211::handleDATAframe: neighbor not registered"); if(af->getRetry() && (it->fsc == af->getSequenceControl())) { debugEV << "Mac80211::handleDATAframe suppressed duplicate message " << af << " fsc: " << it->fsc << "\n"; } else { it->fsc = af->getSequenceControl(); // pass the packet to the upper layer sendUp(decapsMsg(af)); } // wait a short interframe space if(endSifs->isScheduled()) error("Mac80211::handleDATAframe when SIFS scheduled"); endSifs->setContextPointer(af); sendControlDown(endSifs); //scheduleAt(simTime() + SIFS, endSifs); }
void Mac80211::handleEndContentionTimer | ( | ) | [protected, virtual] |
Called by the Blackboard whenever a change occurs we're interested in.
handle end of contention
The node has won the contention, and is now allowed to send an RTS/DATA or Broadcast packet. The backoff value is deleted and will be newly computed in the next contention period
Definition at line 606 of file Mac80211.cc.
References contention, fromUpperLayer, nextIsBroadcast, BaseMacLayer::phy, remainingBackoff, rtsCts(), sendBROADCASTframe(), sendDATAframe(), sendRTSframe(), MacToPhyInterface::setRadioState(), state, suspendContention(), and Radio::TX.
Referenced by handleLowerControl().
{ if(!contention->getResult().isIdle()) { suspendContention(); return; } if(state == IDLE) { remainingBackoff = 0; } else if(state == CONTEND) { // the node has won the channel, the backoff window is deleted and // will be new calculated in the next contention period remainingBackoff = 0; // unicast packet phy->setRadioState(Radio::TX); if (!nextIsBroadcast) { if(rtsCts(fromUpperLayer.front())) { // send a RTS sendRTSframe(); } else { sendDATAframe(0); } }// broadcast packet else { sendBROADCASTframe(); // removes the packet from the queue without waiting for an acknowledgement Mac80211Pkt *temp = fromUpperLayer.front(); fromUpperLayer.pop_front(); delete(temp); } } else { error("logic error: expiration of the contention timer outside of CONTEND/IDLE state, should not happen"); } }
void Mac80211::handleEndSifsTimer | ( | ) | [protected] |
handle end of SIFS
Handle the end sifs timer. Then sends a CTS, a DATA, or an ACK frame
Definition at line 713 of file Mac80211.cc.
References endSifs, fromUpperLayer, BaseMacLayer::phy, sendACKframe(), sendCTSframe(), sendDATAframe(), MacToPhyInterface::setRadioState(), setState(), and Radio::TX.
Referenced by handleLowerControl().
{ if(!endSifs->getResult().isIdle()){ // delete the previously received frame delete static_cast<Mac80211Pkt *>(endSifs->getContextPointer()); // state in now IDLE or CONTEND if (fromUpperLayer.empty()) setState(IDLE); else setState(CONTEND); return; } Mac80211Pkt *frame = static_cast<Mac80211Pkt *>(endSifs->getContextPointer()); phy->setRadioState(Radio::TX); switch (frame->getKind()) { case RTS: sendCTSframe(frame); break; case CTS: sendDATAframe(frame); break; case DATA: sendACKframe(frame); break; default: error("logic error: end sifs timer when previously received packet is not RTS/CTS/DATA"); } // don't need previous frame any more delete frame; }
void Mac80211::handleEndTransmission | ( | ) | [protected] |
handle the end of a transmission...
Handle the end of transmission timer (end of the transmission of an ACK or a broadcast packet). Called by HandleTimer(cMessage* msg)
Definition at line 754 of file Mac80211.cc.
References backoff(), beginNewCycle(), longRetryCounter, nextIsBroadcast, remainingBackoff, shortRetryCounter, and state.
Referenced by handleLowerControl().
{ debugEV << "transmission of packet is over\n"; if(state == BUSY) { if(nextIsBroadcast) { shortRetryCounter = 0; longRetryCounter = 0; remainingBackoff = backoff(); } beginNewCycle(); } else if(state == WFDATA) { beginNewCycle(); } }
void Mac80211::handleLowerMsg | ( | cMessage * | msg | ) | [protected, virtual] |
Handle messages from lower layer.
Handle all messages from lower layer. Checks the destination MAC adress of the packet. Then calls one of the three functions : handleMsgNotForMe(), handleBroadcastMsg(), or handleMsgForMe(). Called by handleMessage().
Reimplemented from BaseMacLayer.
Definition at line 225 of file Mac80211.cc.
References addNeighbor(), contention, currentIFS, MacToPhyInterface::getRadioState(), handleBroadcastMsg(), handleMsgForMe(), handleMsgNotForMe(), BaseMacLayer::myMacAddr, BaseMacLayer::phy, and Radio::RX.
{ Mac80211Pkt *af = static_cast<Mac80211Pkt *>(msg); int radioState = phy->getRadioState(); if(radioState == Radio::RX) { // end of the reception debugEV << " handleLowerMsg frame " << af << " received\n"; addNeighbor(af); if (contention->isScheduled()) { error("Gaack! I am changing the IFS on an ongoing contention"); } currentIFS = DIFS; if(af->getDestAddr() == myMacAddr) { handleMsgForMe(af); } else if(af->getDestAddr() == L2BROADCAST) { handleBroadcastMsg(af); } else { handleMsgNotForMe(af, af->getDuration()); } } else { debugEV << " handleLowerMsg frame " << af << " deleted, strange race condition\n"; delete af; } }
void Mac80211::handleMsgForMe | ( | Mac80211Pkt * | af | ) | [protected] |
handle a message that was meant for me
Handle a packet for the node. The result of this reception is a function of the type of the received message (RTS,CTS,DATA, or ACK), and of the current state of the MAC (WFDATA, CONTEND, IDLE, WFCTS, or WFACK). Called by handleLowerMsg()
Definition at line 418 of file Mac80211.cc.
References contention, handleACKframe(), handleCTSframe(), handleDATAframe(), handleRTSframe(), state, stateName(), and switching.
Referenced by handleLowerMsg().
{ debugEV << "handle msg for me " << af->getName() << " in " << stateName(state) << "\n"; switch (state) { case IDLE: // waiting for the end of the contention period case CONTEND: // or waiting for RTS // RTS or DATA accepted if (af->getKind() == RTS) { assert(!contention->isScheduled()); //suspendContention(); handleRTSframe(af); } else if (af->getKind() == DATA) { assert(!contention->isScheduled()); //suspendContention(); handleDATAframe(af); } else { error("in handleMsgForMe() IDLE/CONTEND, strange message %s", af->getName()); } break; case WFDATA: // waiting for DATA if (af->getKind() == DATA) { handleDATAframe(af); } else { EV << "unexpected message -- probably a collision of RTSs\n"; delete af; } break; case WFACK: // waiting for ACK if (af->getKind() == ACK) { handleACKframe(af); } else { error("in handleMsgForMe() WFACK, strange message %s", af->getName()); } delete af; break; case WFCTS: // The MAC is waiting for CTS if (af->getKind() == CTS) { handleCTSframe(af); } else { EV << "unexpected msg -- deleted \n"; delete af; } break; case QUIET: // the node is currently deferring. // cannot handle any packet with its MAC adress delete af; break; case BUSY: // currently transmitting an ACK or a BROADCAST packet if(switching) { EV << "message received during radio state switchover\n"; delete af; } else { error("logic error: node is currently transmitting, can not receive " "(does the physical layer do its job correctly?)"); } break; default: error("unknown state %d", state); } }
void Mac80211::handleMsgNotForMe | ( | cMessage * | af, | |
simtime_t | duration | |||
) | [protected] |
handle a message that is not for me or errornous
Handle all ACKs,RTS, CTS, or DATA not for the node. If RTS/CTS is used the node must stay quiet until the current handshake between the two communicating nodes is over. This is done by scheduling the timer message nav (Network Allocation Vector). Without RTS/CTS a new contention is started. If an error occured the node must defer for EIFS. Called by handleLowerMsg()
Definition at line 336 of file Mac80211.cc.
References beginNewCycle(), contention, currentIFS, fromUpperLayer, longRetryCounter, nav, rtsCts(), setState(), shortRetryCounter, state, and timeout.
Referenced by handleLowerControl(), and handleLowerMsg().
{ debugEV << "handle msg not for me " << af->getName() << "\n"; // if the duration of the packet is null, then do nothing (to avoid // the unuseful scheduling of a self message) if(duration != 0) { // the node is already deferring if (state == QUIET) { // the current value of the NAV is not sufficient if (nav->getArrivalTime() < simTime() + duration) { cancelEvent(nav); scheduleAt(simTime() + duration, nav); debugEV << "NAV timer started for: " << duration << " State QUIET\n"; } } // other states else { // if the MAC wait for another frame, it can delete its time out // (exchange is aborted) if (timeout->isScheduled()) { cancelEvent(timeout); if(state == WFACK) { fromUpperLayer.front()->setRetry(true); } if((state == WFACK) || (state == WFCTS)) { if(rtsCts(fromUpperLayer.front())) { longRetryCounter++; } else { shortRetryCounter++; } } } // the node must defer for the time of the transmission scheduleAt(simTime() + duration, nav); debugEV << "NAV timer started, not QUIET: " << duration << endl; assert(!contention->isScheduled()); //suspendContention(); setState(QUIET); } } if((af->getKind() == Decider80211::BITERROR) || (af->getKind() == Decider80211::COLLISION)) { assert(!contention->isScheduled()); //suspendContention(); //if (contention->isScheduled()) { // error("Gaack! I am changing the IFS on an ongoing contention"); //} //handle broken cts and ACK frames if(state == WFCTS) { assert(timeout->isScheduled()); cancelEvent(timeout); rtsTransmissionFailed(); } else if(state == WFACK) { assert(timeout->isScheduled()); cancelEvent(timeout); dataTransmissionFailed(); } currentIFS = EIFS; } beginNewCycle(); delete af; }
void Mac80211::handleNavTimer | ( | ) | [protected] |
NAV timer expired, the exchange of messages of other stations is done.
Handle the NAV timer (end of a defering period). Called by HandleTimer(cMessage* msg)
Definition at line 649 of file Mac80211.cc.
References beginNewCycle(), and state.
Referenced by handleSelfMsg().
{ if (state != QUIET) error("logic error: expiration of the NAV timer outside of the state QUIET, should not happen"); // if there's a packet to send and if the channel is free, then start a new contention period // lmf - Potential race condition: If nav expires at same time // medium becomes IDLE (usual case), but the navTimeout comes // before the mediumIndication, then the medium is still BUSY when // beginNewCycle() is called, so the backoff doesn't resume. // Usually it doesn't matter, since there is also an arriving // frame and so beginNewCycle() will be called again by the // handleMsgXXX. But if there is no frame (mobility, exposed // terminal, etc) there's a potential problem. beginNewCycle(); }
void Mac80211::handleRTSframe | ( | Mac80211Pkt * | af | ) | [protected] |
Handle aframe wich is expected to be an RTS. Called by HandleMsgForMe()
Definition at line 499 of file Mac80211.cc.
References endSifs, and BaseLayer::sendControlDown().
Referenced by handleMsgForMe().
{ if(endSifs->isScheduled()) error("Mac80211::handleRTSframe when SIFS scheduled"); // wait a short interframe space endSifs->setContextPointer(af); sendControlDown(endSifs); //scheduleAt(simTime() + SIFS, endSifs); }
void Mac80211::handleSelfMsg | ( | cMessage * | msg | ) | [protected, virtual] |
Handle self messages such as timer...
handle timers
Reimplemented from BaseMacLayer.
Definition at line 306 of file Mac80211.cc.
References handleNavTimer(), and handleTimeoutTimer().
{ debugEV << simTime() << " handleSelfMsg " << msg->getName() << "\n"; switch (msg->getKind()) { // the MAC was waiting for a CTS, a DATA, or an ACK packet but the timer has expired. case TIMEOUT: handleTimeoutTimer(); // noch zu betrachten.. break; // the MAC was waiting because an other communication had won the channel. This communication is now over case NAV: handleNavTimer(); // noch zu betrachten... break; default: error("unknown timer type"); } }
void Mac80211::handleTimeoutTimer | ( | ) | [protected] |
handle time out
Handle the time out timer. Called by handleTimer(cMessage* msg)
Definition at line 692 of file Mac80211.cc.
References beginNewCycle(), state, and stateName().
Referenced by handleSelfMsg().
{ debugEV << simTime() << " handleTimeoutTimer " << stateName(state) << "\n"; if(state == WFCTS) { rtsTransmissionFailed(); } else if(state == WFACK) { dataTransmissionFailed(); } // if there's a packet to send and if the channel is free then // start a new contention period if (state != QUIET) beginNewCycle(); }
void Mac80211::handleUpperMsg | ( | cMessage * | msg | ) | [protected, virtual] |
Handle messages from upper layer.
This implementation does not support fragmentation, so it is tested if the maximum length of the MPDU is exceeded.
Reimplemented from BaseMacLayer.
Definition at line 144 of file Mac80211.cc.
References beginNewCycle(), encapsMsg(), endSifs, fromUpperLayer, BaseMacLayer::PACKET_DROPPED, queueLength, BaseLayer::sendControlUp(), and state.
{ cPacket* pkt = static_cast<cPacket*>(msg); debugEV << "Mac80211::handleUpperMsg " << msg->getName() << "\n"; if (pkt->getBitLength() > 18496){ error("packet from higher layer (%s)%s is too long for 802.11b, %d bytes (fragmentation is not supported yet)", pkt->getClassName(), pkt->getName(), pkt->getByteLength()); } if(fromUpperLayer.size() == queueLength) { //TODO: CSMAMacLayer does create a new mac packet and sends it up. Maybe settle on a consistent solution here msg->setName("MAC ERROR"); msg->setKind(PACKET_DROPPED); sendControlUp(msg); debugEV << "packet " << msg << " received from higher layer but MAC queue is full, signalling error\n"; return; } Mac80211Pkt *mac = encapsMsg(pkt); debugEV << "packet " << pkt << " received from higher layer, dest=" << mac->getDestAddr() << ", encapsulated\n"; fromUpperLayer.push_back(mac); // If the MAC is in the IDLE state, then start a new contention period if (state == IDLE && !endSifs->isScheduled()) { beginNewCycle(); } else { debugEV << "enqueued, will be transmitted later\n"; } }
void Mac80211::initialize | ( | int | stage | ) | [virtual] |
Initialization of the module and some variables.
First we have to initialize the module from which we derived ours, in this case BaseLayer.
Reimplemented from BaseMacLayer.
Reimplemented in Mac80211MultiChannel.
Definition at line 35 of file Mac80211.cc.
References autoBitrate, backoff(), bitrate, centerFreq, MacToPhyInterface::CHANNEL_SENSE_REQUEST, contention, currentIFS, FWMath::dBm2mW(), defaultBitrate, delta, endSifs, fsc, BaseMacLayer::getConnectionManager(), MacToPhyInterface::getCurrentRadioChannel(), longRetryCounter, BaseMacLayer::myMacAddr, nav, neighborhoodCacheMaxAge, neighborhoodCacheSize, BaseMacLayer::phy, queueLength, remainingBackoff, rtsCtsThreshold, senseChannelWhileIdle(), shortRetryCounter, snrThresholds, state, switching, timeout, and txPower.
{ BaseMacLayer::initialize(stage); if (stage == 0) { debugEV << "Initializing stage 0\n"; switching = false; fsc = intrand(0x7FFFFFFF); if(fsc == 0) fsc = 1; debugEV << " fsc: " << fsc << "\n"; queueLength = hasPar("queueLength") ? par("queueLength").longValue() : 10; // timers timeout = new cMessage("timeout", TIMEOUT); nav = new cMessage("NAV", NAV); contention = new ChannelSenseRequest("contention", MacToPhyInterface::CHANNEL_SENSE_REQUEST); contention->setSenseMode(UNTIL_BUSY); endSifs = new ChannelSenseRequest("end SIFS", MacToPhyInterface::CHANNEL_SENSE_REQUEST); endSifs->setSenseMode(UNTIL_BUSY); endSifs->setSenseTimeout(SIFS); state = IDLE; longRetryCounter = 0; shortRetryCounter = 0; rtsCtsThreshold = hasPar("rtsCtsThreshold") ? par("rtsCtsThreshold").longValue() : 1; currentIFS = EIFS; autoBitrate = hasPar("autoBitrate") ? par("autoBitrate").boolValue() : false; txPower = hasPar("txPower") ? par("txPower").doubleValue() : 110.11; delta = 1E-9; debugEV << "SIFS: " << SIFS << " DIFS: " << DIFS << " EIFS: " << EIFS << endl; } else if(stage == 1) { BaseConnectionManager* cc = getConnectionManager(); if(cc->hasPar("pMax") && txPower > cc->par("pMax").doubleValue()) opp_error("TranmitterPower can't be bigger than pMax in ConnectionManager! " "Please adjust your omnetpp.ini file accordingly."); int channel = phy->getCurrentRadioChannel(); if(!(1<=channel && channel<=14)) { opp_error("Radio set to invalid channel %d. Please make sure the" " phy modules parameter \"initialRadioChannel\" is set to" " a valid 802.11 channel (1 to 14)!", channel); } centerFreq = CENTER_FREQUENCIES[channel]; bool found = false; bitrate = hasPar("bitrate") ? par("bitrate").doubleValue() : BITRATES_80211[0]; for(int i = 0; i < 4; i++) { if(bitrate == BITRATES_80211[i]) { found = true; break; } } if(!found) bitrate = BITRATES_80211[0]; defaultBitrate = bitrate; snrThresholds.push_back(hasPar("snr2Mbit") ? par("snr2Mbit").doubleValue() : 100); snrThresholds.push_back(hasPar("snr5Mbit") ? par("snr5Mbit").doubleValue() : 100); snrThresholds.push_back(hasPar("snr11Mbit") ? par("snr11Mbit").doubleValue() : 100); snrThresholds.push_back(111111111); // sentinel neighborhoodCacheSize = hasPar("neighborhoodCacheSize") ? par("neighborhoodCacheSize").longValue() : 0; neighborhoodCacheMaxAge = hasPar("neighborhoodCacheMaxAge") ? par("neighborhoodCacheMaxAge").longValue() : 10000; debugEV << " MAC Address: " << myMacAddr << " rtsCtsThreshold: " << rtsCtsThreshold << " bitrate: " << bitrate << " channel: " << channel << " autoBitrate: " << autoBitrate << " 2MBit: " << snrThresholds[0] << " 5.5MBit: " <<snrThresholds[1] << " 11MBit: " << snrThresholds[2] << " neighborhoodCacheSize " << neighborhoodCacheSize << " neighborhoodCacheMaxAge " << neighborhoodCacheMaxAge << endl; for(int i = 0; i < 3; i++) { snrThresholds[i] = FWMath::dBm2mW(snrThresholds[i]); } remainingBackoff = backoff(); senseChannelWhileIdle(remainingBackoff + currentIFS); } }
simtime_t Mac80211::packetDuration | ( | double | bits, | |
double | br | |||
) | [protected] |
computes the duration of a transmission over the physical channel, given a certain bitrate
Computes the duration of the transmission of a frame over the physical channel. 'bits' should be the total length of the mac packet in bits excluding the phy header length.
Definition at line 1138 of file Mac80211.cc.
References BaseMacLayer::phyHeaderLength.
Referenced by sendACKframe(), sendBROADCASTframe(), sendCTSframe(), sendDATAframe(), sendRTSframe(), and timeOut().
{ return bits / br + phyHeaderLength / BITRATE_HEADER; }
void Mac80211::sendACKframe | ( | Mac80211Pkt * | af | ) | [protected] |
send Acknoledgement
Send an ACK frame.Called by HandleEndSifsTimer()
Definition at line 814 of file Mac80211.cc.
References createSignal(), PhyToMacControlInfo::getDeciderResult(), BaseMacLayer::myMacAddr, packetDuration(), BaseLayer::sendDown(), setState(), and txPower.
Referenced by handleEndSifsTimer().
{ Mac80211Pkt *frame = new Mac80211Pkt("wlan-ack"); PhyToMacControlInfo* phyCtrlInfo = static_cast<PhyToMacControlInfo*>(af->removeControlInfo()); double br = static_cast<const DeciderResult80211*>(phyCtrlInfo->getDeciderResult())->getBitrate(); delete phyCtrlInfo; phyCtrlInfo = 0; Signal* signal = createSignal(simTime(), packetDuration(LENGTH_ACK, br), txPower, br); MacToPhyControlInfo *pco = new MacToPhyControlInfo(signal); frame->setControlInfo(pco); frame->setKind(ACK); frame->setBitLength((int)LENGTH_ACK); // the dest address must be the src adress of the RTS or the DATA // packet received. The src adress is the adress of the node frame->setSrcAddr(myMacAddr); frame->setDestAddr(af->getSrcAddr()); frame->setDuration(0); sendDown(frame); debugEV << "sent ACK frame!\n"; // update state and display setState(BUSY); }
void Mac80211::sendBROADCASTframe | ( | ) | [protected] |
send broadcast frame
Send a BROADCAST frame.Called by handleContentionTimer()
Definition at line 929 of file Mac80211.cc.
References createSignal(), fromUpperLayer, packetDuration(), retrieveBitrate(), BaseLayer::sendDown(), setState(), and txPower.
Referenced by handleEndContentionTimer().
{ // send a copy of the frame in front of the queue Mac80211Pkt *frame = static_cast<Mac80211Pkt *>(fromUpperLayer.front()->dup()); double br = retrieveBitrate(frame->getDestAddr()); simtime_t duration = packetDuration(frame->getBitLength(), br); Signal* signal = createSignal(simTime(), duration, txPower, br); MacToPhyControlInfo *pco = new MacToPhyControlInfo(signal); frame->setControlInfo(pco); frame->setKind(BROADCAST); sendDown(frame); // update state and display setState(BUSY); }
void Mac80211::sendCTSframe | ( | Mac80211Pkt * | af | ) | [protected] |
send CTS frame
Send a CTS frame.Called by HandleEndSifsTimer()
Definition at line 892 of file Mac80211.cc.
References createSignal(), PhyToMacControlInfo::getDeciderResult(), BaseMacLayer::myMacAddr, packetDuration(), BaseLayer::sendDown(), setState(), and txPower.
Referenced by handleEndSifsTimer().
{ Mac80211Pkt *frame = new Mac80211Pkt("wlan-cts"); PhyToMacControlInfo* phyCtrlInfo = static_cast<PhyToMacControlInfo*>(af->removeControlInfo()); double br = static_cast<const DeciderResult80211*>(phyCtrlInfo->getDeciderResult())->getBitrate(); delete phyCtrlInfo; phyCtrlInfo = 0; Signal* signal = createSignal(simTime(), packetDuration(LENGTH_CTS, br), txPower, br); MacToPhyControlInfo *pco = new MacToPhyControlInfo(signal); frame->setControlInfo(pco); frame->setKind(CTS); frame->setBitLength((int)LENGTH_CTS); // the dest adress must be the src adress of the RTS received. The // src adress is the adress of the node frame->setSrcAddr(myMacAddr); frame->setDestAddr(af->getSrcAddr()); frame->setDuration(af->getDuration() - SIFS - packetDuration(LENGTH_CTS, br)); //scheduleAt(simTime() + af->getDuration() - packetDuration(LENGTH_ACK, br) - 2 * SIFS + delta, timeout); debugEV << " Mac80211::sendCTSframe duration: " << packetDuration(LENGTH_CTS, br) << " br: " << br << "\n"; // send CTS frame sendDown(frame); // update state and display setState(WFDATA); }
void Mac80211::sendDATAframe | ( | Mac80211Pkt * | af | ) | [protected, virtual] |
send data frame
Send a DATA frame. Called by HandleEndSifsTimer() or handleEndContentionTimer()
Definition at line 774 of file Mac80211.cc.
References createSignal(), fromUpperLayer, PhyToMacControlInfo::getDeciderResult(), BaseMacLayer::myMacAddr, packetDuration(), retrieveBitrate(), BaseLayer::sendDown(), setState(), shortRetryCounter, timeout, timeOut(), and txPower.
Referenced by handleEndContentionTimer(), and handleEndSifsTimer().
{ Mac80211Pkt *frame = static_cast<Mac80211Pkt *>(fromUpperLayer.front()->dup()); double br; if(af) { PhyToMacControlInfo* tmp = static_cast<PhyToMacControlInfo*>(af->removeControlInfo()); br = static_cast<const DeciderResult80211*>(tmp->getDeciderResult())->getBitrate(); delete tmp; } else { br = retrieveBitrate(frame->getDestAddr()); if(shortRetryCounter) frame->setRetry(true); } simtime_t duration = packetDuration(frame->getBitLength(), br); Signal* signal = createSignal(simTime(), duration, txPower, br); MacToPhyControlInfo *pco = new MacToPhyControlInfo(signal); // build a copy of the frame in front of the queue' frame->setControlInfo(pco); frame->setSrcAddr(myMacAddr); frame->setKind(DATA); frame->setDuration(SIFS + packetDuration(LENGTH_ACK, br)); // schedule time out scheduleAt(simTime() + timeOut(DATA, br), timeout); debugEV << "sending DATA to " << frame->getDestAddr() << " with bitrate " << br << endl; // send DATA frame sendDown(frame); // update state and display setState(WFACK); }
void Mac80211::sendRTSframe | ( | ) | [protected, virtual] |
send RTS frame
Send a RTS frame.Called by handleContentionTimer()
Definition at line 850 of file Mac80211.cc.
References createSignal(), fromUpperLayer, packetDuration(), retrieveBitrate(), BaseLayer::sendDown(), setState(), timeout, timeOut(), and txPower.
Referenced by handleEndContentionTimer().
{ Mac80211Pkt *frame = new Mac80211Pkt("wlan-rts"); const Mac80211Pkt* frameToSend = fromUpperLayer.front(); double br = retrieveBitrate(frameToSend->getDestAddr()); Signal* signal = createSignal(simTime(), packetDuration(LENGTH_RTS, br), txPower, br); MacToPhyControlInfo *pco = new MacToPhyControlInfo(signal); frame->setControlInfo(pco); frame->setKind(RTS); frame->setBitLength((int)LENGTH_RTS); // the src adress and dest address are copied in the frame in the queue (frame to be sent) frame->setSrcAddr(frameToSend->getSrcAddr()); frame->setDestAddr(frameToSend->getDestAddr()); double packetSize = frameToSend->getBitLength(); frame->setDuration(3 * SIFS + packetDuration(LENGTH_CTS, br) + packetDuration(packetSize, br) + packetDuration(LENGTH_ACK, br)); debugEV << " Mac80211::sendRTSframe duration: " << packetDuration(LENGTH_RTS, br) << " br: " << br << "\n"; // schedule time-out scheduleAt(simTime() + timeOut(RTS, br), timeout); // send RTS frame sendDown(frame); // update state and display setState(WFCTS); }
void Mac80211::senseChannelWhileIdle | ( | simtime_t | duration | ) | [protected] |
Starts a channel sense request which sense the channel for the passed duration or until the channel is busy.
Used during contend state to check if the channel is free.
Definition at line 129 of file Mac80211.cc.
References chSenseStart, contention, and BaseLayer::sendControlDown().
Referenced by beginNewCycle(), and initialize().
{ if(contention->isScheduled()) { error("Cannot start a new channel sense request because already sensing the channel!"); } chSenseStart = simTime(); contention->setSenseTimeout(duration); sendControlDown(contention); }
void Mac80211::testMaxAttempts | ( | ) | [protected] |
Test if maximum number of retries to transmit is exceeded.
Test if the maximal retry limit is reached, and delete the frame to send in this case.
Definition at line 1026 of file Mac80211.cc.
References fromUpperLayer, longRetryCounter, BaseMacLayer::PACKET_DROPPED, BaseLayer::sendControlUp(), and shortRetryCounter.
Referenced by beginNewCycle().
{ if ((longRetryCounter >= LONG_RETRY_LIMIT) || (shortRetryCounter >= SHORT_RETRY_LIMIT)) { debugEV << "retry limit reached src: "<< shortRetryCounter << " lrc: " << longRetryCounter << endl; // initialize counter longRetryCounter = 0; shortRetryCounter = 0; // delete the frame to transmit Mac80211Pkt *temp = fromUpperLayer.front(); fromUpperLayer.pop_front(); temp->setName("MAC ERROR"); temp->setKind(PACKET_DROPPED); sendControlUp(temp); } }
simtime_t Mac80211::timeOut | ( | Mac80211MessageKinds | type, | |
double | br | |||
) | [protected] |
return a timeOut value for a certain type of frame
Handle change nofitications. In this layer it is usually information about the radio channel, i.e. if it is IDLE etc. Return a time-out value for a type of frame. Called by SendRTSframe, sendCTSframe, etc.
Definition at line 1113 of file Mac80211.cc.
References delta, fromUpperLayer, and packetDuration().
Referenced by sendDATAframe(), and sendRTSframe().
{ simtime_t time_out = 0; switch (type) { case RTS: time_out = SIFS + packetDuration(LENGTH_RTS, br) + ST + packetDuration(LENGTH_CTS, br) + delta; debugEV << " Mac80211::timeOut RTS " << time_out << "\n"; break; case DATA: time_out = SIFS + packetDuration(fromUpperLayer.front()->getBitLength(), br) + ST + packetDuration(LENGTH_ACK, br) + delta; debugEV << " Mac80211::timeOut DATA " << time_out << "\n"; break; default: EV << "Unused frame type was given when calling timeOut(), this should not happen!\n"; } return time_out; }
double Mac80211::defaultBitrate [protected] |
Default bitrate.
The default bitrate must be set in the omnetpp.ini. It is used whenever an auto bitrate is not appropriate, like broadcasts.
Definition at line 267 of file Mac80211.h.
Referenced by initialize(), and retrieveBitrate().
int Mac80211::fsc [protected] |
sequence control -- to detect duplicates
Definition at line 333 of file Mac80211.h.
Referenced by encapsMsg(), and initialize().
unsigned Mac80211::longRetryCounter [protected] |
Number of frame transmission attempt.
Incremented when the SHORT_RETRY_LIMIT is hit, or when an ACK or CTS is missing.
Definition at line 299 of file Mac80211.h.
Referenced by backoff(), handleACKframe(), handleEndTransmission(), handleMsgNotForMe(), initialize(), retrieveBitrate(), and testMaxAttempts().
bool Mac80211::switching [protected] |
take care of switchover times
Definition at line 330 of file Mac80211.h.
Referenced by handleBroadcastMsg(), handleMsgForMe(), and initialize().