Classes | Public Types | Public Member Functions | Protected Types | Protected Member Functions | Protected Attributes

Mac80211 Class Reference
[macLayer - MAC layer modulesIEEE 802.11 - Classes for the IEEE 802.11 implementation of MiXiM]

An implementation of the 802.11b MAC. More...

#include <Mac80211.h>

Inherits BaseMacLayer.

Inherited by Mac80211MultiChannel.

Collaboration diagram for Mac80211:
Collaboration graph
[legend]

List of all members.

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< NeighborEntryNeighborList
 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.
SignalcreateSignal (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

Detailed Description

An implementation of the 802.11b MAC.

For more info, see the NED file.

Author:
David Raguin, Karl Wessel (port for MiXiM)

Definition at line 39 of file Mac80211.h.


Member Enumeration Documentation

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]

Definition of the timer types

Definition at line 58 of file Mac80211.h.

                   {
      TIMEOUT,
      NAV
    };


Member Function Documentation

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;
}


Member Data Documentation

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().


The documentation for this class was generated from the following files: