Mac80211 Class Reference

#include <Mac80211.h>

Inheritance diagram for Mac80211:

WirelessMacBase INotifiable List of all members.

Detailed Description

An implementation of the 802.11b MAC.

For more info, see the NED file.

Author:
David Raguin


Public Member Functions

 Mac80211 ()
virtual ~Mac80211 ()

Protected Member Functions

virtual int numInitStages () const
 Initialization of the module and some variables.
virtual void initialize (int)
 Initialization of the module and some variables.
void registerInterface ()
 Register the interface in InterfaceTable.
virtual void receiveChangeNotification (int category, cPolymorphic *details)
 Called by the NotificationBoard whenever a change occurs we're interested in.
virtual void handleSelfMsg (cMessage *)
 Handle self messages such as timer...
virtual void handleUpperMsg (cMessage *)
 Handle messages from upper layer.
virtual void handleLowerMsg (cMessage *)
 Handle messages from lower layer.
virtual void handleEndContentionTimer ()
 handle end of contention
void handleMsgNotForMe (Mac80211Pkt *)
 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 handleEndTransmissionTimer ()
 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 *)
virtual void sendDATAframe ()
 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
Mac80211PktencapsMsg (cMessage *netw)
 encapsulate packet
void decapsulateAndSendUp (Mac80211Pkt *frame)
 decapsulate packet and send to higher layer
virtual Mac80211PktbuildDATAframe ()
 build a data frame
Mac80211PktbuildACKframe (Mac80211Pkt *)
 build an ACK
Mac80211PktbuildCTSframe (Mac80211Pkt *)
 build a CTS frame
virtual Mac80211PktbuildRTSframe ()
 build an RTS frame
Mac80211PktbuildBROADCASTframe ()
 build a broadcast frame
virtual void beginNewCycle ()
 start a new contention period
double backoff ()
 Compute a backoff value.
int contentionWindow ()
 Compute a new contention window.
void testMaxAttempts ()
 Test if maximum number of retries to transmit is exceeded.
double timeOut (_802_11frameType type, double last_frame_duration)
 return a timeOut value for a certain type of frame
double packetDuration (int bits)
 computes the duration of a transmission over the physical channel
const char * stateName (State state)
 Produce a readable name of the given state.
const char * timerTypeName (int type)
 Produce a readable name of the given timer type.
const char * pktTypeName (int type)
 Produce a readable name of the given packet type.
void setState (State state)
 Sets the state, and produces a log message in between.

Protected Attributes

MACAddress myMacAddr
 mac address
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.
cMessage * contention
 Timer used for contention periods.
cMessage * endTransmission
 Timer used to indicate the end of the transmission of an ACK or a BROADCAST packet.
cMessage * endSifs
 Timer used to indicate the end of a SIFS.
double EIFS
 extended interframe space
double BW
 Variable to store the current backoff value.
State state
 Current state of the MAC.
RadioState::State radioState
 Current state of the radio (kept updated by receiveChangeNotification()).
int maxQueueSize
 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.
int retryCounter
 Number of frame transmission attempt.
bool tryWithoutBackoff
 If there's a new packet to send and the channel is free, no backoff is needed.
bool rtsCts
 true if Rts/Cts is used, false if not; can be set in omnetpp.ini
double delta
 Very small value used in timer scheduling in order to avoid multiple changements of state in the same simulation time.
double bitrate
 The bitrate should be set in omnetpp.ini; be sure to use a valid 802.11 bitrate.
int broadcastBackoff
 Should be set in the omnetpp.ini.

Private Types

typedef std::list< Mac80211Pkt * > MacPktList
 TIMEOUT
 NAV
 CONTENTION
 END_TRANSMISSION
 END_SIFS
 WFDATA = 0
 QUIET = 1
 IDLE = 2
 CONTEND = 3
 WFCTS = 4
 WFACK = 5
 BUSY = 6
enum  timerType {
  TIMEOUT, NAV, CONTENTION, END_TRANSMISSION,
  END_SIFS
}
enum  State {
  WFDATA = 0, QUIET = 1, IDLE = 2, CONTEND = 3,
  WFCTS = 4, WFACK = 5, BUSY = 6
}


Member Typedef Documentation

typedef std::list<Mac80211Pkt*> Mac80211::MacPktList [private]


Member Enumeration Documentation

enum Mac80211::State [private]

Definition of the states

Enumerator:
WFDATA 
QUIET 
IDLE 
CONTEND 
WFCTS 
WFACK 
BUSY 
00054                {
00055       WFDATA = 0, // waiting for data packet
00056       QUIET = 1,  // waiting for the communication between two other nodes to end
00057       IDLE = 2,   // no packet to send, no packet receiving
00058       CONTEND = 3,// contention state (battle for the channel)
00059       WFCTS = 4,  // RTS sent, waiting for CTS
00060       WFACK = 5,  // DATA packet sent, waiting for ACK
00061       BUSY = 6    // during transmission of an ACK or a BROADCAST packet
00062     };

enum Mac80211::timerType [private]

Definition of the timer types

Enumerator:
TIMEOUT 
NAV 
CONTENTION 
END_TRANSMISSION 
END_SIFS 
00045                    {
00046       TIMEOUT,
00047       NAV,
00048       CONTENTION,
00049       END_TRANSMISSION,
00050       END_SIFS
00051     };


Constructor & Destructor Documentation

Mac80211::Mac80211 (  ) 

00032 {
00033     timeout = nav = contention = endTransmission = endSifs = NULL;
00034 }

Mac80211::~Mac80211 (  )  [virtual]

00037 {
00038     cancelAndDelete(timeout);
00039     cancelAndDelete(nav);
00040     cancelAndDelete(contention);
00041     cancelAndDelete(endTransmission);
00042     cancelAndDelete(endSifs);
00043 }


Member Function Documentation

double Mac80211::backoff (  )  [protected]

Compute a backoff value.

Compute the backoff value.

00843 {
00844     // the MAC has won the previous contention. We have to compute a new
00845     // backoff window
00846     if (BW == 0) {
00847         int CW = contentionWindow();
00848         EV << "generating backoff for CW: " << CW << endl;
00849         BW = ((double) intrand(CW + 1)) * ST;
00850     }
00851     // CW is the contention window (see the function). ST is the
00852     // slot time.  else we take the old value of BW, in order to give a
00853     // bigger priority to a node which has lost a previous contention
00854     // period.
00855     EV << "backing off for: " << BW + DIFS << endl;
00856     return BW;
00857 }

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

00795 {
00796     EV << "beginning new contention cycle\n";
00797 
00798     // before trying to send one more time a packet, test if the
00799     // maximum retry limit is reached. If it is the case, then
00800     // delete the packet and send the next packet.
00801     testMaxAttempts();
00802 
00803     if (!fromUpperLayer.empty())
00804     {
00805 
00806         // look if the next packet is unicast or broadcast
00807         nextIsBroadcast = (((Mac80211Pkt *) fromUpperLayer.front())->getDestAddr().isBroadcast());
00808 
00809         // print("next is broadcast = "<<nextIsBroadcast);
00810 
00811         // if the channel is free then wait a random time and transmit
00812         if (radioState == RadioState::IDLE)
00813         {
00814             // if channel is idle AND I was not the last one that transmitted
00815             // data: no backoff
00816             if (tryWithoutBackoff)
00817             {
00818                 EV << "trying to send without backoff...\n";
00819                 scheduleAt(simTime() + DIFS, contention);
00820             }
00821             else
00822             {
00823                 // backoff!
00824                 scheduleAt(simTime() + backoff() + DIFS, contention);
00825             }
00826         }
00827         tryWithoutBackoff = false;
00828 
00829         // else wait until the channel gets free; the state is now contend
00830         setState(CONTEND);
00831     }
00832     else
00833     {
00834         tryWithoutBackoff = false;
00835         setState(IDLE);
00836     }
00837 }

Mac80211Pkt * Mac80211::buildACKframe ( Mac80211Pkt af  )  [protected]

build an ACK

Build an ACK frame. Called by sendACKframe()

00723 {
00724     Mac80211Pkt *frame = new Mac80211Pkt("wlan-ack");
00725     frame->setKind(ACK);
00726     frame->setLength(LENGTH_ACK);
00727 
00728     // the dest address must be the src adress of the RTS or the DATA
00729     // packet received. The src adress is the adress of the node
00730     frame->setSrcAddr(myMacAddr);
00731     frame->setDestAddr(af->getSrcAddr());
00732     frame->setDuration(0);
00733 
00734     return frame;
00735 }

Mac80211Pkt * Mac80211::buildBROADCASTframe (  )  [protected]

build a broadcast frame

Build a BROADCAST frame. Called sendBROADCASTframe()

00779 {
00780     // send a copy of the frame in front of the queue
00781     Mac80211Pkt *frame = (Mac80211Pkt *) (fromUpperLayer.front())->dup();
00782     frame->setKind(BROADCAST);
00783     return frame;
00784 }

Mac80211Pkt * Mac80211::buildCTSframe ( Mac80211Pkt af  )  [protected]

build a CTS frame

Build a CTS frame. Called by sendCTSframe()

00761 {
00762     Mac80211Pkt *frame = new Mac80211Pkt("wlan-cts");
00763     frame->setKind(CTS);
00764     frame->setLength(LENGTH_CTS);
00765 
00766     // the dest adress must be the src adress of the RTS received. The
00767     // src adress is the adress of the node
00768     frame->setSrcAddr(myMacAddr);
00769     frame->setDestAddr(af->getSrcAddr());
00770     frame->setDuration(af->getDuration() - SIFS - packetDuration(LENGTH_CTS));
00771 
00772     return frame;
00773 }

Mac80211Pkt * Mac80211::buildDATAframe (  )  [protected, virtual]

build a data frame

Build a DATA frame. Called by sendDATAframe()

00705 {
00706     // build a copy of the frame in front of the queue
00707     Mac80211Pkt *frame = (Mac80211Pkt *) (fromUpperLayer.front())->dup();
00708     frame->setSrcAddr(myMacAddr);
00709     frame->setKind(DATA);
00710     if (rtsCts)
00711         frame->setDuration(SIFS + packetDuration(LENGTH_ACK));
00712     else
00713         frame->setDuration(0);
00714 
00715     return frame;
00716 }

Mac80211Pkt * Mac80211::buildRTSframe (  )  [protected, virtual]

build an RTS frame

Build a RTS frame. Called by sendRTSframe()

00742 {
00743     Mac80211Pkt *frame = new Mac80211Pkt("wlan-rts");
00744     frame->setKind(RTS);
00745     frame->setLength(LENGTH_RTS);
00746 
00747     // the src adress and dest address are copied in the frame in the queue (frame to be sent)
00748     frame->setSrcAddr(((Mac80211Pkt *) fromUpperLayer.front())->getSrcAddr());
00749     frame->setDestAddr(((Mac80211Pkt *) fromUpperLayer.front())->getDestAddr());
00750     frame->setDuration(3 * SIFS + packetDuration(LENGTH_CTS) +
00751                        packetDuration(fromUpperLayer.front()->length()) +
00752                        packetDuration(LENGTH_ACK));
00753 
00754     return frame;
00755 }

int Mac80211::contentionWindow (  )  [protected]

Compute a new contention window.

Compute the contention window with the binary backoff algorithm. Use the variable counter (attempts to transmit packet), the constant values CWmax (contention window maximum) and m (parameter for the initial backoff window, usally m=7). Called by backoff()

00867 {
00868     // the next packet is an unicast packet
00869     if (!nextIsBroadcast)
00870     {
00871         int cw = (CW_MIN + 1) * (1 << (retryCounter - 1)) - 1;
00872         // return the calculated value or CWmax if the maximal value is reached
00873         if (cw <= CW_MAX)
00874             return cw;
00875         else
00876             return CW_MAX;
00877     }
00878 
00879     // the next packet is broadcast : the contention window must be maximal
00880     else
00881         return broadcastBackoff;
00882 }

void Mac80211::decapsulateAndSendUp ( Mac80211Pkt frame  )  [protected]

decapsulate packet and send to higher layer

00190 {
00191     cMessage *msg = frame->decapsulate();
00192     // FIXME TBD set control info
00193     delete frame;
00194     sendUp(msg);
00195 }

Mac80211Pkt * Mac80211::encapsMsg ( cMessage *  netw  )  [protected]

encapsulate packet

Encapsulates the received network-layer packet into a MacPkt and set all needed header fields.

00171 {
00172     Mac80211Pkt *pkt = new Mac80211Pkt(netw->name());
00173     pkt->setLength(272);        // headerLength, including final CRC-field
00174 
00175     // copy dest address from the control info
00176     Ieee802Ctrl *ctrl = check_and_cast<Ieee802Ctrl *>(netw->removeControlInfo());
00177     pkt->setDestAddr(ctrl->getDest());
00178     delete ctrl;
00179 
00180     // set the src address to own mac address (nic module id())
00181     pkt->setSrcAddr(myMacAddr);
00182 
00183     // encapsulate the network packet
00184     pkt->encapsulate(netw);
00185 
00186     return pkt;
00187 }

void Mac80211::handleACKframe ( Mac80211Pkt af  )  [protected]

Handle a frame which is expected to be an ACK.Called by HandleMsgForMe(MAcawFrame* af)

00445 {
00446     EV << "handling Ack frame\n";
00447 
00448     // cancel time-out event
00449     cancelEvent(timeout);
00450 
00451     // the transmission is acknowledged : initialize long_retry_counter
00452     retryCounter = 1;
00453 
00454     // removes the acknowledged packet from the queue
00455     Mac80211Pkt *temp = fromUpperLayer.front();
00456     fromUpperLayer.pop_front();
00457     delete temp;
00458 
00459     // if thre's a packet to send and if the channel is free then start a new contention period
00460     beginNewCycle();
00461 }

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)

00484 {
00485     EV << "handle broadcast\n";
00486     if (state == BUSY)
00487         error("logic error: node is currently transmitting, can not receive "
00488               "(does the physical layer do its job correctly?)");
00489 
00490     decapsulateAndSendUp(af);
00491     if (state == CONTEND)
00492         beginNewCycle();
00493 }

void Mac80211::handleCTSframe ( Mac80211Pkt af  )  [protected]

Handle a CTS frame. Called by HandleMsgForMe(Mac80211Pkt* af)

00468 {
00469     // cancel time-out event
00470     cancelEvent(timeout);
00471 
00472     // wait a short interframe space
00473     endSifs->setContextPointer(af);
00474     scheduleAt(simTime() + SIFS, endSifs);
00475 }

void Mac80211::handleDATAframe ( Mac80211Pkt af  )  [protected]

Handle a frame which expected to be a DATA frame. Called by HandleMsgForMe()

00424 {
00425     if (rtsCts)
00426         cancelEvent(timeout);  // cancel time-out event
00427 
00428     // make a copy
00429     Mac80211Pkt *copy = (Mac80211Pkt *) af->dup();
00430 
00431     // pass the packet to the upper layer
00432     decapsulateAndSendUp(af);
00433 
00434     // wait a short interframe space
00435     endSifs->setContextPointer(copy);
00436     scheduleAt(simTime() + SIFS, endSifs);
00437 }

void Mac80211::handleEndContentionTimer (  )  [protected, virtual]

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

00502 {
00503     EV << "end contention period\n";
00504 
00505     if (state != CONTEND)
00506         error("logic error: expiration of the contention timer outside of CONTEND state, should not happen");
00507 
00508     // the node has won the channel, the backoff window is deleted and
00509     // will be new calculated in the next contention period
00510     BW = 0;
00511     // unicast packet
00512     if (!nextIsBroadcast)
00513     {
00514         if (rtsCts)
00515         {
00516             // send a RTS
00517             sendRTSframe();
00518             setState(WFCTS);
00519         }
00520         else
00521         {
00522             sendDATAframe();
00523             setState(WFACK);
00524         }
00525 
00526         // broadcast packet
00527     }
00528     else
00529     {
00530         sendBROADCASTframe();
00531 
00532         // removes the packet from the queue without waiting for an acknowledgement
00533         Mac80211Pkt *temp = fromUpperLayer.front();
00534         fromUpperLayer.pop_front();
00535         delete(temp);
00536     }
00537 }

void Mac80211::handleEndSifsTimer (  )  [protected]

handle end of SIFS

Handle the end sifs timer. Then sends a CTS, a DATA, or an ACK frame

00572 {
00573     Mac80211Pkt *frame = (Mac80211Pkt *) endSifs->contextPointer();
00574 
00575     switch (frame->kind())
00576     {
00577     case RTS:
00578         sendCTSframe(frame);
00579         break;
00580     case CTS:
00581         sendDATAframe();
00582         break;
00583     case DATA:
00584         sendACKframe(frame);
00585         break;
00586     default:
00587         error("logic error: end sifs timer when previously received packet is not RTS/CTS/DATA");
00588     }
00589 
00590     // don't need previous frame any more
00591     delete frame;
00592 }

void Mac80211::handleEndTransmissionTimer (  )  [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)

00600 {
00601     EV << "transmission of ACK/BROADCAST is over\n";
00602     if (state != BUSY)
00603         error("logic error: expiration of the end transmission timer outside the BUSY state, should not happen");
00604 
00605     // if there's a packet to send and if the channel is free, then start a new contention period
00606     beginNewCycle();
00607 }

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

Implements WirelessMacBase.

00204 {
00205     Mac80211Pkt *af = check_and_cast<Mac80211Pkt *>(msg);
00206 
00207     // end of the reception
00208     EV << "frame " << af << " received, kind = " << pktTypeName(af->kind()) << "\n";
00209 
00210     switch (af->kind())
00211     {
00212     case COLLISION: // packet lost or bit error
00213         delete af;
00214         if (state == CONTEND)
00215             beginNewCycle();
00216         break;
00217 
00218     case BITERROR:
00219         handleMsgNotForMe(af);
00220         break;
00221 
00222     case BROADCAST: // broadcast packet
00223         handleBroadcastMsg(af);
00224         break;
00225 
00226     default: // other packet
00227         if (af->getDestAddr() == myMacAddr)  // FIXME verify broadcast dest addr works!
00228             handleMsgForMe(af);
00229         else
00230             handleMsgNotForMe(af);
00231     }
00232 }

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

00347 {
00348     EV << "handle msg for me in state = " << stateName(state) << " with type = " << pktTypeName(af->kind()) << "\n";
00349 
00350     switch (state)
00351     {
00352     case IDLE:     // waiting for the end of the contention period
00353     case CONTEND:  // or waiting for RTS
00354 
00355         // RTS or DATA accepted
00356         if (af->kind() == RTS)
00357             handleRTSframe(af);
00358         else if (af->kind() == DATA)
00359             handleDATAframe(af);
00360         else
00361             // TODO: what if a late ACK has arrived?
00362             EV << "in handleMsgForMe() IDLE/CONTEND, strange message, darf das?\n";
00363         break;
00364 
00365     case WFDATA:  // waiting for DATA
00366 
00367         if (af->kind() == DATA)
00368             handleDATAframe(af);
00369         else
00370             EV << "in handleMsgForMe() WFDATA, strange message, darf das?\n";
00371         break;
00372 
00373     case WFACK:  // waiting for ACK
00374 
00375         if (af->kind() == ACK)
00376             handleACKframe(af);
00377         else
00378             EV << "in handleMsgForMe() WFACK, strange message, darf das?\n";
00379         delete af;
00380         break;
00381 
00382     case WFCTS:  // The MAC is waiting for CTS
00383 
00384         if (af->kind() == CTS)
00385             handleCTSframe(af);
00386         else
00387             EV << "in handleMsgForMe() WFCTS, strange message, darf das?\n";
00388         break;
00389 
00390 
00391     case QUIET: // the node is currently deferring.
00392 
00393         // cannot handle any packet with its MAC adress
00394         delete af;
00395         break;
00396 
00397     case BUSY: // currently transmitting an ACK or a BROADCAST packet
00398         error("logic error: node is currently transmitting, can not receive "
00399               "(does the physical layer do its job correctly?)");
00400         break;
00401 
00402     default:
00403         error("unknown state %d", state);
00404     }
00405 }

void Mac80211::handleMsgNotForMe ( Mac80211Pkt af  )  [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()

00281 {
00282     EV << "handle msg not for me\n";
00283 
00284     // if this packet  can not be correctly read
00285     if (af->kind() == BITERROR)
00286         af->setDuration(EIFS);
00287 
00288     // if the duration of the packet is null, then do nothing (to avoid
00289     // the unuseful scheduling of a self message)
00290     if (af->getDuration() != 0)
00291     {
00292 
00293         // the node is already deferring
00294         if (state == QUIET)
00295         {
00296             // the current value of the NAV is not sufficient
00297             if (nav->arrivalTime() < simTime() + af->getDuration())
00298             {
00299                 cancelEvent(nav);
00300                 scheduleAt(simTime() + af->getDuration(), nav);
00301                 EV << "NAV timer started for: " << af->getDuration() << " State QUIET\n";
00302             }
00303         }
00304 
00305         // other states
00306         else
00307         {
00308             // if the MAC wait for another frame, it can delete its time out
00309             // (exchange is aborted)
00310             if (timeout->isScheduled())
00311                 cancelEvent(timeout);
00312 
00313             // is state == WFCTS or WFACK, the data transfer has failed ...
00314 
00315             // the node must defer for the time of the transmission
00316             scheduleAt(simTime() + af->getDuration(), nav);
00317             EV << "NAV timer started, not QUIET: " << af->getDuration() << endl;
00318             setState(QUIET);
00319 
00320         }
00321     }
00322     if (!rtsCts)
00323     {                           // todo: Nachgucken: was passiert bei Error ohne rtsCts!
00324         if (state == CONTEND)
00325         {
00326             if (af->kind() == BITERROR)
00327             {
00328                 if (contention->isScheduled())
00329                     cancelEvent(contention);
00330                 scheduleAt(simTime() + backoff() + EIFS, contention);
00331             }
00332             else
00333                 beginNewCycle();
00334         }
00335     }
00336     delete af;
00337 }

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)

00544 {
00545     if (state != QUIET)
00546         error("logic error: expiration of the NAV timer outside of the state QUIET, should not happen");
00547 
00548     // if there's a packet to send and if the channel is free, then start a new contention period
00549     beginNewCycle();
00550 }

void Mac80211::handleRTSframe ( Mac80211Pkt af  )  [protected]

Handle aframe wich is expected to be an RTS. Called by HandleMsgForMe()

00412 {
00413     // wait a short interframe space
00414     endSifs->setContextPointer(af);
00415     scheduleAt(simTime() + SIFS, endSifs);
00416 }

void Mac80211::handleSelfMsg ( cMessage *  msg  )  [protected, virtual]

Handle self messages such as timer...

handle timers

Implements WirelessMacBase.

00238 {
00239     EV << "processing self message with type = " << timerTypeName(msg->kind()) << endl;
00240 
00241     switch (msg->kind())
00242     {
00243     case END_SIFS:
00244         handleEndSifsTimer();   // noch zu betrachten
00245         break;
00246 
00247     case END_TRANSMISSION:
00248         handleEndTransmissionTimer();   // noch zu betrachten
00249         break;
00250 
00251     case CONTENTION:
00252         handleEndContentionTimer();
00253         break;
00254 
00255         // the MAC was waiting for a CTS, a DATA, or an ACK packet but the timer has expired.
00256     case TIMEOUT:
00257         handleTimeoutTimer();   // noch zu betrachten..
00258         break;
00259 
00260         // the MAC was waiting because an other communication had won the channel. This communication is now over
00261     case NAV:
00262         handleNavTimer();       // noch zu betrachten...
00263         break;
00264 
00265     default:
00266         error("unknown timer type");
00267     }
00268 }

void Mac80211::handleTimeoutTimer (  )  [protected]

handle time out

Handle the time out timer. Called by handleTimer(cMessage* msg)

00557 {
00558     // if (state == WFCTS || state == WFACK)testMaxAttempts();
00559 
00560     // if there's a packet to send and if the channel is free then
00561     // start a new contention period
00562     if (state != QUIET)
00563         beginNewCycle();
00564 }

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.

Implements WirelessMacBase.

00138 {
00139     if (msg->byteLength() > 2312)
00140         error("packet from higher layer (%s)%s is too long for 802.11b, %d bytes (fragmentation is not supported yet)",
00141               msg->className(), msg->name(), msg->byteLength());
00142 
00143     if (maxQueueSize && fromUpperLayer.size() == maxQueueSize)
00144     {
00145         EV << "packet " << msg << " received from higher layer but MAC queue is full, deleting\n";
00146         delete msg;
00147         return;
00148     }
00149 
00150     Mac80211Pkt *mac = encapsMsg(msg);
00151     EV << "packet " << msg << " received from higher layer, dest=" << mac->getDestAddr() << ", encapsulated\n";
00152 
00153     fromUpperLayer.push_back(mac);
00154     // If the MAC is in the IDLE state, then start a new contention period
00155     if (state == IDLE && !endSifs->isScheduled())
00156     {
00157         tryWithoutBackoff = true;
00158         beginNewCycle();
00159     }
00160     else
00161     {
00162         EV << "enqueued, will be transmitted later\n";
00163     }
00164 }

void Mac80211::initialize ( int   )  [protected, virtual]

Initialization of the module and some variables.

Reimplemented from WirelessMacBase.

00046 {
00047     WirelessMacBase::initialize(stage);
00048 
00049     if (stage == 0)
00050     {
00051         EV << "Initializing stage 0\n";
00052         maxQueueSize = par("maxQueueSize");
00053 
00054         // subscribe for the information of the carrier sense
00055         nb->subscribe(this, NF_RADIOSTATE_CHANGED);
00056 
00057         // timers
00058         timeout = new cMessage("timeout", TIMEOUT);
00059         nav = new cMessage("NAV", NAV);
00060         contention = new cMessage("contention", CONTENTION);
00061         endTransmission = new cMessage("transmission", END_TRANSMISSION);
00062         endSifs = new cMessage("end SIFS", END_SIFS);
00063 
00064         BW = 0;
00065         state = IDLE;
00066         retryCounter = 1;
00067         broadcastBackoff = par("broadcastBackoff");
00068         rtsCts = par("rtsCts");
00069         bitrate = par("bitrate");
00070         delta = 1E-9; //XXX it's rather "epsilon", but this delta business looks a bit dodgy a solution anyway
00071 
00072         radioState = RadioState::IDLE; // until 1st receiveChangeNotification()
00073 
00074         EIFS = SIFS + DIFS + packetDuration(LENGTH_ACK);
00075         EV << "SIFS: " << SIFS << " DIFS: " << DIFS << " EIFS: " << EIFS << endl;
00076 
00077         // get registered in InterfaceTable
00078         registerInterface();
00079 
00080         WATCH(state);
00081         WATCH(radioState);
00082     }
00083 }

virtual int Mac80211::numInitStages (  )  const [inline, protected, virtual]

Initialization of the module and some variables.

00070 {return 2;}

double Mac80211::packetDuration ( int  bits  )  [protected]

computes the duration of a transmission over the physical channel

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.

00997 {
00998     return bits / bitrate + PHY_HEADER_LENGTH / BITRATE_HEADER;
00999 }

const char * Mac80211::pktTypeName ( int  type  )  [protected]

Produce a readable name of the given packet type.

01036 {
01037 #define CASE(x) case x: s=#x; break
01038     const char *s = "???";
01039     switch (type)
01040     {
01041         CASE(TIMEOUT);
01042         CASE(DATA);
01043         CASE(BROADCAST);
01044         CASE(RTS);
01045         CASE(CTS);
01046         CASE(ACK);
01047         CASE(ACKRTS);
01048         CASE(BEGIN_RECEPTION);
01049         CASE(BITERROR);
01050         CASE(COLLISION);
01051     }
01052     return s;
01053 #undef CASE
01054 }

void Mac80211::receiveChangeNotification ( int  category,
cPolymorphic *  details 
) [protected, virtual]

Called by the NotificationBoard whenever a change occurs we're interested in.

Handle change nofitications. In this layer it is usually information about the radio channel, i.e. if it is IDLE etc.

Implements INotifiable.

00910 {
00911     Enter_Method("receiveChangeNotification(%s, %s)", notificationCategoryName(category),
00912                  details?details->info().c_str() : "n/a");
00913     printNotificationBanner(category, details);
00914 
00915     if (category == NF_RADIOSTATE_CHANGED)
00916     {
00917         // update the local copy of the radio state
00918         radioState = check_and_cast<RadioState *>(details)->getState();
00919 
00920         // NOTE: we may be invoked during INIT STAGE 1 too, when SnrEval notifies us
00921         // about the initial radio state. This function has to work correctly
00922         // even when called during initialization phase!
00923 
00924         EV << "** Radio state update in " << className() << ": " << details->info()
00925            << " (at T=" << simtimeToStr(simTime()) << ")\n";
00926 
00927         // beginning of a reception
00928         if (radioState == RadioState::RECV)
00929         {
00930             // if there's a contention period
00931             if (contention->isScheduled())
00932             {
00933                 // update the backoff window in order to give higher priority in
00934                 // the next battle
00935                 if (simTime() - contention->sendingTime() >= DIFS)
00936                 {
00937                     BW = contention->arrivalTime() - simTime();
00938                     EV << "Backoff window made smaller, new BW: " << BW << endl;
00939                 }
00940                 cancelEvent(contention);
00941             }
00942 
00943             // if there's a SIFS period
00944             if (endSifs->isScheduled())
00945             {
00946                 // delete the previously received frame
00947                 delete (Mac80211Pkt *)endSifs->contextPointer();
00948 
00949                 // cancel the next transmission
00950                 cancelEvent(endSifs);
00951 
00952                 // state in now IDLE or CONTEND
00953                 if (fromUpperLayer.empty())
00954                     setState(IDLE);
00955                 else
00956                     setState(CONTEND);
00957             }
00958         }
00959     }
00960 }

void Mac80211::registerInterface (  )  [protected]

Register the interface in InterfaceTable.

00087 {
00088     InterfaceEntry *e = new InterfaceEntry();
00089 
00090     // interface name: NetworkInterface module's name without special characters ([])
00091     char *interfaceName = new char[strlen(parentModule()->fullName()) + 1];
00092     char *d = interfaceName;
00093     for (const char *s = parentModule()->fullName(); *s; s++)
00094         if (isalnum(*s))
00095             *d++ = *s;
00096     *d = '\0';
00097 
00098     e->setName(interfaceName);
00099     delete [] interfaceName;
00100 
00101     const char *addrstr = par("address");
00102     if (!strcmp(addrstr, "auto"))
00103     {
00104         // assign automatic address
00105         myMacAddr = MACAddress::generateAutoAddress();
00106 
00107         // change module parameter from "auto" to concrete address
00108         par("address").setStringValue(myMacAddr.str().c_str());
00109     }
00110     else
00111     {
00112         myMacAddr.setAddress(addrstr);
00113     }
00114     e->setMACAddress(myMacAddr);
00115 
00116     // generate interface identifier for IPv6
00117     e->setInterfaceToken(myMacAddr.formInterfaceIdentifier());
00118 
00119     // MTU on 802.11 = ?
00120     e->setMtu(1500);            // FIXME
00121 
00122     // capabilities
00123     e->setBroadcast(true);
00124     e->setMulticast(true);
00125     e->setPointToPoint(false);
00126 
00127     // add
00128     InterfaceTable *ift = InterfaceTableAccess().get();
00129     ift->addInterface(e, this);
00130 }

void Mac80211::sendACKframe ( Mac80211Pkt af  )  [protected]

send Acknoledgement

Send an ACK frame.Called by HandleEndSifsTimer()

00637 {
00638     // the MAC must wait the end of the transmission before beginning an
00639     // other contention period
00640     scheduleAt(simTime() + packetDuration(LENGTH_ACK) + delta, endTransmission);
00641 
00642     // send ACK frame
00643     sendDown(buildACKframe(af));
00644     EV << "sent ACK frame!\n";
00645 
00646     // update state and display
00647     setState(BUSY);
00648 }

void Mac80211::sendBROADCASTframe (  )  [protected]

send broadcast frame

Send a BROADCAST frame.Called by handleContentionTimer()

00689 {
00690     // the MAC must wait the end of the transmission before beginning any
00691     // other contention period
00692     scheduleAt(simTime() + packetDuration(fromUpperLayer.front()->length()), endTransmission);
00693     // send ACK frame
00694     sendDown(buildBROADCASTframe());
00695 
00696     // update state and display
00697     setState(BUSY);
00698 }

void Mac80211::sendCTSframe ( Mac80211Pkt af  )  [protected]

send CTS frame

Send a CTS frame.Called by HandleEndSifsTimer()

00674 {
00675     // schedule time-out
00676     scheduleAt(simTime() + timeOut(CTS, af->getDuration()), timeout);
00677 
00678     // send CTS frame
00679     sendDown(buildCTSframe(af));
00680 
00681     // update state and display
00682     setState(WFDATA);
00683 }

void Mac80211::sendDATAframe (  )  [protected, virtual]

send data frame

Send a DATA frame. Called by HandleEndSifsTimer() or handleEndContentionTimer()

00615 {
00616     EV << "sending data frame\n";
00617 
00618     // schedule time out
00619     scheduleAt(simTime() + timeOut(DATA, 0), timeout);
00620 
00621     if (!rtsCts)
00622         // retryCounter incremented
00623         retryCounter++;
00624 
00625     // send DATA frame
00626     sendDown(buildDATAframe());
00627 
00628     // update state and display
00629     setState(WFACK);
00630 }

void Mac80211::sendRTSframe (  )  [protected, virtual]

send RTS frame

Send a RTS frame.Called by handleContentionTimer()

00655 {
00656     // schedule time-out
00657     scheduleAt(simTime() + timeOut(RTS, 0), timeout);
00658 
00659     // long_retry_counter incremented
00660     retryCounter++;
00661 
00662     // send RTS frame
00663     sendDown(buildRTSframe());
00664 
00665     // update state and display
00666     setState(WFCTS);
00667 }

void Mac80211::setState ( State  state  )  [protected]

Sets the state, and produces a log message in between.

01057 {
01058     if (state==newState)
01059         EV << "staying in state " << stateName(state) << "\n";
01060     else
01061         EV << "state " << stateName(state) << " --> " << stateName(newState) << "\n";
01062     state = newState;
01063 }

const char * Mac80211::stateName ( State  state  )  [protected]

Produce a readable name of the given state.

01002 {
01003 #define CASE(x) case x: s=#x; break
01004     const char *s = "???";
01005     switch (state)
01006     {
01007         CASE(WFDATA);
01008         CASE(QUIET);
01009         CASE(IDLE);
01010         CASE(CONTEND);
01011         CASE(WFCTS);
01012         CASE(WFACK);
01013         CASE(BUSY);
01014     }
01015     return s;
01016 #undef CASE
01017 }

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.

00891 {
00892     if (retryCounter > RETRY_LIMIT)
00893     {
00894         // initialize counter
00895         retryCounter = 1;
00896         // reportLost(fromUpperLayer.front());
00897 
00898         // delete the frame to transmit
00899         Mac80211Pkt *temp = fromUpperLayer.front();
00900         fromUpperLayer.pop_front();
00901         delete(temp);
00902     }
00903 }

double Mac80211::timeOut ( _802_11frameType  type,
double  last_frame_duration 
) [protected]

return a timeOut value for a certain type of frame

Return a time-out value for a type of frame. Called by SendRTSframe, sendCTSframe, etc.

00968 {
00969     double time_out = 0;
00970     switch (type)
00971     {
00972     case RTS:
00973         time_out = SIFS + packetDuration(LENGTH_RTS) + packetDuration(LENGTH_CTS) + delta;
00974         break;
00975     case CTS:
00976         time_out = last_frame_duration - packetDuration(LENGTH_ACK) - 2 * SIFS + delta;
00977         break;
00978     case DATA:
00979         time_out =
00980             SIFS + packetDuration(fromUpperLayer.front()->length()) + packetDuration(LENGTH_ACK) +
00981             delta + 0.1;
00982         //XXX: I have added some time here, because propagation delay of AirFrames caused problems
00983         // the timeout periods should be carefully revised with special care for the deltas?! --Levy
00984         break;
00985     default:
00986         EV << "Unused frame type was given when calling timeOut(), this should not happen!\n";
00987     }
00988     return time_out;
00989 }

const char * Mac80211::timerTypeName ( int  type  )  [protected]

Produce a readable name of the given timer type.

01020 {
01021 #define CASE(x) case x: s=#x; break
01022     const char *s = "???";
01023     switch (type)
01024     {
01025         CASE(TIMEOUT);
01026         CASE(NAV);
01027         CASE(CONTENTION);
01028         CASE(END_TRANSMISSION);
01029         CASE(END_SIFS);
01030     }
01031     return s;
01032 #undef CASE
01033 }


Member Data Documentation

double Mac80211::bitrate [protected]

The bitrate should be set in omnetpp.ini; be sure to use a valid 802.11 bitrate.

int Mac80211::broadcastBackoff [protected]

Should be set in the omnetpp.ini.

double Mac80211::BW [protected]

Variable to store the current backoff value.

cMessage* Mac80211::contention [protected]

Timer used for contention periods.

double Mac80211::delta [protected]

Very small value used in timer scheduling in order to avoid multiple changements of state in the same simulation time.

double Mac80211::EIFS [protected]

extended interframe space

cMessage* Mac80211::endSifs [protected]

Timer used to indicate the end of a SIFS.

cMessage* Mac80211::endTransmission [protected]

Timer used to indicate the end of the transmission of an ACK or a BROADCAST packet.

MacPktList Mac80211::fromUpperLayer [protected]

Buffering of messages from upper layer.

int Mac80211::maxQueueSize [protected]

Maximal number of packets in the queue; should be set in the omnetpp.ini.

MACAddress Mac80211::myMacAddr [protected]

mac address

cMessage* Mac80211::nav [protected]

Timer used for the defer time of a node. Also called NAV : networks allocation vector.

bool Mac80211::nextIsBroadcast [protected]

Boolean used to know if the next packet is a broadcast packet.

RadioState::State Mac80211::radioState [protected]

Current state of the radio (kept updated by receiveChangeNotification()).

int Mac80211::retryCounter [protected]

Number of frame transmission attempt.

bool Mac80211::rtsCts [protected]

true if Rts/Cts is used, false if not; can be set in omnetpp.ini

State Mac80211::state [protected]

Current state of the MAC.

cMessage* Mac80211::timeout [protected]

Timer used for time-outs after the transmission of a RTS, a CTS, or a DATA packet.

bool Mac80211::tryWithoutBackoff [protected]

If there's a new packet to send and the channel is free, no backoff is needed.


The documentation for this class was generated from the following files:
Generated on Wed Apr 4 13:20:22 2007 for INET Framework for OMNeT++/OMNEST by  doxygen 1.4.7