INET Framework for OMNeT++/OMNEST
Ieee80211Mac.cc
Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2006 Andras Varga and Levente M�sz�ros
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU Lesser General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU Lesser General Public License
00015 // along with this program; if not, see <http://www.gnu.org/licenses/>.
00016 //
00017 
00018 #include <algorithm>
00019 #include "Ieee80211Mac.h"
00020 #include "RadioState.h"
00021 #include "IInterfaceTable.h"
00022 #include "InterfaceTableAccess.h"
00023 #include "PhyControlInfo_m.h"
00024 
00025 Define_Module(Ieee80211Mac);
00026 
00027 // don't forget to keep synchronized the C++ enum and the runtime enum definition
00028 Register_Enum(Ieee80211Mac,
00029    (Ieee80211Mac::IDLE,
00030     Ieee80211Mac::DEFER,
00031     Ieee80211Mac::WAITDIFS,
00032     Ieee80211Mac::BACKOFF,
00033     Ieee80211Mac::WAITACK,
00034     Ieee80211Mac::WAITBROADCAST,
00035     Ieee80211Mac::WAITCTS,
00036     Ieee80211Mac::WAITSIFS,
00037     Ieee80211Mac::RECEIVE));
00038 
00039 // don't forget to keep synchronized the C++ enum and the runtime enum definition
00040 Register_Enum(RadioState,
00041    (RadioState::IDLE,
00042     RadioState::RECV,
00043     RadioState::TRANSMIT,
00044     RadioState::SLEEP));
00045 
00046 /****************************************************************
00047  * Construction functions.
00048  */
00049 Ieee80211Mac::Ieee80211Mac()
00050 {
00051     endSIFS = NULL;
00052     endDIFS = NULL;
00053     endBackoff = NULL;
00054     endTimeout = NULL;
00055     endReserve = NULL;
00056     mediumStateChange = NULL;
00057     pendingRadioConfigMsg = NULL;
00058 }
00059 
00060 Ieee80211Mac::~Ieee80211Mac()
00061 {
00062     cancelAndDelete(endSIFS);
00063     cancelAndDelete(endDIFS);
00064     cancelAndDelete(endBackoff);
00065     cancelAndDelete(endTimeout);
00066     cancelAndDelete(endReserve);
00067     cancelAndDelete(mediumStateChange);
00068 
00069     if (pendingRadioConfigMsg)
00070         delete pendingRadioConfigMsg;
00071 }
00072 
00073 /****************************************************************
00074  * Initialization functions.
00075  */
00076 void Ieee80211Mac::initialize(int stage)
00077 {
00078     WirelessMacBase::initialize(stage);
00079 
00080     if (stage == 0)
00081     {
00082         EV << "Initializing stage 0\n";
00083 
00084         // initialize parameters
00085         maxQueueSize = par("maxQueueSize");
00086         bitrate = par("bitrate");
00087         basicBitrate = 2e6; //FIXME make it parameter
00088         rtsThreshold = par("rtsThresholdBytes");
00089 
00090         // the variable is renamed due to a confusion in the standard
00091         // the name retry limit would be misleading, see the header file comment
00092         transmissionLimit = par("retryLimit");
00093         if (transmissionLimit == -1) transmissionLimit = 7;
00094         ASSERT(transmissionLimit > 0);
00095 
00096         cwMinData = par("cwMinData");
00097         if (cwMinData == -1) cwMinData = CW_MIN;
00098         ASSERT(cwMinData >= 0);
00099 
00100         cwMinBroadcast = par("cwMinBroadcast");
00101         if (cwMinBroadcast == -1) cwMinBroadcast = 31;
00102         ASSERT(cwMinBroadcast >= 0);
00103 
00104         const char *addressString = par("address");
00105         if (!strcmp(addressString, "auto")) {
00106             // assign automatic address
00107             address = MACAddress::generateAutoAddress();
00108             // change module parameter from "auto" to concrete address
00109             par("address").setStringValue(address.str().c_str());
00110         }
00111         else
00112             address.setAddress(addressString);
00113 
00114         // subscribe for the information of the carrier sense
00115         nb->subscribe(this, NF_RADIOSTATE_CHANGED);
00116 
00117         // initalize self messages
00118         endSIFS = new cMessage("SIFS");
00119         endDIFS = new cMessage("DIFS");
00120         endBackoff = new cMessage("Backoff");
00121         endTimeout = new cMessage("Timeout");
00122         endReserve = new cMessage("Reserve");
00123         mediumStateChange = new cMessage("MediumStateChange");
00124 
00125         // interface
00126         registerInterface();
00127 
00128         // obtain pointer to external queue
00129         initializeQueueModule();
00130 
00131         // state variables
00132         fsm.setName("Ieee80211Mac State Machine");
00133         mode = DCF;
00134         sequenceNumber = 0;
00135         radioState = RadioState::IDLE;
00136         retryCounter = 0;
00137         backoffPeriod = -1;
00138         backoff = false;
00139         lastReceiveFailed = false;
00140         nav = false;
00141 
00142         // statistics
00143         numRetry = 0;
00144         numSentWithoutRetry = 0;
00145         numGivenUp = 0;
00146         numCollision = 0;
00147         numSent = 0;
00148         numReceived = 0;
00149         numSentBroadcast = 0;
00150         numReceivedBroadcast = 0;
00151         stateVector.setName("State");
00152         stateVector.setEnum("Ieee80211Mac");
00153         radioStateVector.setName("RadioState");
00154         radioStateVector.setEnum("RadioState");
00155 
00156         // initialize watches
00157         WATCH(fsm);
00158         WATCH(radioState);
00159         WATCH(retryCounter);
00160         WATCH(backoff);
00161         WATCH(nav);
00162 
00163         WATCH(numRetry);
00164         WATCH(numSentWithoutRetry);
00165         WATCH(numGivenUp);
00166         WATCH(numCollision);
00167         WATCH(numSent);
00168         WATCH(numReceived);
00169         WATCH(numSentBroadcast);
00170         WATCH(numReceivedBroadcast);
00171     }
00172 }
00173 
00174 void Ieee80211Mac::registerInterface()
00175 {
00176     IInterfaceTable *ift = InterfaceTableAccess().getIfExists();
00177     if (!ift)
00178         return;
00179 
00180     InterfaceEntry *e = new InterfaceEntry();
00181 
00182     // interface name: NetworkInterface module's name without special characters ([])
00183     char *interfaceName = new char[strlen(getParentModule()->getFullName()) + 1];
00184     char *d = interfaceName;
00185     for (const char *s = getParentModule()->getFullName(); *s; s++)
00186         if (isalnum(*s))
00187             *d++ = *s;
00188     *d = '\0';
00189 
00190     e->setName(interfaceName);
00191     delete [] interfaceName;
00192 
00193     // address
00194     e->setMACAddress(address);
00195     e->setInterfaceToken(address.formInterfaceIdentifier());
00196 
00197     // FIXME: MTU on 802.11 = ?
00198     e->setMtu(par("mtu"));
00199 
00200     // capabilities
00201     e->setBroadcast(true);
00202     e->setMulticast(true);
00203     e->setPointToPoint(false);
00204 
00205     // add
00206     ift->addInterface(e, this);
00207 }
00208 
00209 void Ieee80211Mac::initializeQueueModule()
00210 {
00211     // use of external queue module is optional -- find it if there's one specified
00212     if (par("queueModule").stringValue()[0])
00213     {
00214         cModule *module = getParentModule()->getSubmodule(par("queueModule").stringValue());
00215         queueModule = check_and_cast<IPassiveQueue *>(module);
00216 
00217         EV << "Requesting first two frames from queue module\n";
00218         queueModule->requestPacket();
00219         // needed for backoff: mandatory if next message is already present
00220         queueModule->requestPacket();
00221     }
00222 }
00223 
00224 /****************************************************************
00225  * Message handling functions.
00226  */
00227 void Ieee80211Mac::handleSelfMsg(cMessage *msg)
00228 {
00229     EV << "received self message: " << msg << endl;
00230 
00231     if (msg == endReserve)
00232         nav = false;
00233 
00234     handleWithFSM(msg);
00235 }
00236 
00237 void Ieee80211Mac::handleUpperMsg(cPacket *msg)
00238 {
00239     // check for queue overflow
00240     if (maxQueueSize && (int)transmissionQueue.size() == maxQueueSize)
00241     {
00242         EV << "message " << msg << " received from higher layer but MAC queue is full, dropping message\n";
00243         delete msg;
00244         return;
00245     }
00246 
00247     // must be a Ieee80211DataOrMgmtFrame, within the max size because we don't support fragmentation
00248     Ieee80211DataOrMgmtFrame *frame = check_and_cast<Ieee80211DataOrMgmtFrame *>(msg);
00249     if (frame->getByteLength() > fragmentationThreshold)
00250         error("message from higher layer (%s)%s is too long for 802.11b, %d bytes (fragmentation is not supported yet)",
00251               msg->getClassName(), msg->getName(), (int)(msg->getByteLength()));
00252     EV << "frame " << frame << " received from higher layer, receiver = " << frame->getReceiverAddress() << endl;
00253 
00254     ASSERT(!frame->getReceiverAddress().isUnspecified());
00255 
00256     // fill in missing fields (receiver address, seq number), and insert into the queue
00257     frame->setTransmitterAddress(address);
00258     frame->setSequenceNumber(sequenceNumber);
00259     sequenceNumber = (sequenceNumber+1) % 4096;  //XXX seqNum must be checked upon reception of frames!
00260 
00261     transmissionQueue.push_back(frame);
00262 
00263     handleWithFSM(frame);
00264 }
00265 
00266 void Ieee80211Mac::handleCommand(cMessage *msg)
00267 {
00268     if (msg->getKind()==PHY_C_CONFIGURERADIO)
00269     {
00270         EV << "Passing on command " << msg->getName() << " to physical layer\n";
00271         if (pendingRadioConfigMsg != NULL)
00272         {
00273             // merge contents of the old command into the new one, then delete it
00274             PhyControlInfo *pOld = check_and_cast<PhyControlInfo *>(pendingRadioConfigMsg->getControlInfo());
00275             PhyControlInfo *pNew = check_and_cast<PhyControlInfo *>(msg->getControlInfo());
00276             if (pNew->getChannelNumber()==-1 && pOld->getChannelNumber()!=-1)
00277                 pNew->setChannelNumber(pOld->getChannelNumber());
00278             if (pNew->getBitrate()==-1 && pOld->getBitrate()!=-1)
00279                 pNew->setBitrate(pOld->getBitrate());
00280             delete pendingRadioConfigMsg;
00281             pendingRadioConfigMsg = NULL;
00282         }
00283 
00284         if (fsm.getState() == IDLE || fsm.getState() == DEFER || fsm.getState() == BACKOFF)
00285         {
00286             EV << "Sending it down immediately\n";
00287             sendDown(msg);
00288         }
00289         else
00290         {
00291             EV << "Delaying " << msg->getName() << " until next IDLE or DEFER state\n";
00292             pendingRadioConfigMsg = msg;
00293         }
00294     }
00295     else
00296     {
00297         error("Unrecognized command from mgmt layer: (%s)%s msgkind=%d", msg->getClassName(), msg->getName(), msg->getKind());
00298     }
00299 }
00300 
00301 void Ieee80211Mac::handleLowerMsg(cPacket *msg)
00302 {
00303     EV << "received message from lower layer: " << msg << endl;
00304 
00305     Ieee80211Frame *frame = dynamic_cast<Ieee80211Frame *>(msg);
00306     if (!frame)
00307         error("message from physical layer (%s)%s is not a subclass of Ieee80211Frame",
00308               msg->getClassName(), msg->getName());
00309 
00310     EV << "Self address: " << address
00311        << ", receiver address: " << frame->getReceiverAddress()
00312        << ", received frame is for us: " << isForUs(frame) << endl;
00313 
00314     Ieee80211TwoAddressFrame *twoAddressFrame = dynamic_cast<Ieee80211TwoAddressFrame *>(msg);
00315     ASSERT(!twoAddressFrame || twoAddressFrame->getTransmitterAddress() != address);
00316 
00317     handleWithFSM(msg);
00318 
00319     // if we are the owner then we did not send this message up
00320     if (msg->getOwner() == this)
00321         delete msg;
00322 }
00323 
00324 void Ieee80211Mac::receiveChangeNotification(int category, const cPolymorphic *details)
00325 {
00326     Enter_Method_Silent();
00327     printNotificationBanner(category, details);
00328 
00329     if (category == NF_RADIOSTATE_CHANGED)
00330     {
00331         RadioState::State newRadioState = check_and_cast<RadioState *>(details)->getState();
00332 
00333         // FIXME: double recording, because there's no sample hold in the gui
00334         radioStateVector.record(radioState);
00335         radioStateVector.record(newRadioState);
00336 
00337         radioState = newRadioState;
00338 
00339         handleWithFSM(mediumStateChange);
00340     }
00341 }
00342 
00346 void Ieee80211Mac::handleWithFSM(cMessage *msg)
00347 {
00348     // skip those cases where there's nothing to do, so the switch looks simpler
00349     if (isUpperMsg(msg) && fsm.getState() != IDLE)
00350     {
00351         EV << "deferring upper message transmission in " << fsm.getStateName() << " state\n";
00352         return;
00353     }
00354 
00355     Ieee80211Frame *frame = dynamic_cast<Ieee80211Frame*>(msg);
00356     int frameType = frame ? frame->getType() : -1;
00357     int msgKind = msg->getKind();
00358     logState();
00359     stateVector.record(fsm.getState());
00360 
00361     if (frame && isLowerMsg(frame))
00362     {
00363         lastReceiveFailed =(msgKind == COLLISION || msgKind == BITERROR);
00364         scheduleReservePeriod(frame);
00365     }
00366 
00367     // TODO: fix bug according to the message: [omnetpp] A possible bug in the Ieee80211's FSM.
00368     FSMA_Switch(fsm)
00369     {
00370         FSMA_State(IDLE)
00371         {
00372             FSMA_Enter(sendDownPendingRadioConfigMsg());
00373             FSMA_Event_Transition(Data-Ready,
00374                                   isUpperMsg(msg),
00375                                   DEFER,
00376                 ASSERT(isInvalidBackoffPeriod() || backoffPeriod == 0);
00377                 invalidateBackoffPeriod();
00378             );
00379             FSMA_No_Event_Transition(Immediate-Data-Ready,
00380                                      !transmissionQueue.empty(),
00381                                      DEFER,
00382                 invalidateBackoffPeriod();
00383             );
00384             FSMA_Event_Transition(Receive,
00385                                   isLowerMsg(msg),
00386                                   RECEIVE,
00387             );
00388         }
00389         FSMA_State(DEFER)
00390         {
00391             FSMA_Enter(sendDownPendingRadioConfigMsg());
00392             FSMA_Event_Transition(Wait-DIFS,
00393                                   isMediumStateChange(msg) && isMediumFree(),
00394                                   WAITDIFS,
00395             ;);
00396             FSMA_No_Event_Transition(Immediate-Wait-DIFS,
00397                                      isMediumFree() || !backoff,
00398                                      WAITDIFS,
00399             ;);
00400             FSMA_Event_Transition(Receive,
00401                                   isLowerMsg(msg),
00402                                   RECEIVE,
00403             ;);
00404         }
00405         FSMA_State(WAITDIFS)
00406         {
00407             FSMA_Enter(scheduleDIFSPeriod());
00408             FSMA_Event_Transition(Immediate-Transmit-RTS,
00409                                   msg == endDIFS && !isBroadcast(getCurrentTransmission())
00410                                   && getCurrentTransmission()->getByteLength() >= rtsThreshold && !backoff,
00411                                   WAITCTS,
00412                 sendRTSFrame(getCurrentTransmission());
00413                 cancelDIFSPeriod();
00414             );
00415             FSMA_Event_Transition(Immediate-Transmit-Broadcast,
00416                                   msg == endDIFS && isBroadcast(getCurrentTransmission()) && !backoff,
00417                                   WAITBROADCAST,
00418                 sendBroadcastFrame(getCurrentTransmission());
00419                 cancelDIFSPeriod();
00420             );
00421             FSMA_Event_Transition(Immediate-Transmit-Data,
00422                                   msg == endDIFS && !isBroadcast(getCurrentTransmission()) && !backoff,
00423                                   WAITACK,
00424                 sendDataFrame(getCurrentTransmission());
00425                 cancelDIFSPeriod();
00426             );
00427             FSMA_Event_Transition(DIFS-Over,
00428                                   msg == endDIFS,
00429                                   BACKOFF,
00430                 ASSERT(backoff);
00431                 if (isInvalidBackoffPeriod())
00432                     generateBackoffPeriod();
00433             );
00434             FSMA_Event_Transition(Busy,
00435                                   isMediumStateChange(msg) && !isMediumFree(),
00436                                   DEFER,
00437                 backoff = true;
00438                 cancelDIFSPeriod();
00439             );
00440             FSMA_No_Event_Transition(Immediate-Busy,
00441                                      !isMediumFree(),
00442                                      DEFER,
00443                 backoff = true;
00444                 cancelDIFSPeriod();
00445             );
00446             // radio state changes before we actually get the message, so this must be here
00447             FSMA_Event_Transition(Receive,
00448                                   isLowerMsg(msg),
00449                                   RECEIVE,
00450                 cancelDIFSPeriod();
00451             ;);
00452         }
00453         FSMA_State(BACKOFF)
00454         {
00455             FSMA_Enter(scheduleBackoffPeriod());
00456             FSMA_Event_Transition(Transmit-RTS,
00457                                   msg == endBackoff && !isBroadcast(getCurrentTransmission())
00458                                   && getCurrentTransmission()->getByteLength() >= rtsThreshold,
00459                                   WAITCTS,
00460                 sendRTSFrame(getCurrentTransmission());
00461             );
00462             FSMA_Event_Transition(Transmit-Broadcast,
00463                                   msg == endBackoff && isBroadcast(getCurrentTransmission()),
00464                                   WAITBROADCAST,
00465                 sendBroadcastFrame(getCurrentTransmission());
00466             );
00467             FSMA_Event_Transition(Transmit-Data,
00468                                   msg == endBackoff && !isBroadcast(getCurrentTransmission()),
00469                                   WAITACK,
00470                 sendDataFrame(getCurrentTransmission());
00471             );
00472             FSMA_Event_Transition(Backoff-Busy,
00473                                   isMediumStateChange(msg) && !isMediumFree(),
00474                                   DEFER,
00475                 cancelBackoffPeriod();
00476                 decreaseBackoffPeriod();
00477             );
00478         }
00479         FSMA_State(WAITACK)
00480         {
00481             FSMA_Enter(scheduleDataTimeoutPeriod(getCurrentTransmission()));
00482             FSMA_Event_Transition(Receive-ACK,
00483                                   isLowerMsg(msg) && isForUs(frame) && frameType == ST_ACK,
00484                                   IDLE,
00485                 if (retryCounter == 0) numSentWithoutRetry++;
00486                 numSent++;
00487                 cancelTimeoutPeriod();
00488                 finishCurrentTransmission();
00489             );
00490             FSMA_Event_Transition(Transmit-Data-Failed,
00491                                   msg == endTimeout && retryCounter == transmissionLimit - 1,
00492                                   IDLE,
00493                 giveUpCurrentTransmission();
00494             );
00495             FSMA_Event_Transition(Receive-ACK-Timeout,
00496                                   msg == endTimeout,
00497                                   DEFER,
00498                 retryCurrentTransmission();
00499             );
00500         }
00501         // wait until broadcast is sent
00502         FSMA_State(WAITBROADCAST)
00503         {
00504             FSMA_Enter(scheduleBroadcastTimeoutPeriod(getCurrentTransmission()));
00505             FSMA_Event_Transition(Transmit-Broadcast,
00506                                   msg == endTimeout,
00507                                   IDLE,
00508                 finishCurrentTransmission();
00509                 numSentBroadcast++;
00510             );
00511         }
00512         // accoriding to 9.2.5.7 CTS procedure
00513         FSMA_State(WAITCTS)
00514         {
00515             FSMA_Enter(scheduleCTSTimeoutPeriod());
00516             FSMA_Event_Transition(Receive-CTS,
00517                                   isLowerMsg(msg) && isForUs(frame) && frameType == ST_CTS,
00518                                   WAITSIFS,
00519                 cancelTimeoutPeriod();
00520             );
00521             FSMA_Event_Transition(Transmit-RTS-Failed,
00522                                   msg == endTimeout && retryCounter == transmissionLimit - 1,
00523                                   IDLE,
00524                 giveUpCurrentTransmission();
00525             );
00526             FSMA_Event_Transition(Receive-CTS-Timeout,
00527                                   msg == endTimeout,
00528                                   DEFER,
00529                 retryCurrentTransmission();
00530             );
00531         }
00532         FSMA_State(WAITSIFS)
00533         {
00534             FSMA_Enter(scheduleSIFSPeriod(frame));
00535             FSMA_Event_Transition(Transmit-CTS,
00536                                   msg == endSIFS && getFrameReceivedBeforeSIFS()->getType() == ST_RTS,
00537                                   IDLE,
00538                 sendCTSFrameOnEndSIFS();
00539                 resetStateVariables();
00540             );
00541             FSMA_Event_Transition(Transmit-DATA,
00542                                   msg == endSIFS && getFrameReceivedBeforeSIFS()->getType() == ST_CTS,
00543                                   WAITACK,
00544                 sendDataFrameOnEndSIFS(getCurrentTransmission());
00545             );
00546             FSMA_Event_Transition(Transmit-ACK,
00547                                   msg == endSIFS && isDataOrMgmtFrame(getFrameReceivedBeforeSIFS()),
00548                                   IDLE,
00549                 sendACKFrameOnEndSIFS();
00550                 resetStateVariables();
00551             );
00552         }
00553         // this is not a real state
00554         FSMA_State(RECEIVE)
00555         {
00556             FSMA_No_Event_Transition(Immediate-Receive-Error,
00557                                      isLowerMsg(msg) && (msgKind == COLLISION || msgKind == BITERROR),
00558                                      IDLE,
00559                 EV << "received frame contains bit errors or collision, next wait period is EIFS\n";
00560                 numCollision++;
00561                 resetStateVariables();
00562             );
00563             FSMA_No_Event_Transition(Immediate-Receive-Broadcast,
00564                                      isLowerMsg(msg) && isBroadcast(frame) && isDataOrMgmtFrame(frame),
00565                                      IDLE,
00566                 sendUp(frame);
00567                 numReceivedBroadcast++;
00568                 resetStateVariables();
00569             );
00570             FSMA_No_Event_Transition(Immediate-Receive-Data,
00571                                      isLowerMsg(msg) && isForUs(frame) && isDataOrMgmtFrame(frame),
00572                                      WAITSIFS,
00573                 sendUp(frame);
00574                 numReceived++;
00575             );
00576             FSMA_No_Event_Transition(Immediate-Receive-RTS,
00577                                      isLowerMsg(msg) && isForUs(frame) && frameType == ST_RTS,
00578                                      WAITSIFS,
00579             );
00580             FSMA_No_Event_Transition(Immediate-Receive-Other,
00581                                      isLowerMsg(msg),
00582                                      IDLE,
00583                 resetStateVariables();
00584             );
00585         }
00586     }
00587 
00588     logState();
00589     stateVector.record(fsm.getState());
00590 }
00591 
00592 /****************************************************************
00593  * Timing functions.
00594  */
00595 simtime_t Ieee80211Mac::getSIFS()
00596 {
00597 // TODO:   return aRxRFDelay() + aRxPLCPDelay() + aMACProcessingDelay() + aRxTxTurnaroundTime();
00598     return SIFS;
00599 }
00600 
00601 simtime_t Ieee80211Mac::getSlotTime()
00602 {
00603 // TODO:   return aCCATime() + aRxTxTurnaroundTime + aAirPropagationTime() + aMACProcessingDelay();
00604     return ST;
00605 }
00606 
00607 simtime_t Ieee80211Mac::getPIFS()
00608 {
00609     return getSIFS() + getSlotTime();
00610 }
00611 
00612 simtime_t Ieee80211Mac::getDIFS()
00613 {
00614     return getSIFS() + 2 * getSlotTime();
00615 }
00616 
00617 simtime_t Ieee80211Mac::getEIFS()
00618 {
00619 // FIXME:   return getSIFS() + getDIFS() + (8 * ACKSize + aPreambleLength + aPLCPHeaderLength) / lowestDatarate;
00620     return getSIFS() + getDIFS() + (8 * LENGTH_ACK + PHY_HEADER_LENGTH) / 1E+6;
00621 }
00622 
00623 simtime_t Ieee80211Mac::computeBackoffPeriod(Ieee80211Frame *msg, int r)
00624 {
00625     int cw;
00626 
00627     EV << "generating backoff slot number for retry: " << r << endl;
00628 
00629     if (isBroadcast(msg))
00630         cw = cwMinBroadcast;
00631     else
00632     {
00633         ASSERT(0 <= r && r < transmissionLimit);
00634 
00635         cw = (cwMinData + 1) * (1 << r) - 1;
00636 
00637         if (cw > CW_MAX)
00638             cw = CW_MAX;
00639     }
00640 
00641     int c = intrand(cw + 1);
00642 
00643     EV << "generated backoff slot number: " << c << " , cw: " << cw << endl;
00644 
00645     return ((double)c) * getSlotTime();
00646 }
00647 
00648 /****************************************************************
00649  * Timer functions.
00650  */
00651 void Ieee80211Mac::scheduleSIFSPeriod(Ieee80211Frame *frame)
00652 {
00653     EV << "scheduling SIFS period\n";
00654     endSIFS->setContextPointer(frame->dup());
00655     scheduleAt(simTime() + getSIFS(), endSIFS);
00656 }
00657 
00658 void Ieee80211Mac::scheduleDIFSPeriod()
00659 {
00660     if (lastReceiveFailed)
00661     {
00662         EV << "receiption of last frame failed, scheduling EIFS period\n";
00663         scheduleAt(simTime() + getEIFS(), endDIFS);
00664     }
00665     else
00666     {
00667         EV << "scheduling DIFS period\n";
00668         scheduleAt(simTime() + getDIFS(), endDIFS);
00669     }
00670 }
00671 
00672 void Ieee80211Mac::cancelDIFSPeriod()
00673 {
00674     EV << "cancelling DIFS period\n";
00675     cancelEvent(endDIFS);
00676 }
00677 
00678 void Ieee80211Mac::scheduleDataTimeoutPeriod(Ieee80211DataOrMgmtFrame *frameToSend)
00679 {
00680     EV << "scheduling data timeout period\n";
00681     scheduleAt(simTime() + computeFrameDuration(frameToSend) + getSIFS() + computeFrameDuration(LENGTH_ACK, basicBitrate) + MAX_PROPAGATION_DELAY * 2, endTimeout);
00682 }
00683 
00684 void Ieee80211Mac::scheduleBroadcastTimeoutPeriod(Ieee80211DataOrMgmtFrame *frameToSend)
00685 {
00686     EV << "scheduling broadcast timeout period\n";
00687     scheduleAt(simTime() + computeFrameDuration(frameToSend), endTimeout);
00688 }
00689 
00690 void Ieee80211Mac::cancelTimeoutPeriod()
00691 {
00692     EV << "cancelling timeout period\n";
00693     cancelEvent(endTimeout);
00694 }
00695 
00696 void Ieee80211Mac::scheduleCTSTimeoutPeriod()
00697 {
00698     scheduleAt(simTime() + computeFrameDuration(LENGTH_RTS, basicBitrate) + getSIFS() + computeFrameDuration(LENGTH_CTS, basicBitrate) + MAX_PROPAGATION_DELAY * 2, endTimeout);
00699 }
00700 
00701 void Ieee80211Mac::scheduleReservePeriod(Ieee80211Frame *frame)
00702 {
00703     simtime_t reserve = frame->getDuration();
00704 
00705     // see spec. 7.1.3.2
00706     if (!isForUs(frame) && reserve != 0 && reserve < 32768)
00707     {
00708         if (endReserve->isScheduled()) {
00709             simtime_t oldReserve = endReserve->getArrivalTime() - simTime();
00710 
00711             if (oldReserve > reserve)
00712                 return;
00713 
00714             reserve = std::max(reserve, oldReserve);
00715             cancelEvent(endReserve);
00716         }
00717         else if (radioState == RadioState::IDLE)
00718         {
00719             // NAV: the channel just became virtually busy according to the spec
00720             scheduleAt(simTime(), mediumStateChange);
00721         }
00722 
00723         EV << "scheduling reserve period for: " << reserve << endl;
00724 
00725         ASSERT(reserve > 0);
00726 
00727         nav = true;
00728         scheduleAt(simTime() + reserve, endReserve);
00729     }
00730 }
00731 
00732 void Ieee80211Mac::invalidateBackoffPeriod()
00733 {
00734     backoffPeriod = -1;
00735 }
00736 
00737 bool Ieee80211Mac::isInvalidBackoffPeriod()
00738 {
00739     return backoffPeriod == -1;
00740 }
00741 
00742 void Ieee80211Mac::generateBackoffPeriod()
00743 {
00744     backoffPeriod = computeBackoffPeriod(getCurrentTransmission(), retryCounter);
00745     ASSERT(backoffPeriod >= 0);
00746     EV << "backoff period set to " << backoffPeriod << endl;
00747 }
00748 
00749 void Ieee80211Mac::decreaseBackoffPeriod()
00750 {
00751     // see spec 9.2.5.2
00752     simtime_t elapsedBackoffTime = simTime() - endBackoff->getSendingTime();
00753     backoffPeriod -= ((int)(elapsedBackoffTime / getSlotTime())) * getSlotTime();
00754     ASSERT(backoffPeriod >= 0);
00755     EV << "backoff period decreased to " << backoffPeriod << endl;
00756 }
00757 
00758 void Ieee80211Mac::scheduleBackoffPeriod()
00759 {
00760     EV << "scheduling backoff period\n";
00761     scheduleAt(simTime() + backoffPeriod, endBackoff);
00762 }
00763 
00764 void Ieee80211Mac::cancelBackoffPeriod()
00765 {
00766     EV << "cancelling Backoff period\n";
00767     cancelEvent(endBackoff);
00768 }
00769 
00770 /****************************************************************
00771  * Frame sender functions.
00772  */
00773 void Ieee80211Mac::sendACKFrameOnEndSIFS()
00774 {
00775     Ieee80211Frame *frameToACK = (Ieee80211Frame *)endSIFS->getContextPointer();
00776     endSIFS->setContextPointer(NULL);
00777     sendACKFrame(check_and_cast<Ieee80211DataOrMgmtFrame*>(frameToACK));
00778     delete frameToACK;
00779 }
00780 
00781 void Ieee80211Mac::sendACKFrame(Ieee80211DataOrMgmtFrame *frameToACK)
00782 {
00783     EV << "sending ACK frame\n";
00784     sendDown(setBasicBitrate(buildACKFrame(frameToACK)));
00785 }
00786 
00787 void Ieee80211Mac::sendDataFrameOnEndSIFS(Ieee80211DataOrMgmtFrame *frameToSend)
00788 {
00789     Ieee80211Frame *ctsFrame = (Ieee80211Frame *)endSIFS->getContextPointer();
00790     endSIFS->setContextPointer(NULL);
00791     sendDataFrame(frameToSend);
00792     delete ctsFrame;
00793 }
00794 
00795 void Ieee80211Mac::sendDataFrame(Ieee80211DataOrMgmtFrame *frameToSend)
00796 {
00797     EV << "sending Data frame\n";
00798     sendDown(buildDataFrame(frameToSend));
00799 }
00800 
00801 void Ieee80211Mac::sendBroadcastFrame(Ieee80211DataOrMgmtFrame *frameToSend)
00802 {
00803     EV << "sending Broadcast frame\n";
00804     sendDown(buildBroadcastFrame(frameToSend));
00805 }
00806 
00807 void Ieee80211Mac::sendRTSFrame(Ieee80211DataOrMgmtFrame *frameToSend)
00808 {
00809     EV << "sending RTS frame\n";
00810     sendDown(setBasicBitrate(buildRTSFrame(frameToSend)));
00811 }
00812 
00813 void Ieee80211Mac::sendCTSFrameOnEndSIFS()
00814 {
00815     Ieee80211Frame *rtsFrame = (Ieee80211Frame *)endSIFS->getContextPointer();
00816     endSIFS->setContextPointer(NULL);
00817     sendCTSFrame(check_and_cast<Ieee80211RTSFrame*>(rtsFrame));
00818     delete rtsFrame;
00819 }
00820 
00821 void Ieee80211Mac::sendCTSFrame(Ieee80211RTSFrame *rtsFrame)
00822 {
00823     EV << "sending CTS frame\n";
00824     sendDown(setBasicBitrate(buildCTSFrame(rtsFrame)));
00825 }
00826 
00827 /****************************************************************
00828  * Frame builder functions.
00829  */
00830 Ieee80211DataOrMgmtFrame *Ieee80211Mac::buildDataFrame(Ieee80211DataOrMgmtFrame *frameToSend)
00831 {
00832     Ieee80211DataOrMgmtFrame *frame = (Ieee80211DataOrMgmtFrame *)frameToSend->dup();
00833 
00834     if (isBroadcast(frameToSend))
00835         frame->setDuration(0);
00836     else if (!frameToSend->getMoreFragments())
00837         frame->setDuration(getSIFS() + computeFrameDuration(LENGTH_ACK, basicBitrate));
00838     else
00839         // FIXME: shouldn't we use the next frame to be sent?
00840         frame->setDuration(3 * getSIFS() + 2 * computeFrameDuration(LENGTH_ACK, basicBitrate) + computeFrameDuration(frameToSend));
00841 
00842     return frame;
00843 }
00844 
00845 Ieee80211ACKFrame *Ieee80211Mac::buildACKFrame(Ieee80211DataOrMgmtFrame *frameToACK)
00846 {
00847     Ieee80211ACKFrame *frame = new Ieee80211ACKFrame("wlan-ack");
00848     frame->setReceiverAddress(frameToACK->getTransmitterAddress());
00849 
00850     if (!frameToACK->getMoreFragments())
00851         frame->setDuration(0);
00852     else
00853         frame->setDuration(frameToACK->getDuration() - getSIFS() - computeFrameDuration(LENGTH_ACK, basicBitrate));
00854 
00855     return frame;
00856 }
00857 
00858 Ieee80211RTSFrame *Ieee80211Mac::buildRTSFrame(Ieee80211DataOrMgmtFrame *frameToSend)
00859 {
00860     Ieee80211RTSFrame *frame = new Ieee80211RTSFrame("wlan-rts");
00861     frame->setTransmitterAddress(address);
00862     frame->setReceiverAddress(frameToSend->getReceiverAddress());
00863     frame->setDuration(3 * getSIFS() + computeFrameDuration(LENGTH_CTS, basicBitrate) +
00864                        computeFrameDuration(frameToSend) +
00865                        computeFrameDuration(LENGTH_ACK, basicBitrate));
00866 
00867     return frame;
00868 }
00869 
00870 Ieee80211CTSFrame *Ieee80211Mac::buildCTSFrame(Ieee80211RTSFrame *rtsFrame)
00871 {
00872     Ieee80211CTSFrame *frame = new Ieee80211CTSFrame("wlan-cts");
00873     frame->setReceiverAddress(rtsFrame->getTransmitterAddress());
00874     frame->setDuration(rtsFrame->getDuration() - getSIFS() - computeFrameDuration(LENGTH_CTS, basicBitrate));
00875 
00876     return frame;
00877 }
00878 
00879 Ieee80211DataOrMgmtFrame *Ieee80211Mac::buildBroadcastFrame(Ieee80211DataOrMgmtFrame *frameToSend)
00880 {
00881     Ieee80211DataOrMgmtFrame *frame = (Ieee80211DataOrMgmtFrame *)frameToSend->dup();
00882     frame->setDuration(0);
00883     return frame;
00884 }
00885 
00886 Ieee80211Frame *Ieee80211Mac::setBasicBitrate(Ieee80211Frame *frame)
00887 {
00888     ASSERT(frame->getControlInfo()==NULL);
00889     PhyControlInfo *ctrl = new PhyControlInfo();
00890     ctrl->setBitrate(basicBitrate);
00891     frame->setControlInfo(ctrl);
00892     return frame;
00893 }
00894 
00895 /****************************************************************
00896  * Helper functions.
00897  */
00898 void Ieee80211Mac::finishCurrentTransmission()
00899 {
00900     popTransmissionQueue();
00901     resetStateVariables();
00902 }
00903 
00904 void Ieee80211Mac::giveUpCurrentTransmission()
00905 {
00906     popTransmissionQueue();
00907     resetStateVariables();
00908     numGivenUp++;
00909 }
00910 
00911 void Ieee80211Mac::retryCurrentTransmission()
00912 {
00913     ASSERT(retryCounter < transmissionLimit - 1);
00914     getCurrentTransmission()->setRetry(true);
00915     retryCounter++;
00916     numRetry++;
00917     backoff = true;
00918     generateBackoffPeriod();
00919 }
00920 
00921 Ieee80211DataOrMgmtFrame *Ieee80211Mac::getCurrentTransmission()
00922 {
00923     return (Ieee80211DataOrMgmtFrame *)transmissionQueue.front();
00924 }
00925 
00926 void Ieee80211Mac::sendDownPendingRadioConfigMsg()
00927 {
00928     if (pendingRadioConfigMsg != NULL)
00929     {
00930         sendDown(pendingRadioConfigMsg);
00931         pendingRadioConfigMsg = NULL;
00932     }
00933 }
00934 
00935 void Ieee80211Mac::setMode(Mode mode)
00936 {
00937     if (mode == PCF)
00938         error("PCF mode not yet supported");
00939 
00940     this->mode = mode;
00941 }
00942 
00943 void Ieee80211Mac::resetStateVariables()
00944 {
00945     backoffPeriod = 0;
00946     retryCounter = 0;
00947 
00948     if (!transmissionQueue.empty()) {
00949         backoff = true;
00950         getCurrentTransmission()->setRetry(false);
00951     }
00952     else {
00953         backoff = false;
00954     }
00955 }
00956 
00957 bool Ieee80211Mac::isMediumStateChange(cMessage *msg)
00958 {
00959     return msg == mediumStateChange || (msg == endReserve && radioState == RadioState::IDLE);
00960 }
00961 
00962 bool Ieee80211Mac::isMediumFree()
00963 {
00964     return radioState == RadioState::IDLE && !endReserve->isScheduled();
00965 }
00966 
00967 bool Ieee80211Mac::isBroadcast(Ieee80211Frame *frame)
00968 {
00969     return frame && frame->getReceiverAddress().isBroadcast();
00970 }
00971 
00972 bool Ieee80211Mac::isForUs(Ieee80211Frame *frame)
00973 {
00974     return frame && frame->getReceiverAddress() == address;
00975 }
00976 
00977 bool Ieee80211Mac::isDataOrMgmtFrame(Ieee80211Frame *frame)
00978 {
00979     return dynamic_cast<Ieee80211DataOrMgmtFrame*>(frame);
00980 }
00981 
00982 Ieee80211Frame *Ieee80211Mac::getFrameReceivedBeforeSIFS()
00983 {
00984     return (Ieee80211Frame *)endSIFS->getContextPointer();
00985 }
00986 
00987 void Ieee80211Mac::popTransmissionQueue()
00988 {
00989     EV << "dropping frame from transmission queue\n";
00990     Ieee80211Frame *temp = transmissionQueue.front();
00991     transmissionQueue.pop_front();
00992     delete temp;
00993 
00994     if (queueModule)
00995     {
00996         // tell queue module that we've become idle
00997         EV << "requesting another frame from queue module\n";
00998         queueModule->requestPacket();
00999     }
01000 }
01001 
01002 double Ieee80211Mac::computeFrameDuration(Ieee80211Frame *msg)
01003 {
01004     return computeFrameDuration(msg->getBitLength(), bitrate);
01005 }
01006 
01007 double Ieee80211Mac::computeFrameDuration(int bits, double bitrate)
01008 {
01009     return bits / bitrate + PHY_HEADER_LENGTH / BITRATE_HEADER;
01010 }
01011 
01012 void Ieee80211Mac::logState()
01013 {
01014     EV  << "state information: mode = " << modeName(mode) << ", state = " << fsm.getStateName()
01015         << ", backoff = " << backoff << ", backoffPeriod = " << backoffPeriod
01016         << ", retryCounter = " << retryCounter << ", radioState = " << radioState
01017         << ", nav = " << nav << endl;
01018 }
01019 
01020 const char *Ieee80211Mac::modeName(int mode)
01021 {
01022 #define CASE(x) case x: s=#x; break
01023     const char *s = "???";
01024     switch (mode)
01025     {
01026         CASE(DCF);
01027         CASE(PCF);
01028     }
01029     return s;
01030 #undef CASE
01031 }