INET Framework for OMNeT++/OMNEST
|
An implementation of the 802.11b MAC. More...
#include <Mac80211.h>
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 |
An implementation of the 802.11b MAC.
For more info, see the NED file.
typedef std::list<Mac80211Pkt*> Mac80211::MacPktList [private] |
enum Mac80211::State [private] |
Definition of the states
{ 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 [private] |
Definition of the timer types
{ TIMEOUT, NAV, CONTENTION, END_TRANSMISSION, END_SIFS };
Mac80211::Mac80211 | ( | ) |
{ timeout = nav = contention = endTransmission = endSifs = NULL; }
Mac80211::~Mac80211 | ( | ) | [virtual] |
{ cancelAndDelete(timeout); cancelAndDelete(nav); cancelAndDelete(contention); cancelAndDelete(endTransmission); cancelAndDelete(endSifs); }
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().
{ EV << "beginning new contention cycle\n"; // 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 (!fromUpperLayer.empty()) { // look if the next packet is unicast or broadcast nextIsBroadcast = (((Mac80211Pkt *) fromUpperLayer.front())->getDestAddr().isBroadcast()); // print("next is broadcast = "<<nextIsBroadcast); // if the channel is free then wait a random time and transmit if (radioState == RadioState::IDLE) { // if channel is idle AND I was not the last one that transmitted // data: no backoff if (tryWithoutBackoff) { EV << "trying to send without backoff...\n"; scheduleAt(simTime() + DIFS, contention); } else { // backoff! scheduleAt(simTime() + computeBackoff() + DIFS, contention); } } tryWithoutBackoff = false; // else wait until the channel gets free; the state is now contend setState(CONTEND); } else { tryWithoutBackoff = false; setState(IDLE); } }
Mac80211Pkt * Mac80211::buildACKframe | ( | Mac80211Pkt * | af | ) | [protected, virtual] |
build an ACK
Build an ACK frame. Called by sendACKframe()
Referenced by sendACKframe().
{ Mac80211Pkt *frame = new Mac80211Pkt("wlan-ack"); frame->setKind(ACK); frame->setBitLength(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); return frame; }
Mac80211Pkt * Mac80211::buildBROADCASTframe | ( | ) | [protected, virtual] |
build a broadcast frame
Build a BROADCAST frame. Called sendBROADCASTframe()
Referenced by sendBROADCASTframe().
{ // send a copy of the frame in front of the queue Mac80211Pkt *frame = (Mac80211Pkt *) (fromUpperLayer.front())->dup(); frame->setKind(BROADCAST); return frame; }
Mac80211Pkt * Mac80211::buildCTSframe | ( | Mac80211Pkt * | af | ) | [protected, virtual] |
build a CTS frame
Build a CTS frame. Called by sendCTSframe()
Referenced by sendCTSframe().
{ Mac80211Pkt *frame = new Mac80211Pkt("wlan-cts"); frame->setKind(CTS); frame->setBitLength(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 - computePacketDuration(LENGTH_CTS)); return frame; }
Mac80211Pkt * Mac80211::buildDATAframe | ( | ) | [protected, virtual] |
build a data frame
Build a DATA frame. Called by sendDATAframe()
Referenced by sendDATAframe().
{ // build a copy of the frame in front of the queue Mac80211Pkt *frame = (Mac80211Pkt *) (fromUpperLayer.front())->dup(); frame->setSrcAddr(myMacAddr); frame->setKind(DATA); if (rtsCts) frame->setDuration(SIFS + computePacketDuration(LENGTH_ACK)); else frame->setDuration(0); return frame; }
Mac80211Pkt * Mac80211::buildRTSframe | ( | ) | [protected, virtual] |
build an RTS frame
Build a RTS frame. Called by sendRTSframe()
Referenced by sendRTSframe().
{ Mac80211Pkt *frame = new Mac80211Pkt("wlan-rts"); frame->setKind(RTS); frame->setBitLength(LENGTH_RTS); // the src adress and dest address are copied in the frame in the queue (frame to be sent) frame->setSrcAddr(((Mac80211Pkt *) fromUpperLayer.front())->getSrcAddr()); frame->setDestAddr(((Mac80211Pkt *) fromUpperLayer.front())->getDestAddr()); frame->setDuration(3 * SIFS + computePacketDuration(LENGTH_CTS) + computePacketDuration(fromUpperLayer.front()->getBitLength()) + computePacketDuration(LENGTH_ACK)); return frame; }
simtime_t Mac80211::computeBackoff | ( | ) | [protected, virtual] |
Compute a backoff value.
Compute the backoff value.
Referenced by beginNewCycle(), and handleMsgNotForMe().
{ // the MAC has won the previous contention. We have to compute a new // backoff window if (BW == 0) { int CW = computeContentionWindow(); EV << "generating backoff for CW: " << CW << endl; BW = intrand(CW + 1) * ST; } // CW is the contention window (see the function). ST is the // slot time. else we take the old value of BW, in order to give a // bigger priority to a node which has lost a previous contention // period. EV << "backing off for: " << BW + DIFS << endl; return BW; }
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().
{ // the next packet is an unicast packet if (!nextIsBroadcast) { int cw = (CW_MIN + 1) * (1 << (retryCounter - 1)) - 1; // return the calculated value or CWmax if the maximal value is reached if (cw <= CW_MAX) return cw; else return CW_MAX; } // the next packet is broadcast : the contention window must be maximal else return broadcastBackoff; }
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().
{ return bits / bitrate + PHY_HEADER_LENGTH / BITRATE_HEADER; }
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().
{ simtime_t time_out = 0; switch (type) { case RTS: time_out = SIFS + computePacketDuration(LENGTH_RTS) + computePacketDuration(LENGTH_CTS) + delta; break; case CTS: time_out = last_frame_duration - computePacketDuration(LENGTH_ACK) - 2 * SIFS + delta; break; case DATA: time_out = SIFS + computePacketDuration(fromUpperLayer.front()->getBitLength()) + computePacketDuration(LENGTH_ACK) + delta + 0.1; //XXX: I have added some time here, because propagation delay of AirFrames caused problems // the timeout periods should be carefully revised with special care for the deltas?! --Levy break; default: EV << "Unused frame type was given when calling computeTimeout(), this should not happen!\n"; } return time_out; }
void Mac80211::decapsulateAndSendUp | ( | Mac80211Pkt * | frame | ) | [protected, virtual] |
decapsulate packet and send to higher layer
Referenced by handleBroadcastMsg(), and handleDATAframe().
{ cPacket *msg = frame->decapsulate(); // FIXME TBD set control info delete frame; sendUp(msg); }
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().
{ Mac80211Pkt *pkt = new Mac80211Pkt(netw->getName()); pkt->setBitLength(272); // headerLength, including final CRC-field // copy dest address from the control info Ieee802Ctrl *ctrl = check_and_cast<Ieee802Ctrl *>(netw->removeControlInfo()); pkt->setDestAddr(ctrl->getDest()); delete ctrl; // set the src address to own mac address (nic module getId()) pkt->setSrcAddr(myMacAddr); // encapsulate the network packet pkt->encapsulate(netw); return pkt; }
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().
{ EV << "handling Ack frame\n"; // cancel time-out event cancelEvent(timeout); // the transmission is acknowledged : initialize long_retry_counter retryCounter = 1; // 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, 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().
{ EV << "handle broadcast\n"; if (state == BUSY) error("logic error: node is currently transmitting, can not receive " "(does the physical layer do its job correctly?)"); decapsulateAndSendUp(af); if (state == CONTEND) beginNewCycle(); }
void Mac80211::handleCommand | ( | cMessage * | msg | ) | [protected, virtual] |
Handle commands from upper layer.
Implements WirelessMacBase.
{ // no commands supported by Mac80211 error("Non-packet message arrived from higher layer: (%s)%s", msg->getClassName(), msg->getName()); }
void Mac80211::handleCTSframe | ( | Mac80211Pkt * | af | ) | [protected, virtual] |
Handle a CTS frame. Called by HandleMsgForMe(Mac80211Pkt* af)
Referenced by handleMsgForMe().
void Mac80211::handleDATAframe | ( | Mac80211Pkt * | af | ) | [protected, virtual] |
Handle a frame which expected to be a DATA frame. Called by HandleMsgForMe()
Referenced by handleMsgForMe().
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().
{ EV << "end contention period\n"; if (state != CONTEND) error("logic error: expiration of the contention timer outside of CONTEND state, should not happen"); // the node has won the channel, the backoff window is deleted and // will be new calculated in the next contention period BW = 0; // unicast packet if (!nextIsBroadcast) { if (rtsCts) { // send a RTS sendRTSframe(); setState(WFCTS); } else { sendDATAframe(); setState(WFACK); } // broadcast packet } else { sendBROADCASTframe(); // removes the packet from the queue without waiting for an acknowledgement Mac80211Pkt *temp = fromUpperLayer.front(); fromUpperLayer.pop_front(); delete(temp); } }
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().
{ Mac80211Pkt *frame = (Mac80211Pkt *) endSifs->getContextPointer(); switch (frame->getKind()) { case RTS: sendCTSframe(frame); break; case CTS: sendDATAframe(); 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::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().
{ EV << "transmission of ACK/BROADCAST is over\n"; if (state != BUSY) error("logic error: expiration of the end transmission timer outside the BUSY state, should not happen"); // if there's a packet to send and if the channel is free, then start a new contention period beginNewCycle(); }
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.
{ Mac80211Pkt *af = check_and_cast<Mac80211Pkt *>(msg); // end of the reception EV << "frame " << af << " received, kind = " << pktTypeName(af->getKind()) << "\n"; switch (af->getKind()) { case COLLISION: // packet lost or bit error delete af; if (state == CONTEND) beginNewCycle(); break; case BITERROR: handleMsgNotForMe(af); break; case BROADCAST: // broadcast packet handleBroadcastMsg(af); break; default: // other packet if (af->getDestAddr() == myMacAddr) // FIXME verify broadcast dest addr works! handleMsgForMe(af); else handleMsgNotForMe(af); } }
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().
{ EV << "handle msg for me in state = " << stateName(state) << " with type = " << pktTypeName(af->getKind()) << "\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) handleRTSframe(af); else if (af->getKind() == DATA) handleDATAframe(af); else // TODO: what if a late ACK has arrived? EV << "in handleMsgForMe() IDLE/CONTEND, strange message, darf das?\n"; break; case WFDATA: // waiting for DATA if (af->getKind() == DATA) handleDATAframe(af); else EV << "in handleMsgForMe() WFDATA, strange message, darf das?\n"; break; case WFACK: // waiting for ACK if (af->getKind() == ACK) handleACKframe(af); else EV << "in handleMsgForMe() WFACK, strange message, darf das?\n"; delete af; break; case WFCTS: // The MAC is waiting for CTS if (af->getKind() == CTS) handleCTSframe(af); else EV << "in handleMsgForMe() WFCTS, strange message, darf das?\n"; 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 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 | ( | 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().
{ EV << "handle msg not for me\n"; // if this packet can not be correctly read if (af->getKind() == BITERROR) af->setDuration(EIFS); // if the duration of the packet is null, then do nothing (to avoid // the unuseful scheduling of a self message) if (af->getDuration() != 0) { // the node is already deferring if (state == QUIET) { // the current value of the NAV is not sufficient if (nav->getArrivalTime() < simTime() + af->getDuration()) { cancelEvent(nav); scheduleAt(simTime() + af->getDuration(), nav); EV << "NAV timer started for: " << af->getDuration() << " 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); // is state == WFCTS or WFACK, the data transfer has failed ... // the node must defer for the time of the transmission scheduleAt(simTime() + af->getDuration(), nav); EV << "NAV timer started, not QUIET: " << af->getDuration() << endl; setState(QUIET); } } if (!rtsCts) { // todo: Nachgucken: was passiert bei Error ohne rtsCts! if (state == CONTEND) { if (af->getKind() == BITERROR) { if (contention->isScheduled()) cancelEvent(contention); scheduleAt(simTime() + computeBackoff() + EIFS, contention); } else beginNewCycle(); } } delete af; }
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().
{ 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 beginNewCycle(); }
void Mac80211::handleRTSframe | ( | Mac80211Pkt * | af | ) | [protected, virtual] |
Handle aframe wich is expected to be an RTS. Called by HandleMsgForMe()
Referenced by handleMsgForMe().
void Mac80211::handleSelfMsg | ( | cMessage * | msg | ) | [protected, virtual] |
Handle self messages such as timer...
handle timers
Implements WirelessMacBase.
{ EV << "processing self message with type = " << timerTypeName(msg->getKind()) << endl; switch (msg->getKind()) { case END_SIFS: handleEndSifsTimer(); // noch zu betrachten break; case END_TRANSMISSION: handleEndTransmissionTimer(); // noch zu betrachten break; case CONTENTION: handleEndContentionTimer(); break; // 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, virtual] |
handle time out
Handle the time out timer. Called by handleTimer(cMessage* msg)
Referenced by handleSelfMsg().
{ // if (state == WFCTS || state == WFACK)testMaxAttempts(); // 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 | ( | 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.
{ if (msg->getByteLength() > 2312) error("packet from higher layer (%s)%s is too long for 802.11b, %d bytes (fragmentation is not supported yet)", msg->getClassName(), msg->getName(), (int)(msg->getByteLength())); if (maxQueueSize && (int)fromUpperLayer.size() == maxQueueSize) { EV << "packet " << msg << " received from higher layer but MAC queue is full, deleting\n"; delete msg; return; } Mac80211Pkt *mac = encapsMsg(msg); EV << "packet " << msg << " 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()) { tryWithoutBackoff = true; beginNewCycle(); } else { EV << "enqueued, will be transmitted later\n"; } }
void Mac80211::initialize | ( | int | stage | ) | [protected, virtual] |
Initialization of the module and some variables.
Reimplemented from WirelessMacBase.
{ WirelessMacBase::initialize(stage); if (stage == 0) { EV << "Initializing stage 0\n"; maxQueueSize = par("maxQueueSize"); // subscribe for the information of the carrier sense nb->subscribe(this, NF_RADIOSTATE_CHANGED); // timers timeout = new cMessage("timeout", TIMEOUT); nav = new cMessage("NAV", NAV); contention = new cMessage("contention", CONTENTION); endTransmission = new cMessage("transmission", END_TRANSMISSION); endSifs = new cMessage("end SIFS", END_SIFS); BW = 0; state = IDLE; retryCounter = 1; broadcastBackoff = par("broadcastBackoff"); rtsCts = par("rtsCts"); bitrate = par("bitrate"); delta = 1E-9; //XXX it's rather "epsilon", but this delta business looks a bit dodgy a solution anyway radioState = RadioState::IDLE; // until 1st receiveChangeNotification() EIFS = SIFS + DIFS + computePacketDuration(LENGTH_ACK); EV << "SIFS: " << SIFS << " DIFS: " << DIFS << " EIFS: " << EIFS << endl; // get registered in IInterfaceTable registerInterface(); WATCH(state); WATCH(radioState); } }
virtual int Mac80211::numInitStages | ( | ) | const [inline, protected, virtual] |
Initialization of the module and some variables.
{return 2;}
const char * Mac80211::pktTypeName | ( | int | type | ) | [static, protected] |
Produce a readable name of the given packet type.
Referenced by handleLowerMsg(), and handleMsgForMe().
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.
{ Enter_Method("receiveChangeNotification(%s, %s)", notificationCategoryName(category), details?details->info().c_str() : "n/a"); printNotificationBanner(category, details); if (category == NF_RADIOSTATE_CHANGED) { // update the local copy of the radio state radioState = check_and_cast<RadioState *>(details)->getState(); // NOTE: we may be invoked during INIT STAGE 1 too, when SnrEval notifies us // about the initial radio state. This function has to work correctly // even when called during initialization phase! EV << "** Radio state update in " << getClassName() << ": " << details->info() << " (at T=" << simTime() << ")\n"; // beginning of a reception if (radioState == RadioState::RECV) { // if there's a contention period if (contention->isScheduled()) { // update the backoff window in order to give higher priority in // the next battle if (simTime() - contention->getSendingTime() >= DIFS) { BW = contention->getArrivalTime() - simTime(); EV << "Backoff window made smaller, new BW: " << BW << endl; } cancelEvent(contention); } // if there's a SIFS period if (endSifs->isScheduled()) { // delete the previously received frame delete (Mac80211Pkt *)endSifs->getContextPointer(); // cancel the next transmission cancelEvent(endSifs); // state in now IDLE or CONTEND if (fromUpperLayer.empty()) setState(IDLE); else setState(CONTEND); } } } }
void Mac80211::registerInterface | ( | ) | [protected, virtual] |
Register the interface in IInterfaceTable.
Referenced by initialize().
{ InterfaceEntry *e = new InterfaceEntry(); // interface name: NetworkInterface module's name without special characters ([]) char *interfaceName = new char[strlen(getParentModule()->getFullName()) + 1]; char *d = interfaceName; for (const char *s = getParentModule()->getFullName(); *s; s++) if (isalnum(*s)) *d++ = *s; *d = '\0'; e->setName(interfaceName); delete [] interfaceName; const char *addrstr = par("address"); if (!strcmp(addrstr, "auto")) { // assign automatic address myMacAddr = MACAddress::generateAutoAddress(); // change module parameter from "auto" to concrete address par("address").setStringValue(myMacAddr.str().c_str()); } else { myMacAddr.setAddress(addrstr); } e->setMACAddress(myMacAddr); // generate interface identifier for IPv6 e->setInterfaceToken(myMacAddr.formInterfaceIdentifier()); // MTU on 802.11 = ? e->setMtu(par("mtu")); // FIXME // capabilities e->setBroadcast(true); e->setMulticast(true); e->setPointToPoint(false); // add IInterfaceTable *ift = InterfaceTableAccess().get(); ift->addInterface(e, this); }
void Mac80211::sendACKframe | ( | Mac80211Pkt * | af | ) | [protected, virtual] |
send Acknoledgement
Send an ACK frame.Called by HandleEndSifsTimer()
Referenced by handleEndSifsTimer().
{ // the MAC must wait the end of the transmission before beginning an // other contention period scheduleAt(simTime() + computePacketDuration(LENGTH_ACK) + delta, endTransmission); // send ACK frame sendDown(buildACKframe(af)); EV << "sent ACK frame!\n"; // update state and display setState(BUSY); }
void Mac80211::sendBROADCASTframe | ( | ) | [protected, virtual] |
send broadcast frame
Send a BROADCAST frame.Called by handleContentionTimer()
Referenced by handleEndContentionTimer().
{ // the MAC must wait the end of the transmission before beginning any // other contention period scheduleAt(simTime() + computePacketDuration(fromUpperLayer.front()->getBitLength()), endTransmission); // send ACK frame sendDown(buildBROADCASTframe()); // update state and display setState(BUSY); }
void Mac80211::sendCTSframe | ( | Mac80211Pkt * | af | ) | [protected, virtual] |
send CTS frame
Send a CTS frame.Called by HandleEndSifsTimer()
Referenced by handleEndSifsTimer().
{ // schedule time-out scheduleAt(simTime() + computeTimeout(CTS, af->getDuration()), timeout); // send CTS frame sendDown(buildCTSframe(af)); // update state and display setState(WFDATA); }
void Mac80211::sendDATAframe | ( | ) | [protected, virtual] |
send data frame
Send a DATA frame. Called by HandleEndSifsTimer() or handleEndContentionTimer()
Referenced by handleEndContentionTimer(), and handleEndSifsTimer().
{ EV << "sending data frame\n"; // schedule time out scheduleAt(simTime() + computeTimeout(DATA, 0), timeout); if (!rtsCts) // retryCounter incremented retryCounter++; // send DATA frame sendDown(buildDATAframe()); // update state and display setState(WFACK); }
void Mac80211::sendRTSframe | ( | ) | [protected, virtual] |
send RTS frame
Send a RTS frame.Called by handleContentionTimer()
Referenced by handleEndContentionTimer().
{ // schedule time-out scheduleAt(simTime() + computeTimeout(RTS, 0), timeout); // long_retry_counter incremented retryCounter++; // send RTS frame sendDown(buildRTSframe()); // update state and display setState(WFCTS); }
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().
const char * Mac80211::stateName | ( | State | state | ) | [static, protected] |
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().
{ if (retryCounter > RETRY_LIMIT) { // initialize counter retryCounter = 1; // reportLost(fromUpperLayer.front()); // delete the frame to transmit Mac80211Pkt *temp = fromUpperLayer.front(); fromUpperLayer.pop_front(); delete(temp); } }
const char * Mac80211::timerTypeName | ( | int | type | ) | [static, protected] |
Produce a readable name of the given timer type.
Referenced by handleSelfMsg().
{ #define CASE(x) case x: s=#x; break const char *s = "???"; switch (type) { CASE(TIMEOUT); CASE(NAV); CASE(CONTENTION); CASE(END_TRANSMISSION); CASE(END_SIFS); } return s; #undef CASE }
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().
simtime_t Mac80211::BW [protected] |
Variable to store the current backoff value.
Referenced by computeBackoff(), handleEndContentionTimer(), initialize(), and receiveChangeNotification().
cMessage* Mac80211::contention [protected] |
Timer used for contention periods.
Referenced by beginNewCycle(), handleMsgNotForMe(), initialize(), Mac80211(), receiveChangeNotification(), and ~Mac80211().
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().
simtime_t Mac80211::EIFS [protected] |
extended interframe space
Referenced by handleMsgNotForMe(), and initialize().
cMessage* Mac80211::endSifs [protected] |
Timer used to indicate the end of a SIFS.
Referenced by handleCTSframe(), handleDATAframe(), handleEndSifsTimer(), handleRTSframe(), handleUpperMsg(), 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().
MacPktList Mac80211::fromUpperLayer [protected] |
Buffering of messages from upper layer.
Referenced by beginNewCycle(), buildBROADCASTframe(), buildDATAframe(), buildRTSframe(), computeTimeout(), handleACKframe(), handleEndContentionTimer(), handleUpperMsg(), receiveChangeNotification(), sendBROADCASTframe(), and testMaxAttempts().
int Mac80211::maxQueueSize [protected] |
Maximal number of packets in the queue; should be set in the omnetpp.ini.
Referenced by handleUpperMsg(), and initialize().
MACAddress Mac80211::myMacAddr [protected] |
mac address
Referenced by buildACKframe(), buildCTSframe(), buildDATAframe(), encapsMsg(), handleLowerMsg(), and registerInterface().
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().
bool Mac80211::nextIsBroadcast [protected] |
Boolean used to know if the next packet is a broadcast packet.
Referenced by beginNewCycle(), computeContentionWindow(), and handleEndContentionTimer().
RadioState::State Mac80211::radioState [protected] |
Current state of the radio (kept updated by receiveChangeNotification())
Referenced by beginNewCycle(), initialize(), and receiveChangeNotification().
int Mac80211::retryCounter [protected] |
Number of frame transmission attempt.
Referenced by computeContentionWindow(), handleACKframe(), initialize(), sendDATAframe(), sendRTSframe(), and testMaxAttempts().
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().
State Mac80211::state [protected] |
Current state of the MAC.
Referenced by handleBroadcastMsg(), handleEndContentionTimer(), handleEndTransmissionTimer(), handleLowerMsg(), handleMsgForMe(), handleMsgNotForMe(), handleNavTimer(), handleTimeoutTimer(), handleUpperMsg(), initialize(), and setState().
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().
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().