00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef _MSC_VER
00020 #pragma warning(disable:4786)
00021 #endif
00022
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <omnetpp.h>
00026
00027 #include "EtherMAC.h"
00028 #include "utils.h"
00029 #include "cmessage30.h"
00030
00031
00032
00033 static cEnvir& operator<< (cEnvir& ev, cMessage *msg)
00034 {
00035 ev.printf("(%s)%s",msg->className(),msg->fullName());
00036 return ev;
00037 }
00038
00039
00040 #ifndef OPP3
00041 static cEnvir& operator<< (cEnvir& ev, const MACAddress& addr)
00042 {
00043 char buf[20];
00044 ev << addr.toHexString(buf);
00045 return ev;
00046 }
00047 #endif
00048
00049 static std::ostream& operator<< (std::ostream& ev, const MACAddress& addr)
00050 {
00051 char buf[20];
00052 ev << addr.toHexString(buf);
00053 return ev;
00054 }
00055
00056
00057 Define_Module( EtherMAC );
00058
00059 unsigned int EtherMAC::autoAddressCtr = 0;
00060
00061 void EtherMAC::initialize()
00062 {
00063 outputbuffer.setName("outputBuffer");
00064
00065 frameBeingReceived = NULL;
00066 endTxMsg = new cMessage("EndTransmission", ENDTRANSMISSION);
00067 endJammingMsg = new cMessage("EndJamming", ENDJAMMING);
00068 endRxMsg = new cMessage("EndReception", ENDRECEPTION);
00069 endIFGMsg = new cMessage("EndIFG", ENDIFG);
00070 endBackoffMsg = new cMessage("EndBackoff", ENDBACKOFF);
00071 endPauseMsg = new cMessage("EndPause", ENDPAUSE);
00072
00073 const char *addrstr = par("address");
00074 if (!strcmp(addrstr,"auto"))
00075 {
00076
00077 ++autoAddressCtr;
00078 unsigned char addrbytes[6];
00079 addrbytes[0] = 0x0A;
00080 addrbytes[1] = 0xAA;
00081 addrbytes[2] = (autoAddressCtr>>24)&0xff;
00082 addrbytes[3] = (autoAddressCtr>>16)&0xff;
00083 addrbytes[4] = (autoAddressCtr>>8)&0xff;
00084 addrbytes[5] = (autoAddressCtr)&0xff;
00085 myaddress.setAddressBytes(addrbytes);
00086
00087
00088 char buf[20];
00089 par("address").setStringValue(myaddress.toHexString(buf));
00090 }
00091 else
00092 {
00093 myaddress.setAddress(addrstr);
00094 }
00095 promiscuous = par("promiscuous");
00096 maxQueueSize = par("maxQueueSize");
00097
00098 disabled = !gate("physicalOut")->destinationGate()->isConnected();
00099 if (disabled)
00100 EV << "MAC not connected to a network, disabling.\n";
00101
00102
00103 WATCH(disabled);
00104
00105
00106 bool performAutoconfig = true;
00107 if (!disabled && performAutoconfig)
00108 {
00109 startAutoconfig();
00110 }
00111 else
00112 {
00113 autoconfigInProgress = false;
00114 txrate = par("txrate");
00115 duplexMode = par("duplexEnabled");
00116 calculateParameters();
00117 }
00118 WATCH(autoconfigInProgress);
00119
00120
00121 transmitState = TX_IDLE_STATE;
00122 receiveState = RX_IDLE_STATE;
00123 backoffs = 0;
00124 numConcurrentTransmissions = 0;
00125 framesSentInBurst = 0;
00126 bytesSentInBurst = 0;
00127 pauseUnitsRequested = 0;
00128
00129 WATCH(transmitState);
00130 WATCH(receiveState);
00131 WATCH(backoffs);
00132 WATCH(numConcurrentTransmissions);
00133 WATCH(framesSentInBurst);
00134 WATCH(bytesSentInBurst);
00135 WATCH(pauseUnitsRequested);
00136
00137
00138 totalCollisionTime = 0.0;
00139 totalSuccessfulRxTxTime = 0.0;
00140 numFramesSent = numFramesReceivedOK = numBytesSent = numBytesReceivedOK = 0;
00141 numFramesPassedToHL = numDroppedBitError = numDroppedNotForUs = 0;
00142 numFramesFromHL = numFramesFromHLDropped = 0;
00143 numPauseFramesRcvd = numPauseFramesSent = numCollisions = numBackoffs = 0;
00144
00145 WATCH(numFramesSent);
00146 WATCH(numFramesReceivedOK);
00147 WATCH(numBytesSent);
00148 WATCH(numBytesReceivedOK);
00149 WATCH(numFramesFromHL);
00150 WATCH(numFramesFromHLDropped);
00151 WATCH(numDroppedBitError);
00152 WATCH(numDroppedNotForUs);
00153 WATCH(numFramesPassedToHL);
00154 WATCH(numPauseFramesRcvd);
00155 WATCH(numPauseFramesSent);
00156 WATCH(numCollisions);
00157 WATCH(numBackoffs);
00158
00159 numFramesSentVector.setName("framesSent");
00160 numFramesReceivedOKVector.setName("framesReceivedOK");
00161 numBytesSentVector.setName("bytesSent");
00162 numBytesReceivedOKVector.setName("bytesReceivedOK");
00163 numFramesFromHLDroppedVector.setName("framesFromHLDropped");
00164 numDroppedBitErrorVector.setName("framesDroppedBitError");
00165 numDroppedNotForUsVector.setName("framesDroppedNotForUs");
00166 numFramesPassedToHLVector.setName("framesPassedToHL");
00167 numPauseFramesRcvdVector.setName("pauseFramesRcvd");
00168 numPauseFramesSentVector.setName("pauseFramesSent");
00169 numCollisionsVector.setName("collisions");
00170 numBackoffsVector.setName("backoffs");
00171 }
00172
00173 void EtherMAC::printParameters()
00174 {
00175
00176 EV << "MAC address: " << myaddress << (promiscuous ? ", promiscuous mode" : "") << endl;
00177 EV << "txrate: " << txrate << ", " << (duplexMode ? "duplex" : "half-duplex") << endl;
00178 #if 0
00179 EV << "bitTime: " << bitTime << endl;
00180 EV << "carrierExtension: " << carrierExtension << endl;
00181 EV << "frameBursting: " << frameBursting << endl;
00182 EV << "slotTime: " << slotTime << endl;
00183 EV << "interFrameGap: " << interFrameGap << endl;
00184 EV << "\n";
00185 #endif
00186 }
00187
00188 void EtherMAC::calculateParameters()
00189 {
00190 if (disabled)
00191 {
00192 bitTime = slotTime = interFrameGap = jamDuration = shortestFrameDuration = 0;
00193 carrierExtension = frameBursting = false;
00194 return;
00195 }
00196
00197
00198 if (txrate!=ETHERNET_TXRATE && txrate!=FAST_ETHERNET_TXRATE && txrate!=GIGABIT_ETHERNET_TXRATE)
00199 {
00200 error("nonstandard txrate, must be %ld, %ld or %ld bit/sec", ETHERNET_TXRATE,
00201 FAST_ETHERNET_TXRATE, GIGABIT_ETHERNET_TXRATE);
00202 }
00203 bitTime = 1/(double)txrate;
00204
00205
00206 carrierExtension = (txrate==GIGABIT_ETHERNET_TXRATE && !duplexMode);
00207 frameBursting = (txrate==GIGABIT_ETHERNET_TXRATE);
00208
00209
00210 if (txrate==ETHERNET_TXRATE || txrate==FAST_ETHERNET_TXRATE)
00211 slotTime = SLOT_TIME;
00212 else
00213 slotTime = GIGABIT_SLOT_TIME;
00214
00215 interFrameGap = INTERFRAME_GAP_BITS/(double)txrate;
00216 jamDuration = 8*JAM_SIGNAL_BYTES*bitTime;
00217 shortestFrameDuration = carrierExtension ? GIGABIT_MIN_FRAME_WITH_EXT : MIN_ETHERNET_FRAME;
00218 }
00219
00220 void EtherMAC::startAutoconfig()
00221 {
00222 autoconfigInProgress = true;
00223 lowestTxrateSuggested = 0;
00224 duplexVetoed = false;
00225
00226 double initialTxrate = par("txrate");
00227 bool duplexEnabled = par("duplexEnabled");
00228 txrate = 0;
00229 duplexMode = duplexEnabled;
00230 if (!duplexEnabled || initialTxrate>0)
00231 {
00232 EV << "Autoconfig: advertising our settings: " << initialTxrate/1000000 << "Mb, "
00233 << (duplexMode ? "duplex" : "half-duplex") << endl;
00234
00235 EtherAutoconfig *autoconf = new EtherAutoconfig("autoconf");
00236 if (!duplexEnabled)
00237 autoconf->setHalfDuplex(true);
00238 if (initialTxrate>0)
00239 autoconf->setTxrate(initialTxrate);
00240 send(autoconf, "physicalOut");
00241 }
00242 scheduleAt(simTime()+AUTOCONFIG_PERIOD, new cMessage("EndAutoconfig",ENDAUTOCONFIG));
00243 }
00244
00245 void EtherMAC::handleAutoconfigMessage(cMessage *msg)
00246 {
00247 if (!msg->isSelfMessage())
00248 {
00249 if (msg->arrivalGate() == gate("upperLayerIn"))
00250 {
00251
00252 EV << "Received frame from upper layer during autoconfig period: " << msg << endl;
00253 processFrameFromUpperLayer(check_and_cast<EtherFrame *>(msg));
00254 }
00255 else
00256 {
00257
00258 EV << "Message from network during autoconfig period: " << msg << endl;
00259 EtherAutoconfig *autoconf = check_and_cast<EtherAutoconfig *>(msg);
00260 double acTxrate = autoconf->getTxrate();
00261
00262 EV << "Autoconfig message: ";
00263 if (acTxrate>0)
00264 EV << acTxrate/1000000 << "Mb ";
00265 if (autoconf->getHalfDuplex())
00266 EV << "non-duplex";
00267 EV << "\n";
00268
00269 if (acTxrate>0 && (acTxrate<lowestTxrateSuggested || lowestTxrateSuggested==0))
00270 lowestTxrateSuggested = acTxrate;
00271 if (!duplexVetoed && autoconf->getHalfDuplex())
00272 duplexVetoed = true;
00273 delete msg;
00274 }
00275 }
00276 else
00277 {
00278
00279 EV << "Self-message during autoconfig period: " << msg << endl;
00280
00281 delete msg;
00282 autoconfigInProgress = false;
00283
00284 double initialTxrate = par("txrate");
00285 bool duplexEnabled = par("duplexEnabled");
00286
00287 txrate = (initialTxrate==0 && lowestTxrateSuggested==0) ? 100000000 :
00288 (initialTxrate==0) ? lowestTxrateSuggested :
00289 (lowestTxrateSuggested==0) ? initialTxrate :
00290 (lowestTxrateSuggested<initialTxrate) ? lowestTxrateSuggested : initialTxrate;
00291 duplexMode = (duplexEnabled && !duplexVetoed);
00292 calculateParameters();
00293
00294 EV << "Parameters after autoconfig: txrate=" << txrate/1000000 << "Mb, " << (duplexMode ? "duplex" : "half-duplex") << endl;
00295
00296 #ifdef OPP3
00297 if (ev.isGUI())
00298 {
00299 char modestr[64];
00300 sprintf(modestr, "%dMb\n%s", int(txrate/1000000), (duplexMode ? "full duplex" : "half duplex"));
00301 displayString().setTagArg("t",0,modestr);
00302 displayString().setTagArg("t",1,"r");
00303 sprintf(modestr, "%s: %dMb %s", fullName(), int(txrate/1000000), (duplexMode ? "duplex" : "half duplex"));
00304 parentModule()->bubble(modestr);
00305 }
00306 #endif
00307
00308 if (!outputbuffer.empty())
00309 {
00310 EV << "Autoconfig period over, starting to send frames\n";
00311 scheduleEndIFGPeriod();
00312 }
00313 }
00314 }
00315
00316 void EtherMAC::handleMessage (cMessage *msg)
00317 {
00318 if (disabled)
00319 {
00320 EV << "MAC is disabled -- dropping message " << msg << "\n";
00321 delete msg;
00322 return;
00323 }
00324 if (autoconfigInProgress)
00325 {
00326 handleAutoconfigMessage(msg);
00327 return;
00328 }
00329
00330 printState();
00331
00332 if (!duplexMode && transmitState==TRANSMITTING_STATE && receiveState!=RX_IDLE_STATE)
00333 error("Inconsistent state -- transmitting and receiving at the same time");
00334
00335 if (!msg->isSelfMessage())
00336 {
00337
00338 if (msg->arrivalGate() == gate("upperLayerIn"))
00339 {
00340 EV << "Received frame from upper layer: " << msg << endl;
00341 processFrameFromUpperLayer(check_and_cast<EtherFrame *>(msg));
00342 }
00343 else
00344 {
00345 EV << "Received frame from network: " << msg << endl;
00346 processMsgFromNetwork(msg);
00347 }
00348 }
00349 else
00350 {
00351
00352 EV << "Self-message " << msg << " received\n";
00353 switch (msg->kind())
00354 {
00355 case ENDIFG:
00356 handleEndIFGPeriod();
00357 break;
00358
00359 case ENDTRANSMISSION:
00360 handleEndTxPeriod();
00361 break;
00362
00363 case ENDRECEPTION:
00364 handleEndRxPeriod();
00365 break;
00366
00367 case ENDBACKOFF:
00368 handleEndBackoffPeriod();
00369 break;
00370
00371 case ENDJAMMING:
00372 handleEndJammingPeriod();
00373 break;
00374
00375 case ENDPAUSE:
00376 handleEndPausePeriod();
00377 break;
00378
00379 default:
00380 error("self-message with unexpected message kind %d", msg->kind());
00381 }
00382 }
00383 printState();
00384 }
00385
00386
00387 void EtherMAC::processFrameFromUpperLayer(EtherFrame *frame)
00388 {
00389
00390
00391
00392
00393 if (frame->kind()!=ETH_FRAME && frame->kind()!=ETH_PAUSE)
00394 error("message with unexpected message kind %d arrived from higher layer", frame->kind());
00395
00396
00397 ASSERT((frame->kind()==ETH_PAUSE) == (dynamic_cast<EtherPauseFrame *>(frame)!=NULL));
00398
00399 if (frame->getDest().equals(myaddress))
00400 {
00401 char buf[20];
00402 error("logic error: frame %s from higher layer has local MAC address as dest (%s)",
00403 frame->fullName(), frame->getDest().toHexString(buf));
00404 }
00405
00406 if (frame->length()>8*MAX_ETHERNET_FRAME)
00407 error("packet from higher layer (%d bytes) exceeds maximum Ethernet frame size (%d)", frame->length()/8, MAX_ETHERNET_FRAME);
00408
00409
00410 bool isPauseFrame = (frame->kind()==ETH_PAUSE);
00411 if (!isPauseFrame)
00412 {
00413 numFramesFromHL++;
00414
00415 if (outputbuffer.length()>=maxQueueSize)
00416 {
00417 EV << "Packet " << frame << " arrived from higher layers but queue full, dropping\n";
00418 numFramesFromHLDropped++;
00419 numFramesFromHLDroppedVector.record(numFramesFromHLDropped);
00420 delete frame;
00421 return;
00422 }
00423
00424
00425 if (frame->getSrc().isEmpty())
00426 frame->setSrc(myaddress);
00427
00428
00429 EV << "Packet " << frame << " arrived from higher layers, enqueueing\n";
00430 outputbuffer.insert(frame);
00431 }
00432 else
00433 {
00434 EV << "PAUSE received from higher layer\n";
00435
00436
00437 if (!outputbuffer.empty())
00438 outputbuffer.insertBefore(outputbuffer.tail(), frame);
00439 else
00440 outputbuffer.insert(frame);
00441 }
00442
00443 if (!autoconfigInProgress && (duplexMode || receiveState==RX_IDLE_STATE) && transmitState==TX_IDLE_STATE)
00444 {
00445 EV << "No incoming carrier signals detected, frame clear to send, wait IFG first\n";
00446 scheduleEndIFGPeriod();
00447 }
00448 }
00449
00450
00451 void EtherMAC::processMsgFromNetwork(cMessage *msg)
00452 {
00453
00454 if (msg->kind()!=ETH_FRAME && msg->kind()!=ETH_PAUSE && msg->kind()!=JAM_SIGNAL)
00455 error("message with unexpected message kind %d arrived from network", msg->kind());
00456
00457
00458 if (!duplexMode && simTime()-msg->sendingTime()>=shortestFrameDuration)
00459 error("very long frame propagation time detected, maybe cable exceeds maximum allowed length? "
00460 "(%lgs corresponds to an approx. %lgm cable)",
00461 simTime()-msg->sendingTime(),
00462 (simTime()-msg->sendingTime())*200000000.0);
00463
00464 simtime_t endRxTime = simTime() + msg->length()*bitTime;
00465
00466 if (!duplexMode && transmitState==TRANSMITTING_STATE)
00467 {
00468
00469 if (msg->kind()==JAM_SIGNAL)
00470 error("Stray jam signal arrived while transmitting (usual cause is cable length exceeding allowed maximum)");
00471
00472 EV << "Transmission interrupted by incoming frame, handling collision\n";
00473 cancelEvent(endTxMsg);
00474
00475 EV << "Transmitting jam signal\n";
00476 sendJamSignal();
00477
00478
00479 receiveState = RX_COLLISION_STATE;
00480 numConcurrentTransmissions++;
00481 simtime_t endJamTime = simTime()+jamDuration;
00482 scheduleAt(endRxTime<endJamTime ? endJamTime : endRxTime, endRxMsg);
00483 delete msg;
00484
00485 numCollisions++;
00486 numCollisionsVector.record(numCollisions);
00487 }
00488 else if (receiveState==RX_IDLE_STATE)
00489 {
00490 if (msg->kind()==JAM_SIGNAL)
00491 error("Stray jam signal arrived (usual cause is cable length exceeding allowed maximum)");
00492
00493 EV << "Start reception of frame\n";
00494 numConcurrentTransmissions++;
00495 if (frameBeingReceived)
00496 error("frameBeingReceived!=0 in RX_IDLE_STATE");
00497 frameBeingReceived = (EtherFrame *)msg;
00498 scheduleEndRxPeriod(msg);
00499 channelBusySince = simTime();
00500 }
00501 else if (receiveState==RECEIVING_STATE && msg->kind()!=JAM_SIGNAL && endRxMsg->arrivalTime()-simTime()<bitTime)
00502 {
00503
00504
00505
00506
00507
00508 EV << "Back-to-back frames: completing reception of current frame, starting reception of next one\n";
00509
00510
00511 cancelEvent(endRxMsg);
00512 EtherFrame *frame = frameBeingReceived;
00513 frameBeingReceived = NULL;
00514 frameReceptionComplete(frame);
00515
00516
00517 frameBeingReceived = (EtherFrame *)msg;
00518 scheduleEndRxPeriod(msg);
00519 }
00520 else
00521 {
00522
00523 if (msg->kind()==JAM_SIGNAL)
00524 {
00525 if (numConcurrentTransmissions<=0)
00526 error("numConcurrentTransmissions=%d on jam arrival (stray jam?)",numConcurrentTransmissions);
00527
00528 numConcurrentTransmissions--;
00529 EV << "Jam signal received, this marks end of one transmission\n";
00530
00531
00532 if (numConcurrentTransmissions==0)
00533 {
00534 EV << "Last jam signal received, collision will ends when jam ends\n";
00535 cancelEvent(endRxMsg);
00536 scheduleAt(endRxTime, endRxMsg);
00537 }
00538 }
00539 else
00540 {
00541 numConcurrentTransmissions++;
00542 if (endRxMsg->arrivalTime() < endRxTime)
00543 {
00544
00545 EV << "Overlapping receptions -- setting collision state and extending collision period\n";
00546 cancelEvent(endRxMsg);
00547 scheduleAt(endRxTime, endRxMsg);
00548 }
00549 else
00550 {
00551 EV << "Overlapping receptions -- setting collision state\n";
00552 }
00553 }
00554
00555
00556 delete msg;
00557 if (receiveState==RECEIVING_STATE)
00558 {
00559 delete frameBeingReceived;
00560 frameBeingReceived = NULL;
00561
00562 numCollisions++;
00563 numCollisionsVector.record(numCollisions);
00564 }
00565
00566
00567 receiveState = RX_COLLISION_STATE;
00568 }
00569 }
00570
00571
00572 void EtherMAC::handleEndIFGPeriod()
00573 {
00574 if (transmitState!=WAIT_IFG_STATE)
00575 error("Not in WAIT_IFG_STATE at the end of IFG period");
00576
00577 if (outputbuffer.empty())
00578 error("End of IFG and no frame to transmit");
00579
00580
00581 cMessage *frame = (cMessage *)outputbuffer.tail();
00582 EV << "IFG elapsed, now begin transmission of frame " << frame << endl;
00583
00584
00585 if (carrierExtension && frame->length() < 8*GIGABIT_MIN_FRAME_WITH_EXT)
00586 {
00587 EV << "Performing carrier extension of small frame\n";
00588 frame->setLength(8*GIGABIT_MIN_FRAME_WITH_EXT);
00589 }
00590
00591
00592 if (frameBursting)
00593 {
00594 EV << "Starting frame burst\n";
00595 framesSentInBurst = 0;
00596 bytesSentInBurst = 0;
00597 }
00598
00599
00600 startFrameTransmission();
00601 }
00602
00603 void EtherMAC::startFrameTransmission()
00604 {
00605 cMessage *origFrame = (cMessage *)outputbuffer.tail();
00606 EV << "Transmitting a copy of frame " << origFrame << endl;
00607 cMessage *frame = (cMessage *) origFrame->dup();
00608
00609
00610 frame->setLength(frame->length()+8*PREAMBLE_BYTES+8*SFD_BYTES);
00611 send(frame, "physicalOut");
00612
00613
00614 if (frameBursting)
00615 {
00616 bytesSentInBurst = frame->length()/8;
00617 framesSentInBurst++;
00618 }
00619
00620
00621 if (!duplexMode && receiveState!=RX_IDLE_STATE)
00622 {
00623
00624
00625
00626
00627
00628
00629
00630 sendJamSignal();
00631
00632
00633 if (receiveState==RECEIVING_STATE)
00634 {
00635 delete frameBeingReceived;
00636 frameBeingReceived = NULL;
00637
00638 numCollisions++;
00639 numCollisionsVector.record(numCollisions);
00640 }
00641
00642 receiveState = RX_COLLISION_STATE;
00643 }
00644 else
00645 {
00646
00647 scheduleEndTxPeriod(frame);
00648
00649
00650 if (!duplexMode)
00651 channelBusySince = simTime();
00652 }
00653 }
00654
00655 void EtherMAC::handleEndTxPeriod()
00656 {
00657
00658 if (transmitState!=TRANSMITTING_STATE || (!duplexMode && receiveState!=RX_IDLE_STATE))
00659 error("End of transmission, and incorrect state detected");
00660
00661 if (outputbuffer.empty())
00662 error("Frame under transmission cannot be found");
00663
00664
00665 cMessage *frame = (cMessage*)outputbuffer.pop();
00666
00667 numFramesSent++;
00668 numBytesSent += frame->length()/8;
00669 numFramesSentVector.record(numFramesSent);
00670 numBytesSentVector.record(numBytesSent);
00671
00672 if (frame->kind()==ETH_PAUSE)
00673 {
00674 numPauseFramesSent++;
00675 numPauseFramesSentVector.record(numPauseFramesSent);
00676 }
00677
00678
00679 if (!duplexMode)
00680 {
00681 simtime_t dt = simTime()-channelBusySince;
00682 totalSuccessfulRxTxTime += dt;
00683 }
00684
00685 EV << "Transmission of " << frame << " successfully completed\n";
00686 delete frame;
00687 backoffs = 0;
00688
00689
00690 if (pauseUnitsRequested>0)
00691 {
00692
00693 EV << "Going to PAUSE mode for " << pauseUnitsRequested << " time units\n";
00694 scheduleEndPausePeriod(pauseUnitsRequested);
00695 pauseUnitsRequested = 0;
00696 return;
00697 }
00698
00699
00700
00701 bool burstFrame=false;
00702 if (frameBursting && !outputbuffer.empty())
00703 {
00704
00705 if (bytesSentInBurst<GIGABIT_MAX_BURST_BYTES)
00706 {
00707 burstFrame=true;
00708 EV << "Transmitting next frame in current burst\n";
00709 }
00710 else
00711 {
00712 EV << "Next frame does not fit in current burst\n";
00713 }
00714 }
00715
00716 if (burstFrame)
00717 startFrameTransmission();
00718 else
00719 beginSendFrames();
00720 }
00721
00722 void EtherMAC::handleEndRxPeriod()
00723 {
00724 EV << "Frame reception complete\n";
00725 simtime_t dt = simTime()-channelBusySince;
00726 if (receiveState==RECEIVING_STATE)
00727 {
00728 EtherFrame *frame = frameBeingReceived;
00729 frameBeingReceived = NULL;
00730 frameReceptionComplete(frame);
00731 totalSuccessfulRxTxTime += dt;
00732 }
00733 else
00734 {
00735 totalCollisionTime += dt;
00736 }
00737
00738 receiveState = RX_IDLE_STATE;
00739 numConcurrentTransmissions = 0;
00740
00741 if (transmitState==TX_IDLE_STATE && !outputbuffer.empty())
00742 {
00743 EV << "Receiver now idle, can transmit frames in output buffer after IFG period\n";
00744 scheduleEndIFGPeriod();
00745 }
00746 }
00747
00748 void EtherMAC::handleEndBackoffPeriod()
00749 {
00750 if (transmitState != BACKOFF_STATE)
00751 error("At end of BACKOFF not in BACKOFF_STATE!");
00752 if (outputbuffer.empty())
00753 error("At end of BACKOFF and buffer empty!");
00754
00755 if (receiveState==RX_IDLE_STATE)
00756 {
00757 EV << "Backoff period ended, wait IFG\n";
00758 scheduleEndIFGPeriod();
00759 }
00760 else
00761 {
00762 EV << "Backoff period ended but channel not free, idling\n";
00763 transmitState = TX_IDLE_STATE;
00764 }
00765 }
00766
00767 void EtherMAC::handleEndJammingPeriod()
00768 {
00769 if (transmitState != JAMMING_STATE)
00770 error("At end of JAMMING not in JAMMING_STATE!");
00771 EV << "Jamming finished, executing backoff\n";
00772 handleRetransmission();
00773 }
00774
00775 void EtherMAC::handleEndPausePeriod()
00776 {
00777 if (transmitState != PAUSE_STATE)
00778 error("At end of PAUSE not in PAUSE_STATE!");
00779 EV << "Pause finished, resuming transmissions\n";
00780 beginSendFrames();
00781 }
00782
00783 void EtherMAC::sendJamSignal()
00784 {
00785 cMessage *jam = new cMessage("JAM_SIGNAL", JAM_SIGNAL);
00786 jam->setLength(8*JAM_SIGNAL_BYTES);
00787 send(jam, "physicalOut");
00788
00789 scheduleAt(simTime()+jamDuration, endJammingMsg);
00790 transmitState = JAMMING_STATE;
00791 }
00792
00793 void EtherMAC::scheduleEndIFGPeriod()
00794 {
00795 scheduleAt(simTime()+interFrameGap, endIFGMsg);
00796 transmitState = WAIT_IFG_STATE;
00797 }
00798
00799 void EtherMAC::scheduleEndTxPeriod(cMessage *frame)
00800 {
00801 scheduleAt(simTime()+frame->length()*bitTime, endTxMsg);
00802 transmitState = TRANSMITTING_STATE;
00803 }
00804
00805 void EtherMAC::scheduleEndRxPeriod(cMessage *frame)
00806 {
00807 scheduleAt(simTime()+frame->length()*bitTime, endRxMsg);
00808 receiveState = RECEIVING_STATE;
00809 }
00810
00811 void EtherMAC::scheduleEndPausePeriod(int pauseUnits)
00812 {
00813
00814 double pausePeriod = pauseUnits*PAUSE_BITTIME*bitTime;
00815 scheduleAt(simTime()+pausePeriod, endPauseMsg);
00816 transmitState = PAUSE_STATE;
00817 }
00818
00819 void EtherMAC::frameReceptionComplete(EtherFrame *frame)
00820 {
00821 int pauseUnits;
00822
00823 switch (frame->kind())
00824 {
00825 case ETH_FRAME:
00826 processReceivedDataFrame((EtherFrame *)frame);
00827 break;
00828
00829 case ETH_PAUSE:
00830 pauseUnits = ((EtherPauseFrame *)frame)->getPauseTime();
00831 delete frame;
00832 numPauseFramesRcvd++;
00833 numPauseFramesRcvdVector.record(numPauseFramesRcvd);
00834 processPauseCommand(pauseUnits);
00835 break;
00836
00837 default:
00838 error("Invalid message kind %d",frame->kind());
00839 }
00840 }
00841
00842 void EtherMAC::processReceivedDataFrame(EtherFrame *frame)
00843 {
00844
00845 if (frame->hasBitError())
00846 {
00847 numDroppedBitError++;
00848 numDroppedBitErrorVector.record(numDroppedBitError);
00849 delete frame;
00850 return;
00851 }
00852
00853
00854 frame->setLength(frame->length() - 8*PREAMBLE_BYTES - 8*SFD_BYTES);
00855
00856
00857 numFramesReceivedOK++;
00858 numBytesReceivedOK += frame->length()/8;
00859 numFramesReceivedOKVector.record(numFramesReceivedOK);
00860 numBytesReceivedOKVector.record(numBytesReceivedOK);
00861
00862
00863
00864 if (!promiscuous && !frame->getDest().isBroadcast() && !frame->getDest().equals(myaddress))
00865 {
00866 EV << "Frame `" << frame->name() <<"' not destined to us, discarding\n";
00867 numDroppedNotForUs++;
00868 numDroppedNotForUsVector.record(numDroppedNotForUs);
00869 delete frame;
00870 return;
00871 }
00872
00873 numFramesPassedToHL++;
00874 numFramesPassedToHLVector.record(numFramesPassedToHL);
00875
00876
00877 send(frame, "upperLayerOut");
00878 }
00879
00880 void EtherMAC::processPauseCommand(int pauseUnits)
00881 {
00882 if (transmitState==TX_IDLE_STATE)
00883 {
00884 EV << "PAUSE frame received, pausing for " << pauseUnitsRequested << " time units\n";
00885 if (pauseUnits>0)
00886 scheduleEndPausePeriod(pauseUnits);
00887 }
00888 else if (transmitState==PAUSE_STATE)
00889 {
00890 EV << "PAUSE frame received, pausing for " << pauseUnitsRequested << " more time units from now\n";
00891 cancelEvent(endPauseMsg);
00892 if (pauseUnits>0)
00893 scheduleEndPausePeriod(pauseUnits);
00894 }
00895 else
00896 {
00897
00898
00899 EV << "PAUSE frame received, storing pause request\n";
00900 pauseUnitsRequested = pauseUnits;
00901 }
00902 }
00903
00904 void EtherMAC::handleRetransmission()
00905 {
00906 if (++backoffs > MAX_ATTEMPTS)
00907 {
00908 EV << "Number of retransmit attempts of frame exceeds maximum, cancelling transmission of frame\n";
00909 delete outputbuffer.pop();
00910
00911 transmitState = TX_IDLE_STATE;
00912 backoffs = 0;
00913
00914 return;
00915 }
00916
00917 EV << "Executing backoff procedure\n";
00918 int backoffrange = (backoffs>=BACKOFF_RANGE_LIMIT) ? 1024 : (1 << backoffs);
00919 int slotNumber = intuniform(0,backoffrange-1);
00920 simtime_t backofftime = slotNumber*slotTime;
00921
00922 scheduleAt(simTime()+backofftime, endBackoffMsg);
00923 transmitState = BACKOFF_STATE;
00924
00925 numBackoffs++;
00926 numBackoffsVector.record(numBackoffs);
00927 }
00928
00929 void EtherMAC::printState()
00930 {
00931 #define CASE(x) case x: EV << #x; break
00932 EV << "transmitState: ";
00933 switch (transmitState) {
00934 CASE(TX_IDLE_STATE);
00935 CASE(WAIT_IFG_STATE);
00936 CASE(TRANSMITTING_STATE);
00937 CASE(JAMMING_STATE);
00938 CASE(BACKOFF_STATE);
00939 CASE(PAUSE_STATE);
00940 }
00941 EV << ", receiveState: ";
00942 switch (receiveState) {
00943 CASE(RX_IDLE_STATE);
00944 CASE(RECEIVING_STATE);
00945 CASE(RX_COLLISION_STATE);
00946 }
00947 EV << ", backoffs: " << backoffs;
00948 EV << ", numConcurrentTransmissions: " << numConcurrentTransmissions;
00949 EV << ", queueLength: " << outputbuffer.length() << endl;
00950 #undef CASE
00951 }
00952
00953 void EtherMAC::beginSendFrames()
00954 {
00955 if (!outputbuffer.empty())
00956 {
00957
00958 EV << "Transmit next frame in output queue, after IFG period\n";
00959 scheduleEndIFGPeriod();
00960 }
00961 else
00962 {
00963
00964 EV << "No more frames to send, transmitter set to idle\n";
00965 transmitState = TX_IDLE_STATE;
00966 }
00967 }
00968
00969 void EtherMAC::finish()
00970 {
00971 if (!disabled && par("writeScalars").boolValue())
00972 {
00973 double t = simTime();
00974 simtime_t totalChannelIdleTime = t - totalSuccessfulRxTxTime - totalCollisionTime;
00975 recordScalar("simulated time", t);
00976 recordScalar("txrate (Mb)", txrate/1000000);
00977 recordScalar("full duplex", duplexMode);
00978 recordScalar("rx channel idle (%)", 100*totalChannelIdleTime/t);
00979 recordScalar("rx channel utilization (%)", 100*totalSuccessfulRxTxTime/t);
00980 recordScalar("rx channel collision (%)", 100*totalCollisionTime);
00981 recordScalar("frames sent", numFramesSent);
00982 recordScalar("frames rcvd", numFramesReceivedOK);
00983 recordScalar("bytes sent", numBytesSent);
00984 recordScalar("bytes rcvd", numBytesReceivedOK);
00985 recordScalar("frames from higher layer", numFramesFromHL);
00986 recordScalar("frames from higher layer dropped (queue full)", numFramesFromHLDropped);
00987 recordScalar("frames dropped (bit error)", numDroppedBitError);
00988 recordScalar("frames dropped (not for us)", numDroppedNotForUs);
00989 recordScalar("frames passed up to HL", numFramesPassedToHL);
00990 recordScalar("PAUSE frames sent", numPauseFramesSent);
00991 recordScalar("PAUSE frames rcvd", numPauseFramesRcvd);
00992 recordScalar("collisions", numCollisions);
00993 recordScalar("backoffs", numBackoffs);
00994
00995 if (t>0)
00996 {
00997 recordScalar("frames/sec sent", numFramesSent/t);
00998 recordScalar("frames/sec rcvd", numFramesReceivedOK/t);
00999 recordScalar("bits/sec sent", 8*numBytesSent/t);
01000 recordScalar("bits/sec rcvd", 8*numBytesReceivedOK/t);
01001 }
01002 }
01003 }
01004
01005