#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 }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|