|
INET Framework for OMNeT++/OMNEST
|
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 }