#include <EtherMAC.h>
Inheritance diagram for EtherMAC:
EtherMAC::EtherMAC | ( | ) |
00043 { 00044 frameBeingReceived = NULL; 00045 endJammingMsg = endRxMsg = endBackoffMsg = NULL; 00046 }
EtherMAC::~EtherMAC | ( | ) | [virtual] |
00049 { 00050 delete frameBeingReceived; 00051 cancelAndDelete(endRxMsg); 00052 cancelAndDelete(endBackoffMsg); 00053 cancelAndDelete(endJammingMsg); 00054 }
void EtherMAC::finish | ( | ) | [protected, virtual] |
Reimplemented from EtherMACBase.
00631 { 00632 EtherMACBase::finish(); 00633 00634 if (!disabled && par("writeScalars").boolValue()) 00635 { 00636 double t = simTime(); 00637 simtime_t totalChannelIdleTime = t - totalSuccessfulRxTxTime - totalCollisionTime; 00638 recordScalar("rx channel idle (%)", 100*totalChannelIdleTime/t); 00639 recordScalar("rx channel utilization (%)", 100*totalSuccessfulRxTxTime/t); 00640 recordScalar("rx channel collision (%)", 100*totalCollisionTime); 00641 recordScalar("collisions", numCollisions); 00642 recordScalar("backoffs", numBackoffs); 00643 } 00644 }
void EtherMAC::handleAutoconfigMessage | ( | cMessage * | msg | ) | [private] |
00140 { 00141 if (!msg->isSelfMessage()) 00142 { 00143 if (msg->arrivalGate() == gate("upperLayerIn")) 00144 { 00145 // from upper layer 00146 EV << "Received frame from upper layer during autoconfig period: " << msg << endl; 00147 processFrameFromUpperLayer(check_and_cast<EtherFrame *>(msg)); 00148 } 00149 else 00150 { 00151 // from network: must be autoconfig message 00152 EV << "Message from network during autoconfig period: " << msg << endl; 00153 EtherAutoconfig *autoconf = check_and_cast<EtherAutoconfig *>(msg); 00154 double acTxrate = autoconf->getTxrate(); 00155 00156 EV << "Autoconfig message: "; 00157 if (acTxrate>0) 00158 EV << acTxrate/1000000 << "Mb "; 00159 if (autoconf->getHalfDuplex()) 00160 EV << "non-duplex"; 00161 EV << "\n"; 00162 00163 if (acTxrate>0 && (acTxrate<lowestTxrateSuggested || lowestTxrateSuggested==0)) 00164 lowestTxrateSuggested = acTxrate; 00165 if (!duplexVetoed && autoconf->getHalfDuplex()) 00166 duplexVetoed = true; 00167 delete msg; 00168 } 00169 } 00170 else 00171 { 00172 // self-message signals end of autoconfig period 00173 EV << "Self-message during autoconfig period: " << msg << endl; 00174 00175 delete msg; 00176 autoconfigInProgress = false; 00177 00178 double initialTxrate = par("txrate"); 00179 bool duplexEnabled = par("duplexEnabled"); 00180 00181 txrate = (initialTxrate==0 && lowestTxrateSuggested==0) ? 100000000 /* 100 Mb */: 00182 (initialTxrate==0) ? lowestTxrateSuggested : 00183 (lowestTxrateSuggested==0) ? initialTxrate : 00184 (lowestTxrateSuggested<initialTxrate) ? lowestTxrateSuggested : initialTxrate; 00185 duplexMode = (duplexEnabled && !duplexVetoed); 00186 calculateParameters(); 00187 00188 EV << "Parameters after autoconfig: txrate=" << txrate/1000000 << "Mb, " << (duplexMode ? "duplex" : "half-duplex") << endl; 00189 00190 if (ev.isGUI()) 00191 { 00192 char modestr[64]; 00193 sprintf(modestr, "%dMb\n%s", int(txrate/1000000), (duplexMode ? "full duplex" : "half duplex")); 00194 displayString().setTagArg("t",0,modestr); 00195 //displayString().setTagArg("t",1,"r"); 00196 sprintf(modestr, "%s: %dMb %s", fullName(), int(txrate/1000000), (duplexMode ? "duplex" : "half duplex")); 00197 parentModule()->bubble(modestr); 00198 } 00199 00200 if (!txQueue.empty()) 00201 { 00202 EV << "Autoconfig period over, starting to send frames\n"; 00203 scheduleEndIFGPeriod(); 00204 } 00205 } 00206 }
void EtherMAC::handleEndBackoffPeriod | ( | ) | [private] |
00538 { 00539 if (transmitState != BACKOFF_STATE) 00540 error("At end of BACKOFF not in BACKOFF_STATE!"); 00541 if (txQueue.empty()) 00542 error("At end of BACKOFF and buffer empty!"); 00543 00544 if (receiveState==RX_IDLE_STATE) 00545 { 00546 EV << "Backoff period ended, wait IFG\n"; 00547 scheduleEndIFGPeriod(); 00548 } 00549 else 00550 { 00551 EV << "Backoff period ended but channel not free, idling\n"; 00552 transmitState = TX_IDLE_STATE; 00553 } 00554 }
void EtherMAC::handleEndIFGPeriod | ( | ) | [private, virtual] |
Reimplemented from EtherMACBase.
00401 { 00402 EtherMACBase::handleEndIFGPeriod(); 00403 00404 // End of IFG period, okay to transmit, if Rx idle OR duplexMode 00405 cMessage *frame = (cMessage *)txQueue.tail(); 00406 00407 // Perform carrier extension if in Gigabit Ethernet 00408 if (carrierExtension && frame->byteLength() < GIGABIT_MIN_FRAME_WITH_EXT) 00409 { 00410 EV << "Performing carrier extension of small frame\n"; 00411 frame->setByteLength(GIGABIT_MIN_FRAME_WITH_EXT); 00412 } 00413 00414 // send frame to network 00415 startFrameTransmission(); 00416 }
void EtherMAC::handleEndJammingPeriod | ( | ) | [private] |
00557 { 00558 if (transmitState != JAMMING_STATE) 00559 error("At end of JAMMING not in JAMMING_STATE!"); 00560 EV << "Jamming finished, executing backoff\n"; 00561 handleRetransmission(); 00562 }
void EtherMAC::handleEndRxPeriod | ( | ) | [private] |
00512 { 00513 EV << "Frame reception complete\n"; 00514 simtime_t dt = simTime()-channelBusySince; 00515 if (receiveState==RECEIVING_STATE) // i.e. not RX_COLLISION_STATE 00516 { 00517 EtherFrame *frame = frameBeingReceived; 00518 frameBeingReceived = NULL; 00519 frameReceptionComplete(frame); 00520 totalSuccessfulRxTxTime += dt; 00521 } 00522 else 00523 { 00524 totalCollisionTime += dt; 00525 } 00526 00527 receiveState = RX_IDLE_STATE; 00528 numConcurrentTransmissions = 0; 00529 00530 if (transmitState==TX_IDLE_STATE && !txQueue.empty()) 00531 { 00532 EV << "Receiver now idle, can transmit frames in output buffer after IFG period\n"; 00533 scheduleEndIFGPeriod(); 00534 } 00535 }
void EtherMAC::handleEndTxPeriod | ( | ) | [private, virtual] |
Reimplemented from EtherMACBase.
00472 { 00473 EtherMACBase::handleEndTxPeriod(); 00474 00475 // only count transmissions in totalSuccessfulRxTxTime if channel is half-duplex 00476 if (!duplexMode) 00477 { 00478 simtime_t dt = simTime()-channelBusySince; 00479 totalSuccessfulRxTxTime += dt; 00480 } 00481 00482 backoffs = 0; 00483 00484 // check for and obey received PAUSE frames after each transmission 00485 if (checkAndScheduleEndPausePeriod()) 00486 return; 00487 00488 // Gigabit Ethernet: now decide if we transmit next frame right away (burst) or wait IFG 00489 // FIXME! this is not entirely correct, there must be IFG between burst frames too 00490 bool burstFrame=false; 00491 if (frameBursting && !txQueue.empty()) 00492 { 00493 // check if max bytes for burst not exceeded 00494 if (bytesSentInBurst<GIGABIT_MAX_BURST_BYTES) 00495 { 00496 burstFrame=true; 00497 EV << "Transmitting next frame in current burst\n"; 00498 } 00499 else 00500 { 00501 EV << "Next frame does not fit in current burst\n"; 00502 } 00503 } 00504 00505 if (burstFrame) 00506 startFrameTransmission(); 00507 else 00508 beginSendFrames(); 00509 }
void EtherMAC::handleMessage | ( | cMessage * | msg | ) | [protected, virtual] |
00209 { 00210 if (disabled) 00211 { 00212 EV << "MAC is disabled -- dropping message " << msg << "\n"; 00213 delete msg; 00214 return; 00215 } 00216 if (autoconfigInProgress) 00217 { 00218 handleAutoconfigMessage(msg); 00219 return; 00220 } 00221 00222 printState(); 00223 // some consistency check 00224 if (!duplexMode && transmitState==TRANSMITTING_STATE && receiveState!=RX_IDLE_STATE) 00225 error("Inconsistent state -- transmitting and receiving at the same time"); 00226 00227 if (!msg->isSelfMessage()) 00228 { 00229 // either frame from upper layer, or frame/jam signal from the network 00230 if (msg->arrivalGate() == gate("upperLayerIn")) 00231 processFrameFromUpperLayer(check_and_cast<EtherFrame *>(msg)); 00232 else 00233 processMsgFromNetwork(msg); 00234 } 00235 else 00236 { 00237 // Process different self-messages (timer signals) 00238 EV << "Self-message " << msg << " received\n"; 00239 switch (msg->kind()) 00240 { 00241 case ENDIFG: 00242 handleEndIFGPeriod(); 00243 break; 00244 00245 case ENDTRANSMISSION: 00246 handleEndTxPeriod(); 00247 break; 00248 00249 case ENDRECEPTION: 00250 handleEndRxPeriod(); 00251 break; 00252 00253 case ENDBACKOFF: 00254 handleEndBackoffPeriod(); 00255 break; 00256 00257 case ENDJAMMING: 00258 handleEndJammingPeriod(); 00259 break; 00260 00261 case ENDPAUSE: 00262 handleEndPausePeriod(); 00263 break; 00264 00265 default: 00266 error("self-message with unexpected message kind %d", msg->kind()); 00267 } 00268 } 00269 printState(); 00270 00271 if (ev.isGUI()) 00272 updateDisplayString(); 00273 }
void EtherMAC::handleRetransmission | ( | ) | [private] |
00582 { 00583 if (++backoffs > MAX_ATTEMPTS) 00584 { 00585 EV << "Number of retransmit attempts of frame exceeds maximum, cancelling transmission of frame\n"; 00586 delete txQueue.pop(); 00587 00588 transmitState = TX_IDLE_STATE; 00589 backoffs = 0; 00590 // no beginSendFrames(), because end of jam signal sending will trigger it automatically 00591 return; 00592 } 00593 00594 EV << "Executing backoff procedure\n"; 00595 int backoffrange = (backoffs>=BACKOFF_RANGE_LIMIT) ? 1024 : (1 << backoffs); 00596 int slotNumber = intuniform(0,backoffrange-1); 00597 simtime_t backofftime = slotNumber*slotTime; 00598 00599 scheduleAt(simTime()+backofftime, endBackoffMsg); 00600 transmitState = BACKOFF_STATE; 00601 00602 numBackoffs++; 00603 numBackoffsVector.record(numBackoffs); 00604 }
void EtherMAC::initialize | ( | ) | [protected, virtual] |
Reimplemented from EtherMACBase.
00057 { 00058 EtherMACBase::initialize(); 00059 00060 endRxMsg = new cMessage("EndReception", ENDRECEPTION); 00061 endBackoffMsg = new cMessage("EndBackoff", ENDBACKOFF); 00062 endJammingMsg = new cMessage("EndJamming", ENDJAMMING); 00063 00064 // check: datarate is forbidden with EtherMAC -- module's txrate must be used 00065 cGate *g = gate("physOut"); 00066 while (g) 00067 { 00068 cSimpleChannel *chan = dynamic_cast<cSimpleChannel*>(g->channel()); 00069 if (chan && chan->datarate()>0) 00070 error("connection on gate %s has data rate set: using data rate with EtherMAC " 00071 "is forbidden, module's txrate parameter must be used instead", 00072 g->fullPath().c_str()); 00073 g = g->toGate(); 00074 } 00075 00076 // launch autoconfig process 00077 bool performAutoconfig = true; 00078 if (!disabled && connected && performAutoconfig) 00079 { 00080 startAutoconfig(); 00081 } 00082 else 00083 { 00084 autoconfigInProgress = false; 00085 duplexMode = par("duplexEnabled"); 00086 calculateParameters(); 00087 } 00088 WATCH(autoconfigInProgress); 00089 00090 // initialize state info 00091 backoffs = 0; 00092 numConcurrentTransmissions = 0; 00093 00094 WATCH(backoffs); 00095 WATCH(numConcurrentTransmissions); 00096 00097 // initialize statistics 00098 totalCollisionTime = 0.0; 00099 totalSuccessfulRxTxTime = 0.0; 00100 numCollisions = numBackoffs = 0; 00101 00102 WATCH(numCollisions); 00103 WATCH(numBackoffs); 00104 00105 numCollisionsVector.setName("collisions"); 00106 numBackoffsVector.setName("backoffs"); 00107 }
void EtherMAC::initializeTxrate | ( | ) | [protected, virtual] |
void EtherMAC::printState | ( | ) | [private] |
00607 { 00608 #define CASE(x) case x: EV << #x; break 00609 EV << "transmitState: "; 00610 switch (transmitState) { 00611 CASE(TX_IDLE_STATE); 00612 CASE(WAIT_IFG_STATE); 00613 CASE(TRANSMITTING_STATE); 00614 CASE(JAMMING_STATE); 00615 CASE(BACKOFF_STATE); 00616 CASE(PAUSE_STATE); 00617 } 00618 EV << ", receiveState: "; 00619 switch (receiveState) { 00620 CASE(RX_IDLE_STATE); 00621 CASE(RECEIVING_STATE); 00622 CASE(RX_COLLISION_STATE); 00623 } 00624 EV << ", backoffs: " << backoffs; 00625 EV << ", numConcurrentTransmissions: " << numConcurrentTransmissions; 00626 EV << ", queueLength: " << txQueue.length() << endl; 00627 #undef CASE 00628 }
void EtherMAC::processFrameFromUpperLayer | ( | EtherFrame * | msg | ) | [private, virtual] |
Reimplemented from EtherMACBase.
00277 { 00278 EtherMACBase::processFrameFromUpperLayer(frame); 00279 00280 if (!autoconfigInProgress && (duplexMode || receiveState==RX_IDLE_STATE) && transmitState==TX_IDLE_STATE) 00281 { 00282 EV << "No incoming carrier signals detected, frame clear to send, wait IFG first\n"; 00283 scheduleEndIFGPeriod(); 00284 } 00285 }
void EtherMAC::processMsgFromNetwork | ( | cMessage * | msg | ) | [private, virtual] |
Reimplemented from EtherMACBase.
00289 { 00290 EtherMACBase::processMsgFromNetwork(msg); 00291 00292 simtime_t endRxTime = simTime() + msg->length()*bitTime; 00293 00294 if (!duplexMode && transmitState==TRANSMITTING_STATE) 00295 { 00296 // since we're halfduplex, receiveState must be RX_IDLE_STATE (asserted at top of handleMessage) 00297 if (msg->kind()==JAM_SIGNAL) 00298 error("Stray jam signal arrived while transmitting (usual cause is cable length exceeding allowed maximum)"); 00299 00300 EV << "Transmission interrupted by incoming frame, handling collision\n"; 00301 cancelEvent(endTxMsg); 00302 00303 EV << "Transmitting jam signal\n"; 00304 sendJamSignal(); // backoff will be executed when jamming finished 00305 00306 // set receive state and schedule end of reception 00307 receiveState = RX_COLLISION_STATE; 00308 numConcurrentTransmissions++; 00309 simtime_t endJamTime = simTime()+jamDuration; 00310 scheduleAt(endRxTime<endJamTime ? endJamTime : endRxTime, endRxMsg); 00311 delete msg; 00312 00313 numCollisions++; 00314 numCollisionsVector.record(numCollisions); 00315 } 00316 else if (receiveState==RX_IDLE_STATE) 00317 { 00318 if (msg->kind()==JAM_SIGNAL) 00319 error("Stray jam signal arrived (usual cause is cable length exceeding allowed maximum)"); 00320 00321 EV << "Start reception of frame\n"; 00322 numConcurrentTransmissions++; 00323 if (frameBeingReceived) 00324 error("frameBeingReceived!=0 in RX_IDLE_STATE"); 00325 frameBeingReceived = (EtherFrame *)msg; 00326 scheduleEndRxPeriod(msg); 00327 channelBusySince = simTime(); 00328 } 00329 else if (receiveState==RECEIVING_STATE && msg->kind()!=JAM_SIGNAL && endRxMsg->arrivalTime()-simTime()<bitTime) 00330 { 00331 // With the above condition we filter out "false" collisions that may occur with 00332 // back-to-back frames. That is: when "beginning of frame" message (this one) occurs 00333 // BEFORE "end of previous frame" event (endRxMsg) -- same simulation time, 00334 // only wrong order. 00335 00336 EV << "Back-to-back frames: completing reception of current frame, starting reception of next one\n"; 00337 00338 // complete reception of previous frame 00339 cancelEvent(endRxMsg); 00340 EtherFrame *frame = frameBeingReceived; 00341 frameBeingReceived = NULL; 00342 frameReceptionComplete(frame); 00343 00344 // start receiving next frame 00345 frameBeingReceived = (EtherFrame *)msg; 00346 scheduleEndRxPeriod(msg); 00347 } 00348 else // (receiveState==RECEIVING_STATE || receiveState==RX_COLLISION_STATE) 00349 { 00350 // handle overlapping receptions 00351 if (msg->kind()==JAM_SIGNAL) 00352 { 00353 if (numConcurrentTransmissions<=0) 00354 error("numConcurrentTransmissions=%d on jam arrival (stray jam?)",numConcurrentTransmissions); 00355 00356 numConcurrentTransmissions--; 00357 EV << "Jam signal received, this marks end of one transmission\n"; 00358 00359 // by the time jamming ends, all transmissions will have been aborted 00360 if (numConcurrentTransmissions==0) 00361 { 00362 EV << "Last jam signal received, collision will ends when jam ends\n"; 00363 cancelEvent(endRxMsg); 00364 scheduleAt(endRxTime, endRxMsg); 00365 } 00366 } 00367 else // ETH_FRAME or ETH_PAUSE 00368 { 00369 numConcurrentTransmissions++; 00370 if (endRxMsg->arrivalTime() < endRxTime) 00371 { 00372 // otherwise just wait until the end of the longest transmission 00373 EV << "Overlapping receptions -- setting collision state and extending collision period\n"; 00374 cancelEvent(endRxMsg); 00375 scheduleAt(endRxTime, endRxMsg); 00376 } 00377 else 00378 { 00379 EV << "Overlapping receptions -- setting collision state\n"; 00380 } 00381 } 00382 00383 // delete collided frames: arrived frame as well as the one we're currently receiving 00384 delete msg; 00385 if (receiveState==RECEIVING_STATE) 00386 { 00387 delete frameBeingReceived; 00388 frameBeingReceived = NULL; 00389 00390 numCollisions++; 00391 numCollisionsVector.record(numCollisions); 00392 } 00393 00394 // go to collision state 00395 receiveState = RX_COLLISION_STATE; 00396 } 00397 }
void EtherMAC::scheduleEndRxPeriod | ( | cMessage * | ) | [private] |
00576 { 00577 scheduleAt(simTime()+frame->length()*bitTime, endRxMsg); 00578 receiveState = RECEIVING_STATE; 00579 }
void EtherMAC::sendJamSignal | ( | ) | [private] |
00565 { 00566 cMessage *jam = new cMessage("JAM_SIGNAL", JAM_SIGNAL); 00567 jam->setByteLength(JAM_SIGNAL_BYTES); 00568 if (ev.isGUI()) updateConnectionColor(JAMMING_STATE); 00569 send(jam, "physOut"); 00570 00571 scheduleAt(simTime()+jamDuration, endJammingMsg); 00572 transmitState = JAMMING_STATE; 00573 }
void EtherMAC::startAutoconfig | ( | ) | [private] |
00115 { 00116 autoconfigInProgress = true; 00117 lowestTxrateSuggested = 0; // none suggested 00118 duplexVetoed = false; 00119 00120 double initialTxrate = par("txrate"); 00121 bool duplexEnabled = par("duplexEnabled"); 00122 txrate = 0; 00123 duplexMode = duplexEnabled; 00124 if (!duplexEnabled || initialTxrate>0) 00125 { 00126 EV << "Autoconfig: advertising our settings: " << initialTxrate/1000000 << "Mb, " 00127 << (duplexMode ? "duplex" : "half-duplex") << endl; 00128 00129 EtherAutoconfig *autoconf = new EtherAutoconfig("autoconf"); 00130 if (!duplexEnabled) 00131 autoconf->setHalfDuplex(true); 00132 if (initialTxrate>0) 00133 autoconf->setTxrate(initialTxrate); 00134 send(autoconf, "physOut"); 00135 } 00136 scheduleAt(simTime()+AUTOCONFIG_PERIOD, new cMessage("EndAutoconfig",ENDAUTOCONFIG)); 00137 }
void EtherMAC::startFrameTransmission | ( | ) | [private] |
00419 { 00420 cMessage *origFrame = (cMessage *)txQueue.tail(); 00421 EV << "Transmitting a copy of frame " << origFrame << endl; 00422 cMessage *frame = (cMessage *) origFrame->dup(); 00423 00424 // add preamble and SFD (Starting Frame Delimiter), then send out 00425 frame->addByteLength(PREAMBLE_BYTES+SFD_BYTES); 00426 if (ev.isGUI()) updateConnectionColor(TRANSMITTING_STATE); 00427 send(frame, "physOut"); 00428 00429 // update burst variables 00430 if (frameBursting) 00431 { 00432 bytesSentInBurst = frame->byteLength(); 00433 framesSentInBurst++; 00434 } 00435 00436 // check for collisions (there might be an ongoing reception which we don't know about, see below) 00437 if (!duplexMode && receiveState!=RX_IDLE_STATE) 00438 { 00439 // During the IFG period the hardware cannot listen to the channel, 00440 // so it might happen that receptions have begun during the IFG, 00441 // and even collisions might be in progress. 00442 // 00443 // But we don't know of any ongoing transmission so we blindly 00444 // start transmitting, immediately collide and send a jam signal. 00445 // 00446 sendJamSignal(); 00447 // numConcurrentTransmissions stays the same: +1 transmission, -1 jam 00448 00449 if (receiveState==RECEIVING_STATE) 00450 { 00451 delete frameBeingReceived; 00452 frameBeingReceived = NULL; 00453 00454 numCollisions++; 00455 numCollisionsVector.record(numCollisions); 00456 } 00457 // go to collision state 00458 receiveState = RX_COLLISION_STATE; 00459 } 00460 else 00461 { 00462 // no collision 00463 scheduleEndTxPeriod(frame); 00464 00465 // only count transmissions in totalSuccessfulRxTxTime if channel is half-duplex 00466 if (!duplexMode) 00467 channelBusySince = simTime(); 00468 } 00469 }
bool EtherMAC::autoconfigInProgress [private] |
int EtherMAC::backoffs [private] |
simtime_t EtherMAC::channelBusySince [private] |
bool EtherMAC::duplexVetoed [private] |
cMessage * EtherMAC::endBackoffMsg [private] |
cMessage * EtherMAC::endJammingMsg [private] |
cMessage* EtherMAC::endRxMsg [private] |
EtherFrame* EtherMAC::frameBeingReceived [private] |
double EtherMAC::lowestTxrateSuggested [private] |
unsigned long EtherMAC::numBackoffs [private] |
cOutVector EtherMAC::numBackoffsVector [private] |
unsigned long EtherMAC::numCollisions [private] |
cOutVector EtherMAC::numCollisionsVector [private] |
int EtherMAC::numConcurrentTransmissions [private] |
simtime_t EtherMAC::totalCollisionTime [private] |
simtime_t EtherMAC::totalSuccessfulRxTxTime [private] |