#include <Ieee80211Mac.h>
Inheritance diagram for Ieee80211Mac:
Various comments in the code refer to the Wireless LAN Medium Access Control (MAC) and Physical Layer(PHY) Specifications ANSI/IEEE Std 802.11, 1999 Edition (R2003)
For more info, see the NED file.
TODO: support fragmentation TODO: PCF mode TODO: CF period TODO: pass radio power to upper layer TODO: transmission complete notification to upper layer TODO: STA TCF timer syncronization, see Chapter 11 pp 123
Parts of the implementation have been taken over from the Mobility Framework's Mac80211 module.
Ieee80211Mac state variables | |
Various state information checked and modified according to the state machine. | |
enum | State { IDLE, DEFER, WAITDIFS, BACKOFF, WAITACK, WAITBROADCAST, WAITCTS, WAITSIFS, RECEIVE } |
enum | Mode { DCF, PCF } |
cFSM | fsm |
Mode | mode |
int | sequenceNumber |
bool | lastReceiveFailed |
bool | backoff |
bool | nav |
double | backoffPeriod |
int | retryCounter |
RadioState::State | radioState |
Ieee80211DataOrMgmtFrameList | transmissionQueue |
Ieee80211ASFTupleList | asfTuplesList |
IPassiveQueue * | queueModule |
cMessage * | pendingRadioConfigMsg |
Configuration parameters | |
These are filled in during the initialization phase and not supposed to change afterwards. | |
MACAddress | address |
double | bitrate |
double | basicBitrate |
int | maxQueueSize |
int | rtsThreshold |
int | retryLimit |
int | cwMinData |
int | cwMinBroadcast |
static const int | fragmentationThreshold = 2346 |
Public Member Functions | |
Construction functions | |
Ieee80211Mac () | |
virtual | ~Ieee80211Mac () |
Protected Member Functions | |
Ieee80211Frame * | setBasicBitrate (Ieee80211Frame *frame) |
Attaches a PhyControlInfo to the frame which will cause it to be sent at basicBitrate not bitrate (e.g. 2Mbps instead of 11Mbps). Used with ACK, CTS, RTS. | |
Initialization functions | |
virtual int | numInitStages () const |
Initialization of the module and its variables. | |
virtual void | initialize (int) |
Initialization of the module and some variables. | |
virtual void | registerInterface () |
virtual void | initializeQueueModule () |
Message handing functions | |
Functions called from other classes to notify about state changes and to handle messages. | |
virtual void | receiveChangeNotification (int category, cPolymorphic *details) |
Called by the NotificationBoard whenever a change occurs we're interested in. | |
virtual void | handleCommand (cMessage *msg) |
Handle commands (msg kind+control info) coming from upper layers. | |
virtual void | handleSelfMsg (cMessage *msg) |
Handle timer self messages. | |
virtual void | handleUpperMsg (cMessage *msg) |
Handle messages from upper layer. | |
virtual void | handleLowerMsg (cMessage *msg) |
Handle messages from lower (physical) layer. | |
virtual void | handleWithFSM (cMessage *msg) |
Handle all kinds of messages and notifications with the state machine. | |
Timing functions | |
Calculate various timings based on transmission rate and physical layer charactersitics. | |
simtime_t | SIFSPeriod () |
simtime_t | SlotPeriod () |
simtime_t | DIFSPeriod () |
simtime_t | EIFSPeriod () |
simtime_t | PIFSPeriod () |
simtime_t | BackoffPeriod (Ieee80211Frame *msg, int r) |
Timer functions | |
These functions have the side effect of starting the corresponding timers. | |
void | scheduleSIFSPeriod (Ieee80211Frame *frame) |
void | scheduleDIFSPeriod () |
void | cancelDIFSPeriod () |
void | scheduleDataTimeoutPeriod (Ieee80211DataOrMgmtFrame *frame) |
void | scheduleBroadcastTimeoutPeriod (Ieee80211DataOrMgmtFrame *frame) |
void | cancelTimeoutPeriod () |
void | scheduleCTSTimeoutPeriod () |
void | scheduleReservePeriod (Ieee80211Frame *frame) |
Schedule network allocation period according to 9.2.5.4. | |
void | invalidateBackoffPeriod () |
Generates a new backoff period based on the contention window. | |
bool | isInvalidBackoffPeriod () |
void | generateBackoffPeriod () |
void | decreaseBackoffPeriod () |
void | scheduleBackoffPeriod () |
void | cancelBackoffPeriod () |
Frame transmission functions | |
void | sendACKFrameOnEndSIFS () |
void | sendACKFrame (Ieee80211DataOrMgmtFrame *frame) |
void | sendRTSFrame (Ieee80211DataOrMgmtFrame *frameToSend) |
void | sendCTSFrameOnEndSIFS () |
void | sendCTSFrame (Ieee80211RTSFrame *rtsFrame) |
void | sendDataFrameOnEndSIFS (Ieee80211DataOrMgmtFrame *frameToSend) |
void | sendDataFrame (Ieee80211DataOrMgmtFrame *frameToSend) |
void | sendBroadcastFrame (Ieee80211DataOrMgmtFrame *frameToSend) |
Frame builder functions | |
Ieee80211DataOrMgmtFrame * | buildDataFrame (Ieee80211DataOrMgmtFrame *frameToSend) |
Ieee80211ACKFrame * | buildACKFrame (Ieee80211DataOrMgmtFrame *frameToACK) |
Ieee80211RTSFrame * | buildRTSFrame (Ieee80211DataOrMgmtFrame *frameToSend) |
Ieee80211CTSFrame * | buildCTSFrame (Ieee80211RTSFrame *rtsFrame) |
Ieee80211DataOrMgmtFrame * | buildBroadcastFrame (Ieee80211DataOrMgmtFrame *frameToSend) |
Utility functions | |
void | finishCurrentTransmission () |
void | giveUpCurrentTransmission () |
void | retryCurrentTransmission () |
void | sendDownPendingRadioConfigMsg () |
Send down the change channel message to the physical layer if there is any. | |
void | setMode (Mode mode) |
Change the current MAC operation mode. | |
Ieee80211DataOrMgmtFrame * | currentTransmission () |
Returns the current frame being transmitted. | |
void | resetStateVariables () |
Reset backoff, backoffPeriod and retryCounter for IDLE state. | |
bool | isMediumStateChange (cMessage *msg) |
Used by the state machine to identify medium state change events. This message is currently optimized away and not sent through the kernel. | |
bool | isMediumFree () |
Tells if the medium is free according to the physical and virtual carrier sense algorithm. | |
bool | isBroadcast (Ieee80211Frame *msg) |
Returns true if message is a broadcast message. | |
bool | isForUs (Ieee80211Frame *msg) |
Returns true if message destination address is ours. | |
bool | isDataOrMgmtFrame (Ieee80211Frame *frame) |
Checks if the frame is a data or management frame. | |
Ieee80211Frame * | frameReceivedBeforeSIFS () |
Returns the last frame received before the SIFS period. | |
void | popTransmissionQueue () |
Deletes frame at the front of queue. | |
double | frameDuration (Ieee80211Frame *msg) |
Computes the duration (in seconds) of the transmission of a frame over the physical channel. 'bits' should be the total length of the MAC frame in bits, but excluding the physical layer framing (preamble etc.). | |
double | frameDuration (int bits, double bitrate) |
void | logState () |
Logs all state information. | |
const char * | modeName (int mode) |
Produce a readable name of the given MAC operation mode. | |
Protected Attributes | |
Timer messages | |
cMessage * | endSIFS |
cMessage * | endDIFS |
cMessage * | endBackoff |
cMessage * | endTimeout |
cMessage * | endReserve |
cMessage * | mediumStateChange |
Statistics | |
long | numRetry |
long | numSentWithoutRetry |
long | numGivenUp |
long | numCollision |
long | numSent |
long | numReceived |
long | numSentBroadcast |
long | numReceivedBroadcast |
cOutVector | stateVector |
cOutVector | radioStateVector |
Private Types | |
typedef std::list< Ieee80211DataOrMgmtFrame * > | Ieee80211DataOrMgmtFrameList |
typedef std::list< Ieee80211ASFTuple * > | Ieee80211ASFTupleList |
Classes | |
struct | Ieee80211ASFTuple |
|
|
|
|
|
80211 MAC operation modes
|
|
the 80211 MAC state machine 00115 { 00116 IDLE, 00117 DEFER, 00118 WAITDIFS, 00119 BACKOFF, 00120 WAITACK, 00121 WAITBROADCAST, 00122 WAITCTS, 00123 WAITSIFS, 00124 RECEIVE, 00125 };
|
|
00031 { 00032 endSIFS = NULL; 00033 endDIFS = NULL; 00034 endBackoff = NULL; 00035 endTimeout = NULL; 00036 endReserve = NULL; 00037 mediumStateChange = NULL; 00038 pendingRadioConfigMsg = NULL; 00039 }
|
|
00042 {
00043 cancelAndDelete(endSIFS);
00044 cancelAndDelete(endDIFS);
00045 cancelAndDelete(endBackoff);
00046 cancelAndDelete(endTimeout);
00047 cancelAndDelete(endReserve);
00048 cancelAndDelete(mediumStateChange);
00049
00050 if (pendingRadioConfigMsg)
00051 delete pendingRadioConfigMsg;
00052 }
|
|
00605 { 00606 int cw; 00607 00608 EV << "generating backoff slot number for retry: " << r << endl; 00609 00610 if (isBroadcast(msg)) 00611 cw = cwMinBroadcast; 00612 else 00613 { 00614 ASSERT(0 <= r && r <= retryLimit); 00615 00616 cw = (cwMinData + 1) * (1 << r) - 1; 00617 00618 if (cw > CW_MAX) 00619 cw = CW_MAX; 00620 } 00621 00622 int c = intrand(cw + 1); 00623 00624 EV << "generated backoff slot number: " << c << " , cw: " << cw << endl; 00625 00626 return ((double)c) * SlotPeriod(); 00627 }
|
|
00827 { 00828 Ieee80211ACKFrame *frame = new Ieee80211ACKFrame("wlan-ack"); 00829 frame->setReceiverAddress(frameToACK->getTransmitterAddress()); 00830 00831 if (!frameToACK->getMoreFragments()) 00832 frame->setDuration(0); 00833 else 00834 frame->setDuration(frameToACK->getDuration() - SIFSPeriod() - frameDuration(LENGTH_ACK, basicBitrate)); 00835 00836 return frame; 00837 }
|
|
00861 { 00862 Ieee80211DataOrMgmtFrame *frame = (Ieee80211DataOrMgmtFrame *)frameToSend->dup(); 00863 frame->setDuration(0); 00864 return frame; 00865 }
|
|
00852 { 00853 Ieee80211CTSFrame *frame = new Ieee80211CTSFrame("wlan-cts"); 00854 frame->setReceiverAddress(rtsFrame->getTransmitterAddress()); 00855 frame->setDuration(rtsFrame->getDuration() - SIFSPeriod() - frameDuration(LENGTH_CTS, basicBitrate)); 00856 00857 return frame; 00858 }
|
|
00812 { 00813 Ieee80211DataOrMgmtFrame *frame = (Ieee80211DataOrMgmtFrame *)frameToSend->dup(); 00814 00815 if (isBroadcast(frameToSend)) 00816 frame->setDuration(0); 00817 else if (!frameToSend->getMoreFragments()) 00818 frame->setDuration(SIFSPeriod() + frameDuration(LENGTH_ACK, basicBitrate)); 00819 else 00820 // FIXME: shouldn't we use the next frame to be sent? 00821 frame->setDuration(3 * SIFSPeriod() + 2 * frameDuration(LENGTH_ACK, basicBitrate) + frameDuration(frameToSend)); 00822 00823 return frame; 00824 }
|
|
00840 { 00841 Ieee80211RTSFrame *frame = new Ieee80211RTSFrame("wlan-rts"); 00842 frame->setTransmitterAddress(address); 00843 frame->setReceiverAddress(frameToSend->getReceiverAddress()); 00844 frame->setDuration(3 * SIFSPeriod() + frameDuration(LENGTH_CTS, basicBitrate) + 00845 frameDuration(frameToSend) + 00846 frameDuration(LENGTH_ACK, basicBitrate)); 00847 00848 return frame; 00849 }
|
|
00746 { 00747 EV << "cancelling Backoff period\n"; 00748 cancelEvent(endBackoff); 00749 }
|
|
00654 { 00655 EV << "cancelling DIFS period\n"; 00656 cancelEvent(endDIFS); 00657 }
|
|
00672 { 00673 EV << "cancelling timeout period\n"; 00674 cancelEvent(endTimeout); 00675 }
|
|
Returns the current frame being transmitted.
00903 { 00904 return (Ieee80211DataOrMgmtFrame *)transmissionQueue.front(); 00905 }
|
|
00731 { 00732 // see spec 9.2.5.2 00733 simtime_t elapsedBackoffTime = simTime() - endBackoff->sendingTime(); 00734 backoffPeriod -= ((int)(elapsedBackoffTime / SlotPeriod())) * SlotPeriod(); 00735 ASSERT(backoffPeriod >= 0); 00736 EV << "backoff period decreased to " << backoffPeriod << endl; 00737 }
|
|
00594 { 00595 return SIFSPeriod() + 2 * SlotPeriod(); 00596 }
|
|
00599 { 00600 // FIXME: return SIFSPeriod() + DIFSPeriod() + (8 * ACKSize + aPreambleLength + aPLCPHeaderLength) / lowestDatarate; 00601 return SIFSPeriod() + DIFSPeriod() + (8 * LENGTH_ACK + PHY_HEADER_LENGTH) / 1E+6; 00602 }
|
|
00880 { 00881 popTransmissionQueue(); 00882 resetStateVariables(); 00883 }
|
|
00989 { 00990 return bits / bitrate + PHY_HEADER_LENGTH / BITRATE_HEADER; 00991 }
|
|
Computes the duration (in seconds) of the transmission of a frame over the physical channel. 'bits' should be the total length of the MAC frame in bits, but excluding the physical layer framing (preamble etc.).
00984 { 00985 return frameDuration(msg->length(), bitrate); 00986 }
|
|
Returns the last frame received before the SIFS period.
00964 { 00965 return (Ieee80211Frame *)endSIFS->contextPointer(); 00966 }
|
|
00724 { 00725 backoffPeriod = BackoffPeriod(currentTransmission(), retryCounter); 00726 ASSERT(backoffPeriod >= 0); 00727 EV << "backoff period set to " << backoffPeriod << endl; 00728 }
|
|
00886 { 00887 popTransmissionQueue(); 00888 resetStateVariables(); 00889 numGivenUp++; 00890 }
|
|
Handle commands (msg kind+control info) coming from upper layers.
00250 { 00251 if (msg->kind()==PHY_C_CONFIGURERADIO) 00252 { 00253 EV << "Passing on command " << msg->name() << " to physical layer\n"; 00254 if (pendingRadioConfigMsg != NULL) 00255 { 00256 // merge contents of the old command into the new one, then delete it 00257 PhyControlInfo *pOld = check_and_cast<PhyControlInfo *>(pendingRadioConfigMsg->controlInfo()); 00258 PhyControlInfo *pNew = check_and_cast<PhyControlInfo *>(msg->controlInfo()); 00259 if (pNew->channelNumber()==-1 && pOld->channelNumber()!=-1) 00260 pNew->setChannelNumber(pOld->channelNumber()); 00261 if (pNew->bitrate()==-1 && pOld->bitrate()!=-1) 00262 pNew->setBitrate(pOld->bitrate()); 00263 delete pendingRadioConfigMsg; 00264 pendingRadioConfigMsg = NULL; 00265 } 00266 00267 if (fsm.state() == IDLE || fsm.state() == DEFER || fsm.state() == BACKOFF) 00268 { 00269 EV << "Sending it down immediately\n"; 00270 sendDown(msg); 00271 } 00272 else 00273 { 00274 EV << "Delaying " << msg->name() << " until next IDLE or DEFER state\n"; 00275 pendingRadioConfigMsg = msg; 00276 } 00277 } 00278 else 00279 { 00280 error("Unrecognized command from mgmt layer: (%s)%s msgkind=%d", msg->className(), msg->name(), msg->kind()); 00281 } 00282 }
|
|
Handle messages from lower (physical) layer.
Implements WirelessMacBase. 00285 { 00286 EV << "received message from lower layer: " << msg << endl; 00287 00288 Ieee80211Frame *frame = dynamic_cast<Ieee80211Frame *>(msg); 00289 if (!frame) 00290 error("message from physical layer (%s)%s is not a subclass of Ieee80211Frame", 00291 msg->className(), msg->name()); 00292 00293 EV << "Self address: " << address 00294 << ", receiver address: " << frame->getReceiverAddress() 00295 << ", received frame is for us: " << isForUs(frame) << endl; 00296 00297 Ieee80211TwoAddressFrame *twoAddressFrame = dynamic_cast<Ieee80211TwoAddressFrame *>(msg); 00298 ASSERT(!twoAddressFrame || twoAddressFrame->getTransmitterAddress() != address); 00299 00300 handleWithFSM(msg); 00301 00302 // if we are the owner then we did not send this message up 00303 if (msg->owner() == this) 00304 delete msg; 00305 }
|
|
Handle timer self messages.
Implements WirelessMacBase. 00204 { 00205 EV << "received self message: " << msg << endl; 00206 00207 if (msg == endReserve) 00208 nav = false; 00209 00210 handleWithFSM(msg); 00211 }
|
|
Handle messages from upper layer.
Implements WirelessMacBase. 00214 { 00215 // check if it's a command from the mgmt layer 00216 if (msg->length()==0 && msg->kind()!=0) 00217 { 00218 handleCommand(msg); 00219 return; 00220 } 00221 00222 // check for queue overflow 00223 if (maxQueueSize && transmissionQueue.size() == maxQueueSize) 00224 { 00225 EV << "message " << msg << " received from higher layer but MAC queue is full, dropping message\n"; 00226 delete msg; 00227 return; 00228 } 00229 00230 // must be a Ieee80211DataOrMgmtFrame, within the max size because we don't support fragmentation 00231 Ieee80211DataOrMgmtFrame *frame = check_and_cast<Ieee80211DataOrMgmtFrame *>(msg); 00232 if (frame->byteLength() > fragmentationThreshold) 00233 error("message from higher layer (%s)%s is too long for 802.11b, %d bytes (fragmentation is not supported yet)", 00234 msg->className(), msg->name(), msg->byteLength()); 00235 EV << "frame " << frame << " received from higher layer, receiver = " << frame->getReceiverAddress() << endl; 00236 00237 ASSERT(!frame->getReceiverAddress().isUnspecified()); 00238 00239 // fill in missing fields (receiver address, seq number), and insert into the queue 00240 frame->setTransmitterAddress(address); 00241 frame->setSequenceNumber(sequenceNumber); 00242 sequenceNumber = (sequenceNumber+1) % 4096; //XXX seqNum must be checked upon reception of frames! 00243 00244 transmissionQueue.push_back(frame); 00245 00246 handleWithFSM(frame); 00247 }
|
|
Handle all kinds of messages and notifications with the state machine. Msg can be upper, lower, self or NULL (when radio state changes) 00330 { 00331 // skip those cases where there's nothing to do, so the switch looks simpler 00332 if (isUpperMsg(msg) && fsm.state() != IDLE) 00333 { 00334 EV << "deferring upper message transmission in " << fsm.stateName() << " state\n"; 00335 return; 00336 } 00337 00338 Ieee80211Frame *frame = dynamic_cast<Ieee80211Frame*>(msg); 00339 int frameType = frame ? frame->getType() : -1; 00340 int msgKind = msg->kind(); 00341 logState(); 00342 stateVector.record(fsm.state()); 00343 00344 if (frame && isLowerMsg(frame)) 00345 { 00346 lastReceiveFailed =(msgKind == COLLISION || msgKind == BITERROR); 00347 scheduleReservePeriod(frame); 00348 } 00349 00350 FSMA_Switch(fsm) 00351 { 00352 FSMA_State(IDLE) 00353 { 00354 FSMA_Enter(sendDownPendingRadioConfigMsg()); 00355 FSMA_Event_Transition(Data-Ready, 00356 isUpperMsg(msg), 00357 DEFER, 00358 invalidateBackoffPeriod(); 00359 ); 00360 FSMA_No_Event_Transition(Immediate-Data-Ready, 00361 !transmissionQueue.empty(), 00362 DEFER, 00363 invalidateBackoffPeriod(); 00364 ); 00365 FSMA_Event_Transition(Receive, 00366 isLowerMsg(msg), 00367 RECEIVE, 00368 ); 00369 } 00370 FSMA_State(DEFER) 00371 { 00372 FSMA_Enter(sendDownPendingRadioConfigMsg()); 00373 FSMA_Event_Transition(Wait-DIFS, 00374 isMediumStateChange(msg) && isMediumFree(), 00375 WAITDIFS, 00376 ;); 00377 FSMA_No_Event_Transition(Immediate-Wait-DIFS, 00378 isMediumFree() || !backoff, 00379 WAITDIFS, 00380 ;); 00381 FSMA_Event_Transition(Receive, 00382 isLowerMsg(msg), 00383 RECEIVE, 00384 ;); 00385 } 00386 FSMA_State(WAITDIFS) 00387 { 00388 FSMA_Enter(scheduleDIFSPeriod()); 00389 FSMA_Event_Transition(Immediate-Transmit-RTS, 00390 msg == endDIFS && !isBroadcast(currentTransmission()) 00391 && currentTransmission()->byteLength() >= rtsThreshold && !backoff, 00392 WAITCTS, 00393 sendRTSFrame(currentTransmission()); 00394 cancelDIFSPeriod(); 00395 ); 00396 FSMA_Event_Transition(Immediate-Transmit-Broadcast, 00397 msg == endDIFS && isBroadcast(currentTransmission()) && !backoff, 00398 WAITBROADCAST, 00399 sendBroadcastFrame(currentTransmission()); 00400 cancelDIFSPeriod(); 00401 ); 00402 FSMA_Event_Transition(Immediate-Transmit-Data, 00403 msg == endDIFS && !isBroadcast(currentTransmission()) && !backoff, 00404 WAITACK, 00405 sendDataFrame(currentTransmission()); 00406 cancelDIFSPeriod(); 00407 ); 00408 FSMA_Event_Transition(DIFS-Over, 00409 msg == endDIFS, 00410 BACKOFF, 00411 ASSERT(backoff); 00412 if (isInvalidBackoffPeriod()) 00413 generateBackoffPeriod(); 00414 ); 00415 FSMA_Event_Transition(Busy, 00416 isMediumStateChange(msg) && !isMediumFree(), 00417 DEFER, 00418 backoff = true; 00419 cancelDIFSPeriod(); 00420 ); 00421 FSMA_No_Event_Transition(Immediate-Busy, 00422 !isMediumFree(), 00423 DEFER, 00424 backoff = true; 00425 cancelDIFSPeriod(); 00426 ); 00427 // radio state changes before we actually get the message, so this must be here 00428 FSMA_Event_Transition(Receive, 00429 isLowerMsg(msg), 00430 RECEIVE, 00431 cancelDIFSPeriod(); 00432 ;); 00433 } 00434 FSMA_State(BACKOFF) 00435 { 00436 FSMA_Enter(scheduleBackoffPeriod()); 00437 FSMA_Event_Transition(Transmit-RTS, 00438 msg == endBackoff && !isBroadcast(currentTransmission()) 00439 && currentTransmission()->byteLength() >= rtsThreshold, 00440 WAITCTS, 00441 sendRTSFrame(currentTransmission()); 00442 ); 00443 FSMA_Event_Transition(Transmit-Broadcast, 00444 msg == endBackoff && isBroadcast(currentTransmission()), 00445 WAITBROADCAST, 00446 sendBroadcastFrame(currentTransmission()); 00447 ); 00448 FSMA_Event_Transition(Transmit-Data, 00449 msg == endBackoff && !isBroadcast(currentTransmission()), 00450 WAITACK, 00451 sendDataFrame(currentTransmission()); 00452 ); 00453 FSMA_Event_Transition(Backoff-Busy, 00454 isMediumStateChange(msg) && !isMediumFree(), 00455 DEFER, 00456 cancelBackoffPeriod(); 00457 decreaseBackoffPeriod(); 00458 ); 00459 } 00460 FSMA_State(WAITACK) 00461 { 00462 FSMA_Enter(scheduleDataTimeoutPeriod(currentTransmission())); 00463 FSMA_Event_Transition(Receive-ACK, 00464 isLowerMsg(msg) && isForUs(frame) && frameType == ST_ACK, 00465 IDLE, 00466 cancelTimeoutPeriod(); 00467 finishCurrentTransmission(); 00468 if (retryCounter == 0) numSentWithoutRetry++; 00469 numSent++; 00470 ); 00471 FSMA_Event_Transition(Transmit-Data-Failed, 00472 msg == endTimeout && retryCounter == retryLimit, 00473 IDLE, 00474 giveUpCurrentTransmission(); 00475 ); 00476 FSMA_Event_Transition(Receive-ACK-Timeout, 00477 msg == endTimeout, 00478 DEFER, 00479 retryCurrentTransmission(); 00480 ); 00481 } 00482 // wait until broadcast is sent 00483 FSMA_State(WAITBROADCAST) 00484 { 00485 FSMA_Enter(scheduleBroadcastTimeoutPeriod(currentTransmission())); 00486 FSMA_Event_Transition(Transmit-Broadcast, 00487 msg == endTimeout, 00488 IDLE, 00489 finishCurrentTransmission(); 00490 numSentBroadcast++; 00491 ); 00492 } 00493 // accoriding to 9.2.5.7 CTS procedure 00494 FSMA_State(WAITCTS) 00495 { 00496 FSMA_Enter(scheduleCTSTimeoutPeriod()); 00497 FSMA_Event_Transition(Receive-CTS, 00498 isLowerMsg(msg) && isForUs(frame) && frameType == ST_CTS, 00499 WAITSIFS, 00500 cancelTimeoutPeriod(); 00501 ); 00502 FSMA_Event_Transition(Transmit-RTS-Failed, 00503 msg == endTimeout && retryCounter == retryLimit, 00504 IDLE, 00505 giveUpCurrentTransmission(); 00506 ); 00507 FSMA_Event_Transition(Receive-CTS-Timeout, 00508 msg == endTimeout, 00509 DEFER, 00510 retryCurrentTransmission(); 00511 ); 00512 } 00513 FSMA_State(WAITSIFS) 00514 { 00515 FSMA_Enter(scheduleSIFSPeriod(frame)); 00516 FSMA_Event_Transition(Transmit-CTS, 00517 msg == endSIFS && frameReceivedBeforeSIFS()->getType() == ST_RTS, 00518 IDLE, 00519 sendCTSFrameOnEndSIFS(); 00520 resetStateVariables(); 00521 ); 00522 FSMA_Event_Transition(Transmit-DATA, 00523 msg == endSIFS && frameReceivedBeforeSIFS()->getType() == ST_CTS, 00524 WAITACK, 00525 sendDataFrameOnEndSIFS(currentTransmission()); 00526 ); 00527 FSMA_Event_Transition(Transmit-ACK, 00528 msg == endSIFS && isDataOrMgmtFrame(frameReceivedBeforeSIFS()), 00529 IDLE, 00530 sendACKFrameOnEndSIFS(); 00531 resetStateVariables(); 00532 ); 00533 } 00534 // this is not a real state 00535 FSMA_State(RECEIVE) 00536 { 00537 FSMA_No_Event_Transition(Immediate-Receive-Error, 00538 isLowerMsg(msg) && (msgKind == COLLISION || msgKind == BITERROR), 00539 IDLE, 00540 EV << "received frame contains bit errors or collision, next wait period is EIFS\n"; 00541 numCollision++; 00542 resetStateVariables(); 00543 ); 00544 FSMA_No_Event_Transition(Immediate-Receive-Broadcast, 00545 isLowerMsg(msg) && isBroadcast(frame) && isDataOrMgmtFrame(frame), 00546 IDLE, 00547 sendUp(frame); 00548 numReceivedBroadcast++; 00549 resetStateVariables(); 00550 ); 00551 FSMA_No_Event_Transition(Immediate-Receive-Data, 00552 isLowerMsg(msg) && isForUs(frame) && isDataOrMgmtFrame(frame), 00553 WAITSIFS, 00554 sendUp(frame); 00555 numReceived++; 00556 ); 00557 FSMA_No_Event_Transition(Immediate-Receive-RTS, 00558 isLowerMsg(msg) && isForUs(frame) && frameType == ST_RTS, 00559 WAITSIFS, 00560 ); 00561 FSMA_No_Event_Transition(Immediate-Receive-Other, 00562 isLowerMsg(msg), 00563 IDLE, 00564 resetStateVariables(); 00565 ); 00566 } 00567 } 00568 00569 logState(); 00570 stateVector.record(fsm.state()); 00571 }
|
|
Initialization of the module and some variables.
Reimplemented from WirelessMacBase. 00058 { 00059 WirelessMacBase::initialize(stage); 00060 00061 if (stage == 0) 00062 { 00063 EV << "Initializing stage 0\n"; 00064 00065 // initialize parameters 00066 maxQueueSize = par("maxQueueSize"); 00067 bitrate = par("bitrate"); 00068 basicBitrate = 2e6; //FIXME make it parameter 00069 rtsThreshold = par("rtsThresholdBytes"); 00070 00071 retryLimit = par("retryLimit"); 00072 if (retryLimit == -1) retryLimit = 7; 00073 ASSERT(retryLimit >= 0); 00074 00075 cwMinData = par("cwMinData"); 00076 if (cwMinData == -1) cwMinData = CW_MIN; 00077 ASSERT(cwMinData >= 0); 00078 00079 cwMinBroadcast = par("cwMinBroadcast"); 00080 if (cwMinBroadcast == -1) cwMinBroadcast = 31; 00081 ASSERT(cwMinBroadcast >= 0); 00082 00083 const char *addressString = par("address"); 00084 if (!strcmp(addressString, "auto")) { 00085 // assign automatic address 00086 address = MACAddress::generateAutoAddress(); 00087 // change module parameter from "auto" to concrete address 00088 par("address").setStringValue(address.str().c_str()); 00089 } 00090 else 00091 address.setAddress(addressString); 00092 00093 // subscribe for the information of the carrier sense 00094 nb->subscribe(this, NF_RADIOSTATE_CHANGED); 00095 00096 // initalize self messages 00097 endSIFS = new cMessage("SIFS"); 00098 endDIFS = new cMessage("DIFS"); 00099 endBackoff = new cMessage("Backoff"); 00100 endTimeout = new cMessage("Timeout"); 00101 endReserve = new cMessage("Reserve"); 00102 mediumStateChange = new cMessage("MediumStateChange"); 00103 00104 // interface 00105 registerInterface(); 00106 00107 // obtain pointer to external queue 00108 initializeQueueModule(); 00109 00110 // state variables 00111 fsm.setName("Ieee80211Mac State Machine"); 00112 mode = DCF; 00113 sequenceNumber = 0; 00114 radioState = RadioState::IDLE; 00115 retryCounter = 0; 00116 backoff = false; 00117 lastReceiveFailed = false; 00118 nav = false; 00119 00120 // statistics 00121 numRetry = 0; 00122 numSentWithoutRetry = 0; 00123 numGivenUp = 0; 00124 numCollision = 0; 00125 numSent = 0; 00126 numReceived = 0; 00127 numSentBroadcast = 0; 00128 numReceivedBroadcast = 0; 00129 stateVector.setName("State"); 00130 radioStateVector.setName("RadioState"); 00131 00132 // initialize watches 00133 WATCH(fsm); 00134 WATCH(radioState); 00135 WATCH(retryCounter); 00136 WATCH(backoff); 00137 WATCH(nav); 00138 00139 WATCH(numRetry); 00140 WATCH(numSentWithoutRetry); 00141 WATCH(numGivenUp); 00142 WATCH(numCollision); 00143 WATCH(numSent); 00144 WATCH(numReceived); 00145 WATCH(numSentBroadcast); 00146 WATCH(numReceivedBroadcast); 00147 } 00148 }
|
|
00186 { 00187 // use of external queue module is optional -- find it if there's one specified 00188 if (par("queueModule").stringValue()[0]) 00189 { 00190 cModule *module = parentModule()->submodule(par("queueModule").stringValue()); 00191 queueModule = check_and_cast<IPassiveQueue *>(module); 00192 00193 EV << "Requesting first two frames from queue module\n"; 00194 queueModule->requestPacket(); 00195 // needed for backoff: mandatory if next message is already present 00196 queueModule->requestPacket(); 00197 } 00198 }
|
|
Generates a new backoff period based on the contention window.
00714 { 00715 backoffPeriod = -1; 00716 }
|
|
Returns true if message is a broadcast message.
00949 { 00950 return frame && frame->getReceiverAddress().isBroadcast(); 00951 }
|
|
Checks if the frame is a data or management frame.
00959 {
00960 return dynamic_cast<Ieee80211DataOrMgmtFrame*>(frame);
00961 }
|
|
Returns true if message destination address is ours.
00954 { 00955 return frame && frame->getReceiverAddress() == address; 00956 }
|
|
00719 { 00720 return backoffPeriod == -1; 00721 }
|
|
Tells if the medium is free according to the physical and virtual carrier sense algorithm.
00944 { 00945 return radioState == RadioState::IDLE && !endReserve->isScheduled(); 00946 }
|
|
Used by the state machine to identify medium state change events. This message is currently optimized away and not sent through the kernel.
00939 { 00940 return msg == mediumStateChange || (msg == endReserve && radioState == RadioState::IDLE); 00941 }
|
|
Logs all state information.
00994 { 00995 EV << "state information: mode = " << modeName(mode) << ", state = " << fsm.stateName() 00996 << ", backoff = " << backoff << ", backoffPeriod = " << backoffPeriod 00997 << ", retryCounter = " << retryCounter << ", radioState = " << radioState 00998 << ", nav = " << nav << endl; 00999 }
|
|
Produce a readable name of the given MAC operation mode.
01002 { 01003 #define CASE(x) case x: s=#x; break 01004 const char *s = "???"; 01005 switch (mode) 01006 { 01007 CASE(DCF); 01008 CASE(PCF); 01009 } 01010 return s; 01011 #undef CASE 01012 }
|
|
Initialization of the module and its variables.
00235 {return 2;}
|
|
00589 { 00590 return SIFSPeriod() + SlotPeriod(); 00591 }
|
|
Deletes frame at the front of queue.
00969 { 00970 EV << "dropping frame from transmission queue\n"; 00971 Ieee80211Frame *temp = transmissionQueue.front(); 00972 transmissionQueue.pop_front(); 00973 delete temp; 00974 00975 if (queueModule) 00976 { 00977 // tell queue module that we've become idle 00978 EV << "requesting another frame from queue module\n"; 00979 queueModule->requestPacket(); 00980 } 00981 }
|
|
Called by the NotificationBoard whenever a change occurs we're interested in.
Implements INotifiable. 00308 { 00309 Enter_Method_Silent(); 00310 printNotificationBanner(category, details); 00311 00312 if (category == NF_RADIOSTATE_CHANGED) 00313 { 00314 RadioState::State newRadioState = check_and_cast<RadioState *>(details)->getState(); 00315 00316 // FIXME: double recording, because there's no sample hold in the gui 00317 radioStateVector.record(radioState); 00318 radioStateVector.record(newRadioState); 00319 00320 radioState = newRadioState; 00321 00322 handleWithFSM(mediumStateChange); 00323 } 00324 }
|
|
00151 { 00152 InterfaceTable *ift = InterfaceTableAccess().getIfExists(); 00153 if (!ift) 00154 return; 00155 00156 InterfaceEntry *e = new InterfaceEntry(); 00157 00158 // interface name: NetworkInterface module's name without special characters ([]) 00159 char *interfaceName = new char[strlen(parentModule()->fullName()) + 1]; 00160 char *d = interfaceName; 00161 for (const char *s = parentModule()->fullName(); *s; s++) 00162 if (isalnum(*s)) 00163 *d++ = *s; 00164 *d = '\0'; 00165 00166 e->setName(interfaceName); 00167 delete [] interfaceName; 00168 00169 // address 00170 e->setMACAddress(address); 00171 e->setInterfaceToken(address.formInterfaceIdentifier()); 00172 00173 // FIXME: MTU on 802.11 = ? 00174 e->setMtu(1500); 00175 00176 // capabilities 00177 e->setBroadcast(true); 00178 e->setMulticast(true); 00179 e->setPointToPoint(false); 00180 00181 // add 00182 ift->addInterface(e, this); 00183 }
|
|
Reset backoff, backoffPeriod and retryCounter for IDLE state.
00925 { 00926 backoffPeriod = 0; 00927 retryCounter = 0; 00928 00929 if (!transmissionQueue.empty()) { 00930 backoff = true; 00931 currentTransmission()->setRetry(false); 00932 } 00933 else { 00934 backoff = false; 00935 } 00936 }
|
|
00893 { 00894 ASSERT(retryCounter < retryLimit); 00895 currentTransmission()->setRetry(true); 00896 retryCounter++; 00897 numRetry++; 00898 backoff = true; 00899 generateBackoffPeriod(); 00900 }
|
|
00740 { 00741 EV << "scheduling backoff period\n"; 00742 scheduleAt(simTime() + backoffPeriod, endBackoff); 00743 }
|
|
00666 { 00667 EV << "scheduling broadcast timeout period\n"; 00668 scheduleAt(simTime() + frameDuration(frameToSend), endTimeout); 00669 }
|
|
00678 { 00679 scheduleAt(simTime() + frameDuration(LENGTH_RTS, basicBitrate) + SIFSPeriod() + frameDuration(LENGTH_CTS, basicBitrate) + MAX_PROPAGATION_DELAY * 2, endTimeout); 00680 }
|
|
00660 { 00661 EV << "scheduling data timeout period\n"; 00662 scheduleAt(simTime() + frameDuration(frameToSend) + SIFSPeriod() + frameDuration(LENGTH_ACK, basicBitrate) + MAX_PROPAGATION_DELAY * 2, endTimeout); 00663 }
|
|
00640 { 00641 if (lastReceiveFailed) 00642 { 00643 EV << "receiption of last frame failed, scheduling EIFS period\n"; 00644 scheduleAt(simTime() + EIFSPeriod(), endDIFS); 00645 } 00646 else 00647 { 00648 EV << "scheduling DIFS period\n"; 00649 scheduleAt(simTime() + DIFSPeriod(), endDIFS); 00650 } 00651 }
|
|
Schedule network allocation period according to 9.2.5.4.
00683 { 00684 simtime_t reserve = frame->getDuration(); 00685 00686 // see spec. 7.1.3.2 00687 if (!isForUs(frame) && reserve != 0 && reserve < 32768) 00688 { 00689 if (endReserve->isScheduled()) { 00690 simtime_t oldReserve = endReserve->arrivalTime() - simTime(); 00691 00692 if (oldReserve > reserve) 00693 return; 00694 00695 reserve = max(reserve, oldReserve); 00696 cancelEvent(endReserve); 00697 } 00698 else if (radioState == RadioState::IDLE) 00699 { 00700 // NAV: the channel just became virtually busy according to the spec 00701 scheduleAt(simTime(), mediumStateChange); 00702 } 00703 00704 EV << "scheduling reserve period for: " << reserve << endl; 00705 00706 ASSERT(reserve > 0); 00707 00708 nav = true; 00709 scheduleAt(simTime() + reserve, endReserve); 00710 } 00711 }
|
|
00633 { 00634 EV << "scheduling SIFS period\n"; 00635 endSIFS->setContextPointer(frame->dup()); 00636 scheduleAt(simTime() + SIFSPeriod(), endSIFS); 00637 }
|
|
00763 { 00764 EV << "sending ACK frame\n"; 00765 sendDown(setBasicBitrate(buildACKFrame(frameToACK))); 00766 }
|
|
00755 { 00756 Ieee80211Frame *frameToACK = (Ieee80211Frame *)endSIFS->contextPointer(); 00757 endSIFS->setContextPointer(NULL); 00758 sendACKFrame(check_and_cast<Ieee80211DataOrMgmtFrame*>(frameToACK)); 00759 delete frameToACK; 00760 }
|
|
00783 { 00784 EV << "sending Broadcast frame\n"; 00785 sendDown(buildBroadcastFrame(frameToSend)); 00786 }
|
|
00803 { 00804 EV << "sending CTS frame\n"; 00805 sendDown(setBasicBitrate(buildCTSFrame(rtsFrame))); 00806 }
|
|
00795 { 00796 Ieee80211Frame *rtsFrame = (Ieee80211Frame *)endSIFS->contextPointer(); 00797 endSIFS->setContextPointer(NULL); 00798 sendCTSFrame(check_and_cast<Ieee80211RTSFrame*>(rtsFrame)); 00799 delete rtsFrame; 00800 }
|
|
00777 { 00778 EV << "sending Data frame\n"; 00779 sendDown(buildDataFrame(frameToSend)); 00780 }
|
|
00769 { 00770 Ieee80211Frame *ctsFrame = (Ieee80211Frame *)endSIFS->contextPointer(); 00771 endSIFS->setContextPointer(NULL); 00772 sendDataFrame(frameToSend); 00773 delete ctsFrame; 00774 }
|
|
Send down the change channel message to the physical layer if there is any.
00908 { 00909 if (pendingRadioConfigMsg != NULL) 00910 { 00911 sendDown(pendingRadioConfigMsg); 00912 pendingRadioConfigMsg = NULL; 00913 } 00914 }
|
|
00789 { 00790 EV << "sending RTS frame\n"; 00791 sendDown(setBasicBitrate(buildRTSFrame(frameToSend))); 00792 }
|
|
Attaches a PhyControlInfo to the frame which will cause it to be sent at basicBitrate not bitrate (e.g. 2Mbps instead of 11Mbps). Used with ACK, CTS, RTS.
00868 { 00869 ASSERT(frame->controlInfo()==NULL); 00870 PhyControlInfo *ctrl = new PhyControlInfo(); 00871 ctrl->setBitrate(basicBitrate); 00872 frame->setControlInfo(ctrl); 00873 return frame; 00874 }
|
|
Change the current MAC operation mode.
00917 {
00918 if (mode == PCF)
00919 error("PCF mode not yet supported");
00920
00921 this->mode = mode;
00922 }
|
|
00577 { 00578 // TODO: return aRxRFDelay() + aRxPLCPDelay() + aMACProcessingDelay() + aRxTxTurnaroundTime(); 00579 return SIFS; 00580 }
|
|
00583 { 00584 // TODO: return aCCATime() + aRxTxTurnaroundTime + aAirPropagationTime() + aMACProcessingDelay(); 00585 return ST; 00586 }
|
|
MAC address |
|
A list of last sender, sequence and fragment number tuples to identify duplicates, see spec 9.2.9. TODO: this is not yet used |
|
True if backoff is enabled |
|
Remaining backoff period in seconds |
|
The basic bitrate (1 or 2 Mbps) is used to transmit control frames |
|
The bitrate is used to send data and mgmt frames; be sure to use a valid 802.11 bitrate |
|
Contention window size for broadcast messages. |
|
Minimum contention window. |
|
End of the backoff period |
|
End of the Data Inter-Frame Time period |
|
End of medium reserve period (NAV) when two other nodes were communicating on the channel |
|
End of the Short Inter-Frame Time period |
|
Timeout after the transmission of an RTS, a CTS, or a DATA frame |
|
Messages longer than this threshold will be sent in multiple fragments. see spec 361 |
|
|
|
Indicates that the last frame received had bit errors in it or there was a collision during receiving the frame. If this flag is set, then the MAC will wait EIFS instead of DIFS period of time in WAITDIFS state. |
|
Maximum number of frames in the queue; should be set in the omnetpp.ini |
|
Radio state change self message. Currently this is optimized away and sent directly |
|
|
|
True during network allocation period. This flag is present to be able to watch this state. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The last change channel message received and not yet sent to the physical layer, or NULL. The message will be sent down when the state goes to IDLE or DEFER next time. |
|
Passive queue module to request messages from |
|
Physical radio (medium) state copied from physical layer |
|
|
|
Number of frame retransmission attempts, this is a simpification of SLRC and SSRC, see 9.2.4 in the spec |
|
Maximum number of retries. |
|
The minimum length of MPDU to use RTS/CTS mechanism. 0 means always, extremely large value means never. See spec 9.2.6 and 361. |
|
Sequence number to be assigned to the next frame |
|
|
|
Messages received from upper layer and to be transmitted later |