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.
virtual void registerInterface ()
 Register the interface in IInterfaceTable.
virtual void receiveChangeNotification (int category, const 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 (cPacket *)
 Handle packets from upper layer.
virtual void handleCommand (cMessage *)
 Handle commands from upper layer.
virtual void handleLowerMsg (cPacket *)
 Handle packets from lower layer.
virtual void handleEndContentionTimer ()
 handle end of contention
virtual void handleMsgNotForMe (Mac80211Pkt *)
 handle a message that is not for me or errornous
virtual void handleMsgForMe (Mac80211Pkt *)
 handle a message that was meant for me
virtual void handleBroadcastMsg (Mac80211Pkt *)
virtual void handleEndTransmissionTimer ()
 handle the end of a transmission...
virtual void handleEndSifsTimer ()
 handle end of SIFS
virtual void handleTimeoutTimer ()
 handle time out
virtual void handleNavTimer ()
 NAV timer expired, the exchange of messages of other stations is done.
virtual void handleRTSframe (Mac80211Pkt *)
virtual void handleDATAframe (Mac80211Pkt *)
virtual void handleACKframe (Mac80211Pkt *)
virtual void handleCTSframe (Mac80211Pkt *)
virtual void sendDATAframe ()
 send data frame
virtual void sendACKframe (Mac80211Pkt *)
 send Acknoledgement
virtual void sendCTSframe (Mac80211Pkt *)
 send CTS frame
virtual void sendRTSframe ()
 send RTS frame
virtual void sendBROADCASTframe ()
 send broadcast frame
virtual Mac80211Pkt * encapsMsg (cPacket *netw)
 encapsulate packet
virtual void decapsulateAndSendUp (Mac80211Pkt *frame)
 decapsulate packet and send to higher layer
virtual Mac80211Pkt * buildDATAframe ()
 build a data frame
virtual Mac80211Pkt * buildACKframe (Mac80211Pkt *)
 build an ACK
virtual Mac80211Pkt * buildCTSframe (Mac80211Pkt *)
 build a CTS frame
virtual Mac80211Pkt * buildRTSframe ()
 build an RTS frame
virtual Mac80211Pkt * buildBROADCASTframe ()
 build a broadcast frame
virtual void beginNewCycle ()
 start a new contention period
virtual simtime_t computeBackoff ()
 Compute a backoff value.
virtual int computeContentionWindow ()
 Compute a new contention window.
virtual void testMaxAttempts ()
 Test if maximum number of retries to transmit is exceeded.
virtual simtime_t computeTimeout (_802_11frameType type, simtime_t last_frame_duration)
 return a timeOut value for a certain type of frame
virtual simtime_t computePacketDuration (int bits)
 computes the duration of a transmission over the physical channel
virtual void setState (State state)
 Sets the state, and produces a log message in between.

Static Protected Member Functions

static const char * stateName (State state)
 Produce a readable name of the given state.
static const char * timerTypeName (int type)
 Produce a readable name of the given timer type.
static const char * pktTypeName (int type)
 Produce a readable name of the given packet type.

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.
simtime_t EIFS
 extended interframe space
simtime_t 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
simtime_t 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

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
}
typedef std::list< Mac80211Pkt * > MacPktList

Member Typedef Documentation

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


Member Enumeration Documentation

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

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


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

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

Initialization of the module and some variables.

00070 {return 2;}

void Mac80211::initialize ( int  stage  )  [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 + computePacketDuration(LENGTH_ACK);
00075         EV << "SIFS: " << SIFS << " DIFS: " << DIFS << " EIFS: " << EIFS << endl;
00076 
00077         // get registered in IInterfaceTable
00078         registerInterface();
00079 
00080         WATCH(state);
00081         WATCH(radioState);
00082     }
00083 }

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

Register the interface in IInterfaceTable.

Referenced by initialize().

00087 {
00088     InterfaceEntry *e = new InterfaceEntry();
00089 
00090     // interface name: NetworkInterface module's name without special characters ([])
00091     char *interfaceName = new char[strlen(getParentModule()->getFullName()) + 1];
00092     char *d = interfaceName;
00093     for (const char *s = getParentModule()->getFullName(); *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(par("mtu"));            // FIXME
00121 
00122     // capabilities
00123     e->setBroadcast(true);
00124     e->setMulticast(true);
00125     e->setPointToPoint(false);
00126 
00127     // add
00128     IInterfaceTable *ift = InterfaceTableAccess().get();
00129     ift->addInterface(e, this);
00130 }

void Mac80211::receiveChangeNotification ( int  category,
const 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.

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

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

Handle self messages such as timer...

handle timers

Implements WirelessMacBase.

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

void Mac80211::handleUpperMsg ( cPacket *  msg  )  [protected, virtual]

Handle packets from upper layer.

This implementation does not support fragmentation, so it is tested if the maximum length of the MPDU is exceeded.

Implements WirelessMacBase.

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

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

Handle commands from upper layer.

Implements WirelessMacBase.

00133 {
00134     // no commands supported by Mac80211
00135     error("Non-packet message arrived from higher layer: (%s)%s", msg->getClassName(), msg->getName());
00136 }

void Mac80211::handleLowerMsg ( cPacket *  msg  )  [protected, virtual]

Handle packets 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.

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

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

Referenced by handleSelfMsg().

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

void Mac80211::handleMsgNotForMe ( Mac80211Pkt *  af  )  [protected, virtual]

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

Referenced by handleLowerMsg().

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

void Mac80211::handleMsgForMe ( Mac80211Pkt *  af  )  [protected, virtual]

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

Referenced by handleLowerMsg().

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

void Mac80211::handleBroadcastMsg ( Mac80211Pkt *  af  )  [protected, virtual]

Handle a broadcast packet. This packet is simply passed to the upper layer. No acknowledgement is needed. Called by handleLowerMsg(Mac80211Pkt *af)

Referenced by handleLowerMsg().

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

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

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)

Referenced by handleSelfMsg().

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

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

handle end of SIFS

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

Referenced by handleSelfMsg().

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

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

handle time out

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

Referenced by handleSelfMsg().

00562 {
00563     // if (state == WFCTS || state == WFACK)testMaxAttempts();
00564 
00565     // if there's a packet to send and if the channel is free then
00566     // start a new contention period
00567     if (state != QUIET)
00568         beginNewCycle();
00569 }

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

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)

Referenced by handleSelfMsg().

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

void Mac80211::handleRTSframe ( Mac80211Pkt *  af  )  [protected, virtual]

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

Referenced by handleMsgForMe().

00417 {
00418     // wait a short interframe space
00419     endSifs->setContextPointer(af);
00420     scheduleAt(simTime() + SIFS, endSifs);
00421 }

void Mac80211::handleDATAframe ( Mac80211Pkt *  af  )  [protected, virtual]

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

Referenced by handleMsgForMe().

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

void Mac80211::handleACKframe ( Mac80211Pkt *  af  )  [protected, virtual]

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

Referenced by handleMsgForMe().

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

void Mac80211::handleCTSframe ( Mac80211Pkt *  af  )  [protected, virtual]

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

Referenced by handleMsgForMe().

00473 {
00474     // cancel time-out event
00475     cancelEvent(timeout);
00476 
00477     // wait a short interframe space
00478     endSifs->setContextPointer(af);
00479     scheduleAt(simTime() + SIFS, endSifs);
00480 }

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

send data frame

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

Referenced by handleEndContentionTimer(), and handleEndSifsTimer().

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

void Mac80211::sendACKframe ( Mac80211Pkt *  af  )  [protected, virtual]

send Acknoledgement

Send an ACK frame.Called by HandleEndSifsTimer()

Referenced by handleEndSifsTimer().

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

void Mac80211::sendCTSframe ( Mac80211Pkt *  af  )  [protected, virtual]

send CTS frame

Send a CTS frame.Called by HandleEndSifsTimer()

Referenced by handleEndSifsTimer().

00679 {
00680     // schedule time-out
00681     scheduleAt(simTime() + computeTimeout(CTS, af->getDuration()), timeout);
00682 
00683     // send CTS frame
00684     sendDown(buildCTSframe(af));
00685 
00686     // update state and display
00687     setState(WFDATA);
00688 }

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

send RTS frame

Send a RTS frame.Called by handleContentionTimer()

Referenced by handleEndContentionTimer().

00660 {
00661     // schedule time-out
00662     scheduleAt(simTime() + computeTimeout(RTS, 0), timeout);
00663 
00664     // long_retry_counter incremented
00665     retryCounter++;
00666 
00667     // send RTS frame
00668     sendDown(buildRTSframe());
00669 
00670     // update state and display
00671     setState(WFCTS);
00672 }

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

send broadcast frame

Send a BROADCAST frame.Called by handleContentionTimer()

Referenced by handleEndContentionTimer().

00694 {
00695     // the MAC must wait the end of the transmission before beginning any
00696     // other contention period
00697     scheduleAt(simTime() + computePacketDuration(fromUpperLayer.front()->getBitLength()), endTransmission);
00698     // send ACK frame
00699     sendDown(buildBROADCASTframe());
00700 
00701     // update state and display
00702     setState(BUSY);
00703 }

Mac80211Pkt * Mac80211::encapsMsg ( cPacket *  netw  )  [protected, virtual]

encapsulate packet

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

Referenced by handleUpperMsg().

00176 {
00177     Mac80211Pkt *pkt = new Mac80211Pkt(netw->getName());
00178     pkt->setBitLength(272);        // headerLength, including final CRC-field
00179 
00180     // copy dest address from the control info
00181     Ieee802Ctrl *ctrl = check_and_cast<Ieee802Ctrl *>(netw->removeControlInfo());
00182     pkt->setDestAddr(ctrl->getDest());
00183     delete ctrl;
00184 
00185     // set the src address to own mac address (nic module getId())
00186     pkt->setSrcAddr(myMacAddr);
00187 
00188     // encapsulate the network packet
00189     pkt->encapsulate(netw);
00190 
00191     return pkt;
00192 }

void Mac80211::decapsulateAndSendUp ( Mac80211Pkt *  frame  )  [protected, virtual]

decapsulate packet and send to higher layer

Referenced by handleBroadcastMsg(), and handleDATAframe().

00195 {
00196     cPacket *msg = frame->decapsulate();
00197     // FIXME TBD set control info
00198     delete frame;
00199     sendUp(msg);
00200 }

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

build a data frame

Build a DATA frame. Called by sendDATAframe()

Referenced by sendDATAframe().

00710 {
00711     // build a copy of the frame in front of the queue
00712     Mac80211Pkt *frame = (Mac80211Pkt *) (fromUpperLayer.front())->dup();
00713     frame->setSrcAddr(myMacAddr);
00714     frame->setKind(DATA);
00715     if (rtsCts)
00716         frame->setDuration(SIFS + computePacketDuration(LENGTH_ACK));
00717     else
00718         frame->setDuration(0);
00719 
00720     return frame;
00721 }

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

build an ACK

Build an ACK frame. Called by sendACKframe()

Referenced by sendACKframe().

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

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

build a CTS frame

Build a CTS frame. Called by sendCTSframe()

Referenced by sendCTSframe().

00766 {
00767     Mac80211Pkt *frame = new Mac80211Pkt("wlan-cts");
00768     frame->setKind(CTS);
00769     frame->setBitLength(LENGTH_CTS);
00770 
00771     // the dest adress must be the src adress of the RTS received. The
00772     // src adress is the adress of the node
00773     frame->setSrcAddr(myMacAddr);
00774     frame->setDestAddr(af->getSrcAddr());
00775     frame->setDuration(af->getDuration() - SIFS - computePacketDuration(LENGTH_CTS));
00776 
00777     return frame;
00778 }

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

build an RTS frame

Build a RTS frame. Called by sendRTSframe()

Referenced by sendRTSframe().

00747 {
00748     Mac80211Pkt *frame = new Mac80211Pkt("wlan-rts");
00749     frame->setKind(RTS);
00750     frame->setBitLength(LENGTH_RTS);
00751 
00752     // the src adress and dest address are copied in the frame in the queue (frame to be sent)
00753     frame->setSrcAddr(((Mac80211Pkt *) fromUpperLayer.front())->getSrcAddr());
00754     frame->setDestAddr(((Mac80211Pkt *) fromUpperLayer.front())->getDestAddr());
00755     frame->setDuration(3 * SIFS + computePacketDuration(LENGTH_CTS) +
00756                        computePacketDuration(fromUpperLayer.front()->getBitLength()) +
00757                        computePacketDuration(LENGTH_ACK));
00758 
00759     return frame;
00760 }

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

build a broadcast frame

Build a BROADCAST frame. Called sendBROADCASTframe()

Referenced by sendBROADCASTframe().

00784 {
00785     // send a copy of the frame in front of the queue
00786     Mac80211Pkt *frame = (Mac80211Pkt *) (fromUpperLayer.front())->dup();
00787     frame->setKind(BROADCAST);
00788     return frame;
00789 }

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

Referenced by handleACKframe(), handleBroadcastMsg(), handleEndTransmissionTimer(), handleLowerMsg(), handleMsgNotForMe(), handleNavTimer(), handleTimeoutTimer(), and handleUpperMsg().

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

simtime_t Mac80211::computeBackoff (  )  [protected, virtual]

Compute a backoff value.

Compute the backoff value.

Referenced by beginNewCycle(), and handleMsgNotForMe().

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

int Mac80211::computeContentionWindow (  )  [protected, virtual]

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

Referenced by computeBackoff().

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

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

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.

Referenced by beginNewCycle().

00896 {
00897     if (retryCounter > RETRY_LIMIT)
00898     {
00899         // initialize counter
00900         retryCounter = 1;
00901         // reportLost(fromUpperLayer.front());
00902 
00903         // delete the frame to transmit
00904         Mac80211Pkt *temp = fromUpperLayer.front();
00905         fromUpperLayer.pop_front();
00906         delete(temp);
00907     }
00908 }

simtime_t Mac80211::computeTimeout ( _802_11frameType  type,
simtime_t  last_frame_duration 
) [protected, virtual]

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.

Referenced by sendCTSframe(), sendDATAframe(), and sendRTSframe().

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

simtime_t Mac80211::computePacketDuration ( int  bits  )  [protected, virtual]

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.

Referenced by buildCTSframe(), buildDATAframe(), buildRTSframe(), computeTimeout(), initialize(), sendACKframe(), and sendBROADCASTframe().

01002 {
01003     return bits / bitrate + PHY_HEADER_LENGTH / BITRATE_HEADER;
01004 }

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

Produce a readable name of the given state.

Referenced by handleMsgForMe(), and setState().

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

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

Produce a readable name of the given timer type.

Referenced by handleSelfMsg().

01025 {
01026 #define CASE(x) case x: s=#x; break
01027     const char *s = "???";
01028     switch (type)
01029     {
01030         CASE(TIMEOUT);
01031         CASE(NAV);
01032         CASE(CONTENTION);
01033         CASE(END_TRANSMISSION);
01034         CASE(END_SIFS);
01035     }
01036     return s;
01037 #undef CASE
01038 }

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

Produce a readable name of the given packet type.

Referenced by handleLowerMsg(), and handleMsgForMe().

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

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

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

Referenced by beginNewCycle(), handleEndContentionTimer(), handleMsgNotForMe(), receiveChangeNotification(), sendACKframe(), sendBROADCASTframe(), sendCTSframe(), sendDATAframe(), and sendRTSframe().

01062 {
01063     if (state==newState)
01064         EV << "staying in state " << stateName(state) << "\n";
01065     else
01066         EV << "state " << stateName(state) << " --> " << stateName(newState) << "\n";
01067     state = newState;
01068 }


Member Data Documentation

cMessage* Mac80211::timeout [protected]

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

Referenced by handleACKframe(), handleCTSframe(), handleDATAframe(), handleMsgNotForMe(), initialize(), Mac80211(), sendCTSframe(), sendDATAframe(), sendRTSframe(), and ~Mac80211().

cMessage* Mac80211::nav [protected]

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

Referenced by handleMsgNotForMe(), initialize(), Mac80211(), and ~Mac80211().

cMessage* Mac80211::contention [protected]

Timer used for contention periods.

Referenced by beginNewCycle(), handleMsgNotForMe(), initialize(), Mac80211(), receiveChangeNotification(), and ~Mac80211().

cMessage* Mac80211::endTransmission [protected]

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

Referenced by initialize(), Mac80211(), sendACKframe(), sendBROADCASTframe(), and ~Mac80211().

cMessage* Mac80211::endSifs [protected]

simtime_t Mac80211::EIFS [protected]

extended interframe space

Referenced by handleMsgNotForMe(), and initialize().

simtime_t Mac80211::BW [protected]

Variable to store the current backoff value.

Referenced by computeBackoff(), handleEndContentionTimer(), initialize(), and receiveChangeNotification().

State Mac80211::state [protected]

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

Referenced by beginNewCycle(), initialize(), and receiveChangeNotification().

int Mac80211::maxQueueSize [protected]

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

Referenced by handleUpperMsg(), and initialize().

bool Mac80211::nextIsBroadcast [protected]

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

Referenced by beginNewCycle(), computeContentionWindow(), and handleEndContentionTimer().

int Mac80211::retryCounter [protected]

Number of frame transmission attempt.

Referenced by computeContentionWindow(), handleACKframe(), initialize(), sendDATAframe(), sendRTSframe(), and testMaxAttempts().

bool Mac80211::tryWithoutBackoff [protected]

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

Referenced by beginNewCycle(), and handleUpperMsg().

bool Mac80211::rtsCts [protected]

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

Referenced by buildDATAframe(), handleDATAframe(), handleEndContentionTimer(), handleMsgNotForMe(), initialize(), and sendDATAframe().

simtime_t Mac80211::delta [protected]

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

Referenced by computeTimeout(), initialize(), and sendACKframe().

double Mac80211::bitrate [protected]

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

Referenced by computePacketDuration(), and initialize().

int Mac80211::broadcastBackoff [protected]

Should be set in the omnetpp.ini.

Referenced by computeContentionWindow(), and initialize().


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

Generated on Fri Mar 20 18:51:20 2009 for INET Framework for OMNeT++/OMNEST by  doxygen 1.5.5