#include <EtherMAC.h>
|
|
00043 {
00044 frameBeingReceived = NULL;
00045 endTxMsg = endJammingMsg = endRxMsg = endIFGMsg = endBackoffMsg = endPauseMsg = NULL;
00046 }
|
|
|
00049 {
00050 delete frameBeingReceived;
00051 cancelAndDelete(endTxMsg);
00052 cancelAndDelete(endJammingMsg);
00053 cancelAndDelete(endRxMsg);
00054 cancelAndDelete(endIFGMsg);
00055 cancelAndDelete(endBackoffMsg);
00056 cancelAndDelete(endPauseMsg);
00057 }
|
|
|
01041 {
01042 if (!txQueue.empty())
01043 {
01044 // Other frames are queued, therefore wait IFG period and transmit next frame
01045 EV << "Transmit next frame in output queue, after IFG period\n";
01046 scheduleEndIFGPeriod();
01047 }
01048 else
01049 {
01050 transmitState = TX_IDLE_STATE;
01051 if (queueModule)
01052 {
01053 // tell queue module that we've become idle
01054 EV << "Requesting another frame from queue module\n";
01055 queueModule->requestPacket();
01056 }
01057 else
01058 {
01059 // No more frames set transmitter to idle
01060 EV << "No more frames to send, transmitter set to idle\n";
01061 }
01062 }
01063 }
|
|
|
00206 {
00207 if (disabled)
00208 {
00209 bitTime = slotTime = interFrameGap = jamDuration = shortestFrameDuration = 0;
00210 carrierExtension = frameBursting = false;
00211 return;
00212 }
00213
00214 // calculate other parameters from txrate and duplexMode
00215 if (txrate!=ETHERNET_TXRATE && txrate!=FAST_ETHERNET_TXRATE && txrate!=GIGABIT_ETHERNET_TXRATE)
00216 {
00217 error("nonstandard txrate, must be %ld, %ld or %ld bit/sec", ETHERNET_TXRATE,
00218 FAST_ETHERNET_TXRATE, GIGABIT_ETHERNET_TXRATE);
00219 }
00220 bitTime = 1/(double)txrate;
00221
00222 // Only if Gigabit Ethernet
00223 carrierExtension = (txrate==GIGABIT_ETHERNET_TXRATE && !duplexMode);
00224 frameBursting = (txrate==GIGABIT_ETHERNET_TXRATE);
00225
00226 // set slot time
00227 if (txrate==ETHERNET_TXRATE || txrate==FAST_ETHERNET_TXRATE)
00228 slotTime = SLOT_TIME;
00229 else
00230 slotTime = GIGABIT_SLOT_TIME;
00231
00232 interFrameGap = INTERFRAME_GAP_BITS/(double)txrate;
00233 jamDuration = 8*JAM_SIGNAL_BYTES*bitTime;
00234 shortestFrameDuration = carrierExtension ? GIGABIT_MIN_FRAME_WITH_EXT : MIN_ETHERNET_FRAME;
00235 }
|
|
|
01066 {
01067 if (!disabled && par("writeScalars").boolValue())
01068 {
01069 double t = simTime();
01070 simtime_t totalChannelIdleTime = t - totalSuccessfulRxTxTime - totalCollisionTime;
01071 recordScalar("simulated time", t);
01072 recordScalar("txrate (Mb)", txrate/1000000);
01073 recordScalar("full duplex", duplexMode);
01074 recordScalar("rx channel idle (%)", 100*totalChannelIdleTime/t);
01075 recordScalar("rx channel utilization (%)", 100*totalSuccessfulRxTxTime/t);
01076 recordScalar("rx channel collision (%)", 100*totalCollisionTime);
01077 recordScalar("frames sent", numFramesSent);
01078 recordScalar("frames rcvd", numFramesReceivedOK);
01079 recordScalar("bytes sent", numBytesSent);
01080 recordScalar("bytes rcvd", numBytesReceivedOK);
01081 recordScalar("frames from higher layer", numFramesFromHL);
01082 recordScalar("frames from higher layer dropped (iface down)", numDroppedIfaceDown);
01083 recordScalar("frames dropped (bit error)", numDroppedBitError);
01084 recordScalar("frames dropped (not for us)", numDroppedNotForUs);
01085 recordScalar("frames passed up to HL", numFramesPassedToHL);
01086 recordScalar("PAUSE frames sent", numPauseFramesSent);
01087 recordScalar("PAUSE frames rcvd", numPauseFramesRcvd);
01088 recordScalar("collisions", numCollisions);
01089 recordScalar("backoffs", numBackoffs);
01090
01091 if (t>0)
01092 {
01093 recordScalar("frames/sec sent", numFramesSent/t);
01094 recordScalar("frames/sec rcvd", numFramesReceivedOK/t);
01095 recordScalar("bits/sec sent", 8*numBytesSent/t);
01096 recordScalar("bits/sec rcvd", 8*numBytesReceivedOK/t);
01097 }
01098 }
01099 }
|
|
|
00836 {
00837 int pauseUnits;
00838
00839 switch (frame->kind())
00840 {
00841 case ETH_FRAME:
00842 processReceivedDataFrame((EtherFrame *)frame);
00843 break;
00844
00845 case ETH_PAUSE:
00846 pauseUnits = ((EtherPauseFrame *)frame)->getPauseTime();
00847 delete frame;
00848 numPauseFramesRcvd++;
00849 numPauseFramesRcvdVector.record(numPauseFramesRcvd);
00850 processPauseCommand(pauseUnits);
00851 break;
00852
00853 default:
00854 error("Invalid message kind %d",frame->kind());
00855 }
00856 }
|
|
|
Returns MAC address 00083 {return myaddress;}
|
|
|
00263 {
00264 if (!msg->isSelfMessage())
00265 {
00266 if (msg->arrivalGate() == gate("upperLayerIn"))
00267 {
00268 // from upper layer
00269 EV << "Received frame from upper layer during autoconfig period: " << msg << endl;
00270 processFrameFromUpperLayer(check_and_cast<EtherFrame *>(msg));
00271 }
00272 else
00273 {
00274 // from network: must be autoconfig message
00275 EV << "Message from network during autoconfig period: " << msg << endl;
00276 EtherAutoconfig *autoconf = check_and_cast<EtherAutoconfig *>(msg);
00277 double acTxrate = autoconf->getTxrate();
00278
00279 EV << "Autoconfig message: ";
00280 if (acTxrate>0)
00281 EV << acTxrate/1000000 << "Mb ";
00282 if (autoconf->getHalfDuplex())
00283 EV << "non-duplex";
00284 EV << "\n";
00285
00286 if (acTxrate>0 && (acTxrate<lowestTxrateSuggested || lowestTxrateSuggested==0))
00287 lowestTxrateSuggested = acTxrate;
00288 if (!duplexVetoed && autoconf->getHalfDuplex())
00289 duplexVetoed = true;
00290 delete msg;
00291 }
00292 }
00293 else
00294 {
00295 // self-message signals end of autoconfig period
00296 EV << "Self-message during autoconfig period: " << msg << endl;
00297
00298 delete msg;
00299 autoconfigInProgress = false;
00300
00301 double initialTxrate = par("txrate");
00302 bool duplexEnabled = par("duplexEnabled");
00303
00304 txrate = (initialTxrate==0 && lowestTxrateSuggested==0) ? 100000000 /* 100 Mb */:
00305 (initialTxrate==0) ? lowestTxrateSuggested :
00306 (lowestTxrateSuggested==0) ? initialTxrate :
00307 (lowestTxrateSuggested<initialTxrate) ? lowestTxrateSuggested : initialTxrate;
00308 duplexMode = (duplexEnabled && !duplexVetoed);
00309 calculateParameters();
00310
00311 EV << "Parameters after autoconfig: txrate=" << txrate/1000000 << "Mb, " << (duplexMode ? "duplex" : "half-duplex") << endl;
00312
00313 if (ev.isGUI())
00314 {
00315 char modestr[64];
00316 sprintf(modestr, "%dMb\n%s", int(txrate/1000000), (duplexMode ? "full duplex" : "half duplex"));
00317 displayString().setTagArg("t",0,modestr);
00318 //displayString().setTagArg("t",1,"r");
00319 sprintf(modestr, "%s: %dMb %s", fullName(), int(txrate/1000000), (duplexMode ? "duplex" : "half duplex"));
00320 parentModule()->bubble(modestr);
00321 }
00322
00323 if (!txQueue.empty())
00324 {
00325 EV << "Autoconfig period over, starting to send frames\n";
00326 scheduleEndIFGPeriod();
00327 }
00328 }
00329 }
|
|
|
00764 {
00765 if (transmitState != BACKOFF_STATE)
00766 error("At end of BACKOFF not in BACKOFF_STATE!");
00767 if (txQueue.empty())
00768 error("At end of BACKOFF and buffer empty!");
00769
00770 if (receiveState==RX_IDLE_STATE)
00771 {
00772 EV << "Backoff period ended, wait IFG\n";
00773 scheduleEndIFGPeriod();
00774 }
00775 else
00776 {
00777 EV << "Backoff period ended but channel not free, idling\n";
00778 transmitState = TX_IDLE_STATE;
00779 }
00780 }
|
|
|
00587 {
00588 if (transmitState!=WAIT_IFG_STATE)
00589 error("Not in WAIT_IFG_STATE at the end of IFG period");
00590
00591 if (txQueue.empty())
00592 error("End of IFG and no frame to transmit");
00593
00594 // End of IFG period, okay to transmit, if Rx idle OR duplexMode
00595 cMessage *frame = (cMessage *)txQueue.tail();
00596 EV << "IFG elapsed, now begin transmission of frame " << frame << endl;
00597
00598 // Perform carrier extension if in Gigabit Ethernet
00599 if (carrierExtension && frame->byteLength() < GIGABIT_MIN_FRAME_WITH_EXT)
00600 {
00601 EV << "Performing carrier extension of small frame\n";
00602 frame->setByteLength(GIGABIT_MIN_FRAME_WITH_EXT);
00603 }
00604
00605 // start frame burst, if enabled
00606 if (frameBursting)
00607 {
00608 EV << "Starting frame burst\n";
00609 framesSentInBurst = 0;
00610 bytesSentInBurst = 0;
00611 }
00612
00613 // send frame to network
00614 startFrameTransmission();
00615 }
|
|
|
00783 {
00784 if (transmitState != JAMMING_STATE)
00785 error("At end of JAMMING not in JAMMING_STATE!");
00786 EV << "Jamming finished, executing backoff\n";
00787 handleRetransmission();
00788 }
|
|
|
00791 {
00792 if (transmitState != PAUSE_STATE)
00793 error("At end of PAUSE not in PAUSE_STATE!");
00794 EV << "Pause finished, resuming transmissions\n";
00795 beginSendFrames();
00796 }
|
|
|
00738 {
00739 EV << "Frame reception complete\n";
00740 simtime_t dt = simTime()-channelBusySince;
00741 if (receiveState==RECEIVING_STATE) // i.e. not RX_COLLISION_STATE
00742 {
00743 EtherFrame *frame = frameBeingReceived;
00744 frameBeingReceived = NULL;
00745 frameReceptionComplete(frame);
00746 totalSuccessfulRxTxTime += dt;
00747 }
00748 else
00749 {
00750 totalCollisionTime += dt;
00751 }
00752
00753 receiveState = RX_IDLE_STATE;
00754 numConcurrentTransmissions = 0;
00755
00756 if (transmitState==TX_IDLE_STATE && !txQueue.empty())
00757 {
00758 EV << "Receiver now idle, can transmit frames in output buffer after IFG period\n";
00759 scheduleEndIFGPeriod();
00760 }
00761 }
|
|
|
00671 {
00672 // we only get here if transmission has finished successfully, without collision
00673 if (transmitState!=TRANSMITTING_STATE || (!duplexMode && receiveState!=RX_IDLE_STATE))
00674 error("End of transmission, and incorrect state detected");
00675
00676 if (txQueue.empty())
00677 error("Frame under transmission cannot be found");
00678
00679 // get frame from buffer
00680 cMessage *frame = (cMessage*)txQueue.pop();
00681
00682 numFramesSent++;
00683 numBytesSent += frame->byteLength();
00684 numFramesSentVector.record(numFramesSent);
00685 numBytesSentVector.record(numBytesSent);
00686
00687 if (frame->kind()==ETH_PAUSE)
00688 {
00689 numPauseFramesSent++;
00690 numPauseFramesSentVector.record(numPauseFramesSent);
00691 }
00692
00693 // only count transmissions in totalSuccessfulRxTxTime if channel is half-duplex
00694 if (!duplexMode)
00695 {
00696 simtime_t dt = simTime()-channelBusySince;
00697 totalSuccessfulRxTxTime += dt;
00698 }
00699
00700 EV << "Transmission of " << frame << " successfully completed\n";
00701 delete frame;
00702 backoffs = 0;
00703
00704 // check for and obey received PAUSE frames after each transmission
00705 if (pauseUnitsRequested>0)
00706 {
00707 // if we received a PAUSE frame recently, go into PAUSE state
00708 EV << "Going to PAUSE mode for " << pauseUnitsRequested << " time units\n";
00709 scheduleEndPausePeriod(pauseUnitsRequested);
00710 pauseUnitsRequested = 0;
00711 return;
00712 }
00713
00714 // Gigabit Ethernet: now decide if we transmit next frame right away (burst) or wait IFG
00715 // FIXME! this is not entirely correct, there must be IFG between burst frames too
00716 bool burstFrame=false;
00717 if (frameBursting && !txQueue.empty())
00718 {
00719 // check if max bytes for burst not exceeded
00720 if (bytesSentInBurst<GIGABIT_MAX_BURST_BYTES)
00721 {
00722 burstFrame=true;
00723 EV << "Transmitting next frame in current burst\n";
00724 }
00725 else
00726 {
00727 EV << "Next frame does not fit in current burst\n";
00728 }
00729 }
00730
00731 if (burstFrame)
00732 startFrameTransmission();
00733 else
00734 beginSendFrames();
00735 }
|
|
|
00332 {
00333 if (disabled)
00334 {
00335 EV << "MAC is disabled -- dropping message " << msg << "\n";
00336 delete msg;
00337 return;
00338 }
00339 if (autoconfigInProgress)
00340 {
00341 handleAutoconfigMessage(msg);
00342 return;
00343 }
00344
00345 printState();
00346 // some consistency check
00347 if (!duplexMode && transmitState==TRANSMITTING_STATE && receiveState!=RX_IDLE_STATE)
00348 error("Inconsistent state -- transmitting and receiving at the same time");
00349
00350 if (!msg->isSelfMessage())
00351 {
00352 // either frame from upper layer, or frame/jam signal from the network
00353 if (msg->arrivalGate() == gate("upperLayerIn"))
00354 {
00355 EV << "Received frame from upper layer: " << msg << endl;
00356 processFrameFromUpperLayer(check_and_cast<EtherFrame *>(msg));
00357 }
00358 else
00359 {
00360 EV << "Received frame from network: " << msg << endl;
00361 processMsgFromNetwork(msg);
00362 }
00363 }
00364 else
00365 {
00366 // Process different self-messages (timer signals)
00367 EV << "Self-message " << msg << " received\n";
00368 switch (msg->kind())
00369 {
00370 case ENDIFG:
00371 handleEndIFGPeriod();
00372 break;
00373
00374 case ENDTRANSMISSION:
00375 handleEndTxPeriod();
00376 break;
00377
00378 case ENDRECEPTION:
00379 handleEndRxPeriod();
00380 break;
00381
00382 case ENDBACKOFF:
00383 handleEndBackoffPeriod();
00384 break;
00385
00386 case ENDJAMMING:
00387 handleEndJammingPeriod();
00388 break;
00389
00390 case ENDPAUSE:
00391 handleEndPausePeriod();
00392 break;
00393
00394 default:
00395 error("self-message with unexpected message kind %d", msg->kind());
00396 }
00397 }
00398 printState();
00399
00400 if (ev.isGUI())
00401 updateDisplayString();
00402 }
|
|
|
00921 {
00922 if (++backoffs > MAX_ATTEMPTS)
00923 {
00924 EV << "Number of retransmit attempts of frame exceeds maximum, cancelling transmission of frame\n";
00925 delete txQueue.pop();
00926
00927 transmitState = TX_IDLE_STATE;
00928 backoffs = 0;
00929 // no beginSendFrames(), because end of jam signal sending will trigger it automatically
00930 return;
00931 }
00932
00933 EV << "Executing backoff procedure\n";
00934 int backoffrange = (backoffs>=BACKOFF_RANGE_LIMIT) ? 1024 : (1 << backoffs);
00935 int slotNumber = intuniform(0,backoffrange-1);
00936 simtime_t backofftime = slotNumber*slotTime;
00937
00938 scheduleAt(simTime()+backofftime, endBackoffMsg);
00939 transmitState = BACKOFF_STATE;
00940
00941 numBackoffs++;
00942 numBackoffsVector.record(numBackoffs);
00943 }
|
|
|
00060 {
00061 txQueue.setName("txQueue");
00062
00063 // find queueModule
00064 queueModule = NULL;
00065 if (par("queueModule").stringValue()[0])
00066 {
00067 cModule *mod = parentModule()->submodule(par("queueModule").stringValue());
00068 queueModule = check_and_cast<IPassiveQueue *>(mod);
00069 }
00070
00071 frameBeingReceived = NULL;
00072 endTxMsg = new cMessage("EndTransmission", ENDTRANSMISSION);
00073 endJammingMsg = new cMessage("EndJamming", ENDJAMMING);
00074 endRxMsg = new cMessage("EndReception", ENDRECEPTION);
00075 endIFGMsg = new cMessage("EndIFG", ENDIFG);
00076 endBackoffMsg = new cMessage("EndBackoff", ENDBACKOFF);
00077 endPauseMsg = new cMessage("EndPause", ENDPAUSE);
00078
00079 const char *addrstr = par("address");
00080 if (!strcmp(addrstr,"auto"))
00081 {
00082 // assign automatic address
00083 myaddress = MACAddress::generateAutoAddress();
00084
00085 // change module parameter from "auto" to concrete address
00086 par("address").setStringValue(myaddress.str().c_str());
00087 }
00088 else
00089 {
00090 myaddress.setAddress(addrstr);
00091 }
00092 promiscuous = par("promiscuous");
00093 txQueueLimit = par("txQueueLimit");
00094
00095 // check: datarate is forbidden with EtherMAC -- module's txrate must be used
00096 cGate *g = gate("physOut");
00097 while (g)
00098 {
00099 cSimpleChannel *chan = dynamic_cast<cSimpleChannel*>(g->channel());
00100 if (chan && chan->datarate()>0)
00101 error("connection on gate %s has data rate set: using data rate with EtherMAC "
00102 "is forbidden, module's txrate parameter must be used instead",
00103 g->fullPath().c_str());
00104 g = g->toGate();
00105 }
00106
00107 // check if connected
00108 disabled = !gate("physOut")->destinationGate()->isConnected();
00109 if (disabled)
00110 EV << "MAC not connected to a network, disabling.\n";
00111 // Note: it is currently not supported to enable a disabled MAC at runtime.
00112 // Difficulties: (1) autoconfig (2) how to pick up channel state (free, tx, collision etc)
00113 WATCH(disabled);
00114
00115 // launch autoconfig process
00116 bool performAutoconfig = true;
00117 if (!disabled && performAutoconfig)
00118 {
00119 startAutoconfig();
00120 }
00121 else
00122 {
00123 autoconfigInProgress = false;
00124 txrate = par("txrate");
00125 duplexMode = par("duplexEnabled");
00126 calculateParameters();
00127 }
00128 WATCH(autoconfigInProgress);
00129
00130 // request first frame to send
00131 if (queueModule)
00132 {
00133 EV << "Requesting first frame from queue module\n";
00134 queueModule->requestPacket();
00135 }
00136
00137 // initialize state info
00138 transmitState = TX_IDLE_STATE;
00139 receiveState = RX_IDLE_STATE;
00140 backoffs = 0;
00141 numConcurrentTransmissions = 0;
00142 framesSentInBurst = 0;
00143 bytesSentInBurst = 0;
00144 pauseUnitsRequested = 0;
00145
00146 WATCH(transmitState);
00147 WATCH(receiveState);
00148 WATCH(backoffs);
00149 WATCH(numConcurrentTransmissions);
00150 WATCH(framesSentInBurst);
00151 WATCH(bytesSentInBurst);
00152 WATCH(pauseUnitsRequested);
00153
00154 // init statistics
00155 totalCollisionTime = 0.0;
00156 totalSuccessfulRxTxTime = 0.0;
00157 numFramesSent = numFramesReceivedOK = numBytesSent = numBytesReceivedOK = 0;
00158 numFramesPassedToHL = numDroppedBitError = numDroppedNotForUs = 0;
00159 numFramesFromHL = numDroppedIfaceDown = 0;
00160 numPauseFramesRcvd = numPauseFramesSent = numCollisions = numBackoffs = 0;
00161
00162 WATCH(numFramesSent);
00163 WATCH(numFramesReceivedOK);
00164 WATCH(numBytesSent);
00165 WATCH(numBytesReceivedOK);
00166 WATCH(numFramesFromHL);
00167 WATCH(numDroppedIfaceDown);
00168 WATCH(numDroppedBitError);
00169 WATCH(numDroppedNotForUs);
00170 WATCH(numFramesPassedToHL);
00171 WATCH(numPauseFramesRcvd);
00172 WATCH(numPauseFramesSent);
00173 WATCH(numCollisions);
00174 WATCH(numBackoffs);
00175
00176 numFramesSentVector.setName("framesSent");
00177 numFramesReceivedOKVector.setName("framesReceivedOK");
00178 numBytesSentVector.setName("bytesSent");
00179 numBytesReceivedOKVector.setName("bytesReceivedOK");
00180 numDroppedIfaceDownVector.setName("framesDroppedIfaceDown");
00181 numDroppedBitErrorVector.setName("framesDroppedBitError");
00182 numDroppedNotForUsVector.setName("framesDroppedNotForUs");
00183 numFramesPassedToHLVector.setName("framesPassedToHL");
00184 numPauseFramesRcvdVector.setName("pauseFramesRcvd");
00185 numPauseFramesSentVector.setName("pauseFramesSent");
00186 numCollisionsVector.setName("collisions");
00187 numBackoffsVector.setName("backoffs");
00188 }
|
|
|
00191 {
00192 // Dump parameters
00193 EV << "MAC address: " << myaddress << (promiscuous ? ", promiscuous mode" : "") << endl;
00194 EV << "txrate: " << txrate << ", " << (duplexMode ? "duplex" : "half-duplex") << endl;
00195 #if 0
00196 EV << "bitTime: " << bitTime << endl;
00197 EV << "carrierExtension: " << carrierExtension << endl;
00198 EV << "frameBursting: " << frameBursting << endl;
00199 EV << "slotTime: " << slotTime << endl;
00200 EV << "interFrameGap: " << interFrameGap << endl;
00201 EV << "\n";
00202 #endif
00203 }
|
|
|
00946 {
00947 #define CASE(x) case x: EV << #x; break
00948 EV << "transmitState: ";
00949 switch (transmitState) {
00950 CASE(TX_IDLE_STATE);
00951 CASE(WAIT_IFG_STATE);
00952 CASE(TRANSMITTING_STATE);
00953 CASE(JAMMING_STATE);
00954 CASE(BACKOFF_STATE);
00955 CASE(PAUSE_STATE);
00956 }
00957 EV << ", receiveState: ";
00958 switch (receiveState) {
00959 CASE(RX_IDLE_STATE);
00960 CASE(RECEIVING_STATE);
00961 CASE(RX_COLLISION_STATE);
00962 }
00963 EV << ", backoffs: " << backoffs;
00964 EV << ", numConcurrentTransmissions: " << numConcurrentTransmissions;
00965 EV << ", queueLength: " << txQueue.length() << endl;
00966 #undef CASE
00967 }
|
|
|
00406 {
00407 // note: this method may be called during autoconfig period too, but we really
00408 // shouldn't start transmission at that time, only queue up the frame.
00409
00410 // check message kind
00411 if (frame->kind()!=ETH_FRAME && frame->kind()!=ETH_PAUSE)
00412 error("message with unexpected message kind %d arrived from higher layer", frame->kind());
00413
00414 // pause frames must be EtherPauseFrame AND kind==ETH_PAUSE
00415 ASSERT((frame->kind()==ETH_PAUSE) == (dynamic_cast<EtherPauseFrame *>(frame)!=NULL));
00416
00417 if (frame->getDest().equals(myaddress))
00418 {
00419 error("logic error: frame %s from higher layer has local MAC address as dest (%s)",
00420 frame->fullName(), frame->getDest().str().c_str());
00421 }
00422
00423 if (frame->byteLength() > MAX_ETHERNET_FRAME)
00424 error("packet from higher layer (%d bytes) exceeds maximum Ethernet frame size (%d)", frame->byteLength(), MAX_ETHERNET_FRAME);
00425
00426 // must be ETH_FRAME (or ETH_PAUSE) from upper layer
00427 bool isPauseFrame = (frame->kind()==ETH_PAUSE);
00428 if (!isPauseFrame)
00429 {
00430 numFramesFromHL++;
00431
00432 if (txQueueLimit && txQueue.length()>txQueueLimit)
00433 error("txQueue length exceeds %d -- this is probably due to "
00434 "a bogus app model generating excessive traffic "
00435 "(or if this is normal, increase txQueueLimit!)",
00436 txQueueLimit);
00437
00438 // fill in src address if not set
00439 if (frame->getSrc().isUnspecified())
00440 frame->setSrc(myaddress);
00441
00442 // store frame and possibly begin transmitting
00443 EV << "Packet " << frame << " arrived from higher layers, enqueueing\n";
00444 txQueue.insert(frame);
00445 }
00446 else
00447 {
00448 EV << "PAUSE received from higher layer\n";
00449
00450 // PAUSE frames enjoy priority -- they're transmitted before all other frames queued up
00451 if (!txQueue.empty())
00452 txQueue.insertBefore(txQueue.tail(), frame); // tail() frame is probably being transmitted
00453 else
00454 txQueue.insert(frame);
00455 }
00456
00457 if (!autoconfigInProgress && (duplexMode || receiveState==RX_IDLE_STATE) && transmitState==TX_IDLE_STATE)
00458 {
00459 EV << "No incoming carrier signals detected, frame clear to send, wait IFG first\n";
00460 scheduleEndIFGPeriod();
00461 }
00462 }
|
|
|
00466 {
00467 // msg must be ETH_FRAME, ETH_PAUSE or JAM_SIGNAL
00468 if (msg->kind()!=ETH_FRAME && msg->kind()!=ETH_PAUSE && msg->kind()!=JAM_SIGNAL)
00469 error("message with unexpected message kind %d arrived from network", msg->kind());
00470
00471 // detect cable length violation in half-duplex mode
00472 if (!duplexMode && simTime()-msg->sendingTime()>=shortestFrameDuration)
00473 error("very long frame propagation time detected, maybe cable exceeds maximum allowed length? "
00474 "(%lgs corresponds to an approx. %lgm cable)",
00475 simTime()-msg->sendingTime(),
00476 (simTime()-msg->sendingTime())*200000000.0);
00477
00478 simtime_t endRxTime = simTime() + msg->length()*bitTime;
00479
00480 if (!duplexMode && transmitState==TRANSMITTING_STATE)
00481 {
00482 // since we're halfduplex, receiveState must be RX_IDLE_STATE (asserted at top of handleMessage)
00483 if (msg->kind()==JAM_SIGNAL)
00484 error("Stray jam signal arrived while transmitting (usual cause is cable length exceeding allowed maximum)");
00485
00486 EV << "Transmission interrupted by incoming frame, handling collision\n";
00487 cancelEvent(endTxMsg);
00488
00489 EV << "Transmitting jam signal\n";
00490 sendJamSignal(); // backoff will be executed when jamming finished
00491
00492 // set receive state and schedule end of reception
00493 receiveState = RX_COLLISION_STATE;
00494 numConcurrentTransmissions++;
00495 simtime_t endJamTime = simTime()+jamDuration;
00496 scheduleAt(endRxTime<endJamTime ? endJamTime : endRxTime, endRxMsg);
00497 delete msg;
00498
00499 numCollisions++;
00500 numCollisionsVector.record(numCollisions);
00501 }
00502 else if (receiveState==RX_IDLE_STATE)
00503 {
00504 if (msg->kind()==JAM_SIGNAL)
00505 error("Stray jam signal arrived (usual cause is cable length exceeding allowed maximum)");
00506
00507 EV << "Start reception of frame\n";
00508 numConcurrentTransmissions++;
00509 if (frameBeingReceived)
00510 error("frameBeingReceived!=0 in RX_IDLE_STATE");
00511 frameBeingReceived = (EtherFrame *)msg;
00512 scheduleEndRxPeriod(msg);
00513 channelBusySince = simTime();
00514 }
00515 else if (receiveState==RECEIVING_STATE && msg->kind()!=JAM_SIGNAL && endRxMsg->arrivalTime()-simTime()<bitTime)
00516 {
00517 // With the above condition we filter out "false" collisions that may occur with
00518 // back-to-back frames. That is: when "beginning of frame" message (this one) occurs
00519 // BEFORE "end of previous frame" event (endRxMsg) -- same simulation time,
00520 // only wrong order.
00521
00522 EV << "Back-to-back frames: completing reception of current frame, starting reception of next one\n";
00523
00524 // complete reception of previous frame
00525 cancelEvent(endRxMsg);
00526 EtherFrame *frame = frameBeingReceived;
00527 frameBeingReceived = NULL;
00528 frameReceptionComplete(frame);
00529
00530 // start receiving next frame
00531 frameBeingReceived = (EtherFrame *)msg;
00532 scheduleEndRxPeriod(msg);
00533 }
00534 else // (receiveState==RECEIVING_STATE || receiveState==RX_COLLISION_STATE)
00535 {
00536 // handle overlapping receptions
00537 if (msg->kind()==JAM_SIGNAL)
00538 {
00539 if (numConcurrentTransmissions<=0)
00540 error("numConcurrentTransmissions=%d on jam arrival (stray jam?)",numConcurrentTransmissions);
00541
00542 numConcurrentTransmissions--;
00543 EV << "Jam signal received, this marks end of one transmission\n";
00544
00545 // by the time jamming ends, all transmissions will have been aborted
00546 if (numConcurrentTransmissions==0)
00547 {
00548 EV << "Last jam signal received, collision will ends when jam ends\n";
00549 cancelEvent(endRxMsg);
00550 scheduleAt(endRxTime, endRxMsg);
00551 }
00552 }
00553 else // ETH_FRAME or ETH_PAUSE
00554 {
00555 numConcurrentTransmissions++;
00556 if (endRxMsg->arrivalTime() < endRxTime)
00557 {
00558 // otherwise just wait until the end of the longest transmission
00559 EV << "Overlapping receptions -- setting collision state and extending collision period\n";
00560 cancelEvent(endRxMsg);
00561 scheduleAt(endRxTime, endRxMsg);
00562 }
00563 else
00564 {
00565 EV << "Overlapping receptions -- setting collision state\n";
00566 }
00567 }
00568
00569 // delete collided frames: arrived frame as well as the one we're currently receiving
00570 delete msg;
00571 if (receiveState==RECEIVING_STATE)
00572 {
00573 delete frameBeingReceived;
00574 frameBeingReceived = NULL;
00575
00576 numCollisions++;
00577 numCollisionsVector.record(numCollisions);
00578 }
00579
00580 // go to collision state
00581 receiveState = RX_COLLISION_STATE;
00582 }
00583 }
|
|
|
00897 {
00898 if (transmitState==TX_IDLE_STATE)
00899 {
00900 EV << "PAUSE frame received, pausing for " << pauseUnitsRequested << " time units\n";
00901 if (pauseUnits>0)
00902 scheduleEndPausePeriod(pauseUnits);
00903 }
00904 else if (transmitState==PAUSE_STATE)
00905 {
00906 EV << "PAUSE frame received, pausing for " << pauseUnitsRequested << " more time units from now\n";
00907 cancelEvent(endPauseMsg);
00908 if (pauseUnits>0)
00909 scheduleEndPausePeriod(pauseUnits);
00910 }
00911 else
00912 {
00913 // transmitter busy -- wait until it finishes with current frame (endTx)
00914 // and then it'll go to PAUSE state
00915 EV << "PAUSE frame received, storing pause request\n";
00916 pauseUnitsRequested = pauseUnits;
00917 }
00918 }
|
|
|
00859 {
00860 // bit errors
00861 if (frame->hasBitError())
00862 {
00863 numDroppedBitError++;
00864 numDroppedBitErrorVector.record(numDroppedBitError);
00865 delete frame;
00866 return;
00867 }
00868
00869 // strip preamble and SFD
00870 frame->addByteLength(-PREAMBLE_BYTES-SFD_BYTES);
00871
00872 // statistics
00873 numFramesReceivedOK++;
00874 numBytesReceivedOK += frame->byteLength();
00875 numFramesReceivedOKVector.record(numFramesReceivedOK);
00876 numBytesReceivedOKVector.record(numBytesReceivedOK);
00877
00878 // If not set to promiscuous = on, then checks if received frame contains destination MAC address
00879 // matching port's MAC address, also checks if broadcast bit is set
00880 if (!promiscuous && !frame->getDest().isBroadcast() && !frame->getDest().equals(myaddress))
00881 {
00882 EV << "Frame `" << frame->name() <<"' not destined to us, discarding\n";
00883 numDroppedNotForUs++;
00884 numDroppedNotForUsVector.record(numDroppedNotForUs);
00885 delete frame;
00886 return;
00887 }
00888
00889 numFramesPassedToHL++;
00890 numFramesPassedToHLVector.record(numFramesPassedToHL);
00891
00892 // pass up to upper layer
00893 send(frame, "upperLayerOut");
00894 }
|
|
|
Public function to query output queue size. 00078 {return txQueue.length();}
|
|
|
00810 {
00811 scheduleAt(simTime()+interFrameGap, endIFGMsg);
00812 transmitState = WAIT_IFG_STATE;
00813 }
|
|
|
00828 {
00829 // length is interpreted as 512-bit-time units
00830 double pausePeriod = pauseUnits*PAUSE_BITTIME*bitTime;
00831 scheduleAt(simTime()+pausePeriod, endPauseMsg);
00832 transmitState = PAUSE_STATE;
00833 }
|
|
|
00822 {
00823 scheduleAt(simTime()+frame->length()*bitTime, endRxMsg);
00824 receiveState = RECEIVING_STATE;
00825 }
|
|
|
00816 {
00817 scheduleAt(simTime()+frame->length()*bitTime, endTxMsg);
00818 transmitState = TRANSMITTING_STATE;
00819 }
|
|
|
00799 {
00800 cMessage *jam = new cMessage("JAM_SIGNAL", JAM_SIGNAL);
00801 jam->setByteLength(JAM_SIGNAL_BYTES);
00802 if (ev.isGUI()) updateConnectionColor(JAMMING_STATE);
00803 send(jam, "physOut");
00804
00805 scheduleAt(simTime()+jamDuration, endJammingMsg);
00806 transmitState = JAMMING_STATE;
00807 }
|
|
|
00238 {
00239 autoconfigInProgress = true;
00240 lowestTxrateSuggested = 0; // none suggested
00241 duplexVetoed = false;
00242
00243 double initialTxrate = par("txrate");
00244 bool duplexEnabled = par("duplexEnabled");
00245 txrate = 0;
00246 duplexMode = duplexEnabled;
00247 if (!duplexEnabled || initialTxrate>0)
00248 {
00249 EV << "Autoconfig: advertising our settings: " << initialTxrate/1000000 << "Mb, "
00250 << (duplexMode ? "duplex" : "half-duplex") << endl;
00251
00252 EtherAutoconfig *autoconf = new EtherAutoconfig("autoconf");
00253 if (!duplexEnabled)
00254 autoconf->setHalfDuplex(true);
00255 if (initialTxrate>0)
00256 autoconf->setTxrate(initialTxrate);
00257 send(autoconf, "physOut");
00258 }
00259 scheduleAt(simTime()+AUTOCONFIG_PERIOD, new cMessage("EndAutoconfig",ENDAUTOCONFIG));
00260 }
|
|
|
00618 {
00619 cMessage *origFrame = (cMessage *)txQueue.tail();
00620 EV << "Transmitting a copy of frame " << origFrame << endl;
00621 cMessage *frame = (cMessage *) origFrame->dup();
00622
00623 // add preamble and SFD (Starting Frame Delimiter), then send out
00624 frame->addByteLength(PREAMBLE_BYTES+SFD_BYTES);
00625 if (ev.isGUI()) updateConnectionColor(TRANSMITTING_STATE);
00626 send(frame, "physOut");
00627
00628 // update burst variables
00629 if (frameBursting)
00630 {
00631 bytesSentInBurst = frame->byteLength();
00632 framesSentInBurst++;
00633 }
00634
00635 // check for collisions (there might be an ongoing reception which we don't know about, see below)
00636 if (!duplexMode && receiveState!=RX_IDLE_STATE)
00637 {
00638 // During the IFG period the hardware cannot listen to the channel,
00639 // so it might happen that receptions have begun during the IFG,
00640 // and even collisions might be in progress.
00641 //
00642 // But we don't know of any ongoing transmission so we blindly
00643 // start transmitting, immediately collide and send a jam signal.
00644 //
00645 sendJamSignal();
00646 // numConcurrentTransmissions stays the same: +1 transmission, -1 jam
00647
00648 if (receiveState==RECEIVING_STATE)
00649 {
00650 delete frameBeingReceived;
00651 frameBeingReceived = NULL;
00652
00653 numCollisions++;
00654 numCollisionsVector.record(numCollisions);
00655 }
00656 // go to collision state
00657 receiveState = RX_COLLISION_STATE;
00658 }
00659 else
00660 {
00661 // no collision
00662 scheduleEndTxPeriod(frame);
00663
00664 // only count transmissions in totalSuccessfulRxTxTime if channel is half-duplex
00665 if (!duplexMode)
00666 channelBusySince = simTime();
00667 }
00668 }
|
|
|
01022 {
01023 const char *color;
01024 if (txState==TRANSMITTING_STATE)
01025 color = "yellow";
01026 else if (txState==JAMMING_STATE || txState==BACKOFF_STATE)
01027 color = "red";
01028 else
01029 color = "";
01030
01031 cGate *g = gate("physOut");
01032 while (g && g->type()=='O')
01033 {
01034 g->displayString().setTagArg("o",0,color);
01035 g->displayString().setTagArg("o",1, color[0] ? "3" : "1");
01036 g = g->toGate();
01037 }
01038 }
|
|
|
00970 {
00971 // icon coloring
00972 const char *color;
00973 if (receiveState==RX_COLLISION_STATE)
00974 color = "red";
00975 else if (transmitState==TRANSMITTING_STATE)
00976 color = "yellow";
00977 else if (transmitState==JAMMING_STATE)
00978 color = "red";
00979 else if (receiveState==RECEIVING_STATE)
00980 color = "#4040ff";
00981 else if (transmitState==BACKOFF_STATE)
00982 color = "white";
00983 else if (transmitState==PAUSE_STATE)
00984 color = "gray";
00985 else
00986 color = "";
00987 displayString().setTagArg("i",1,color);
00988 if (!strcmp(parentModule()->className(),"EthernetInterface"))
00989 parentModule()->displayString().setTagArg("i",1,color);
00990
00991 // connection coloring
00992 updateConnectionColor(transmitState);
00993
00994 #if 0
00995 // this code works but didn't turn out to be very useful
00996 const char *txStateName;
00997 switch (transmitState) {
00998 case TX_IDLE_STATE: txStateName="IDLE"; break;
00999 case WAIT_IFG_STATE: txStateName="WAIT_IFG"; break;
01000 case TRANSMITTING_STATE: txStateName="TX"; break;
01001 case JAMMING_STATE: txStateName="JAM"; break;
01002 case BACKOFF_STATE: txStateName="BACKOFF"; break;
01003 case PAUSE_STATE: txStateName="PAUSE"; break;
01004 default: error("wrong tx state");
01005 }
01006 const char *rxStateName;
01007 switch (receiveState) {
01008 case RX_IDLE_STATE: rxStateName="IDLE"; break;
01009 case RECEIVING_STATE: rxStateName="RX"; break;
01010 case RX_COLLISION_STATE: rxStateName="COLL"; break;
01011 default: error("wrong rx state");
01012 }
01013
01014 char buf[80];
01015 sprintf(buf, "tx:%s rx: %s\n#boff:%d #cTx:%d",
01016 txStateName, rxStateName, backoffs, numConcurrentTransmissions);
01017 displayString().setTagArg("t",0,buf);
01018 #endif
01019 }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1.4.1