Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

EtherMAC Class Reference

#include <EtherMAC.h>

List of all members.


Detailed Description

Ethernet MAC module.


Public Member Functions

 EtherMAC ()
virtual ~EtherMAC ()
long queueLength ()
MACAddress getMACAddress ()

Protected Member Functions

virtual void initialize ()
virtual void handleMessage (cMessage *msg)
virtual void finish ()
void updateDisplayString ()
void updateConnectionColor (int txState)

Private Member Functions

void processFrameFromUpperLayer (EtherFrame *msg)
void processMsgFromNetwork (cMessage *msg)
void handleEndIFGPeriod ()
void handleEndTxPeriod ()
void handleEndRxPeriod ()
void handleEndBackoffPeriod ()
void handleEndJammingPeriod ()
void handleEndPausePeriod ()
void startAutoconfig ()
void handleAutoconfigMessage (cMessage *msg)
void printState ()
void printParameters ()
void calculateParameters ()
void scheduleEndIFGPeriod ()
void scheduleEndTxPeriod (cMessage *)
void scheduleEndRxPeriod (cMessage *)
void scheduleEndPausePeriod (int pauseUnits)
void sendJamSignal ()
void handleRetransmission ()
void beginSendFrames ()
void frameReceptionComplete (EtherFrame *frame)
void processReceivedDataFrame (EtherFrame *frame)
void processPauseCommand (int pauseUnits)
void startFrameTransmission ()

Private Attributes

bool disabled
MACAddress myaddress
bool promiscuous
bool duplexMode
bool carrierExtension
bool frameBursting
int txQueueLimit
double txrate
double bitTime
double slotTime
double interFrameGap
double jamDuration
double shortestFrameDuration
bool autoconfigInProgress
double lowestTxrateSuggested
bool duplexVetoed
int transmitState
int receiveState
int framesSentInBurst
int bytesSentInBurst
int backoffs
int numConcurrentTransmissions
int pauseUnitsRequested
cQueue txQueue
IPassiveQueuequeueModule
EtherFrame * frameBeingReceived
cMessage * endTxMsg
cMessage * endRxMsg
cMessage * endIFGMsg
cMessage * endBackoffMsg
cMessage * endJammingMsg
cMessage * endPauseMsg
std::string oldConnColor
simtime_t totalCollisionTime
simtime_t totalSuccessfulRxTxTime
simtime_t channelBusySince
unsigned long numFramesSent
unsigned long numFramesReceivedOK
unsigned long numBytesSent
unsigned long numBytesReceivedOK
unsigned long numFramesFromHL
unsigned long numDroppedIfaceDown
unsigned long numDroppedBitError
unsigned long numDroppedNotForUs
unsigned long numFramesPassedToHL
unsigned long numPauseFramesRcvd
unsigned long numPauseFramesSent
unsigned long numCollisions
unsigned long numBackoffs
cOutVector numFramesSentVector
cOutVector numFramesReceivedOKVector
cOutVector numBytesSentVector
cOutVector numBytesReceivedOKVector
cOutVector numDroppedIfaceDownVector
cOutVector numDroppedBitErrorVector
cOutVector numDroppedNotForUsVector
cOutVector numFramesPassedToHLVector
cOutVector numPauseFramesRcvdVector
cOutVector numPauseFramesSentVector
cOutVector numCollisionsVector
cOutVector numBackoffsVector


Constructor & Destructor Documentation

EtherMAC::EtherMAC  ) 
 

00043 {
00044     frameBeingReceived = NULL;
00045     endTxMsg = endJammingMsg = endRxMsg = endIFGMsg = endBackoffMsg = endPauseMsg = NULL;
00046 }

EtherMAC::~EtherMAC  )  [virtual]
 

00049 {
00050     delete frameBeingReceived;
00051     cancelAndDelete(endTxMsg);
00052     cancelAndDelete(endJammingMsg);
00053     cancelAndDelete(endRxMsg);
00054     cancelAndDelete(endIFGMsg);
00055     cancelAndDelete(endBackoffMsg);
00056     cancelAndDelete(endPauseMsg);
00057 }


Member Function Documentation

void EtherMAC::beginSendFrames  )  [private]
 

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 }

void EtherMAC::calculateParameters  )  [private]
 

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 }

void EtherMAC::finish  )  [protected, virtual]
 

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 }

void EtherMAC::frameReceptionComplete EtherFrame *  frame  )  [private]
 

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 }

MACAddress EtherMAC::getMACAddress  )  [inline]
 

Returns MAC address

00083 {return myaddress;}

void EtherMAC::handleAutoconfigMessage cMessage *  msg  )  [private]
 

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 }

void EtherMAC::handleEndBackoffPeriod  )  [private]
 

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 }

void EtherMAC::handleEndIFGPeriod  )  [private]
 

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 }

void EtherMAC::handleEndJammingPeriod  )  [private]
 

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 }

void EtherMAC::handleEndPausePeriod  )  [private]
 

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 }

void EtherMAC::handleEndRxPeriod  )  [private]
 

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 }

void EtherMAC::handleEndTxPeriod  )  [private]
 

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 }

void EtherMAC::handleMessage cMessage *  msg  )  [protected, virtual]
 

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 }

void EtherMAC::handleRetransmission  )  [private]
 

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 }

void EtherMAC::initialize  )  [protected, virtual]
 

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 }

void EtherMAC::printParameters  )  [private]
 

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 }

void EtherMAC::printState  )  [private]
 

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 }

void EtherMAC::processFrameFromUpperLayer EtherFrame *  msg  )  [private]
 

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 }

void EtherMAC::processMsgFromNetwork cMessage *  msg  )  [private]
 

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 }

void EtherMAC::processPauseCommand int  pauseUnits  )  [private]
 

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 }

void EtherMAC::processReceivedDataFrame EtherFrame *  frame  )  [private]
 

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 }

long EtherMAC::queueLength  )  [inline]
 

Public function to query output queue size.

00078 {return txQueue.length();}

void EtherMAC::scheduleEndIFGPeriod  )  [private]
 

00810 {
00811     scheduleAt(simTime()+interFrameGap, endIFGMsg);
00812     transmitState = WAIT_IFG_STATE;
00813 }

void EtherMAC::scheduleEndPausePeriod int  pauseUnits  )  [private]
 

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 }

void EtherMAC::scheduleEndRxPeriod cMessage *   )  [private]
 

00822 {
00823     scheduleAt(simTime()+frame->length()*bitTime, endRxMsg);
00824     receiveState = RECEIVING_STATE;
00825 }

void EtherMAC::scheduleEndTxPeriod cMessage *   )  [private]
 

00816 {
00817     scheduleAt(simTime()+frame->length()*bitTime, endTxMsg);
00818     transmitState = TRANSMITTING_STATE;
00819 }

void EtherMAC::sendJamSignal  )  [private]
 

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 }

void EtherMAC::startAutoconfig  )  [private]
 

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 }

void EtherMAC::startFrameTransmission  )  [private]
 

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 }

void EtherMAC::updateConnectionColor int  txState  )  [protected]
 

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 }

void EtherMAC::updateDisplayString  )  [protected]
 

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 }


Member Data Documentation

bool EtherMAC::autoconfigInProgress [private]
 

int EtherMAC::backoffs [private]
 

double EtherMAC::bitTime [private]
 

int EtherMAC::bytesSentInBurst [private]
 

bool EtherMAC::carrierExtension [private]
 

simtime_t EtherMAC::channelBusySince [private]
 

bool EtherMAC::disabled [private]
 

bool EtherMAC::duplexMode [private]
 

bool EtherMAC::duplexVetoed [private]
 

cMessage * EtherMAC::endBackoffMsg [private]
 

cMessage * EtherMAC::endIFGMsg [private]
 

cMessage * EtherMAC::endJammingMsg [private]
 

cMessage * EtherMAC::endPauseMsg [private]
 

cMessage * EtherMAC::endRxMsg [private]
 

cMessage* EtherMAC::endTxMsg [private]
 

EtherFrame* EtherMAC::frameBeingReceived [private]
 

bool EtherMAC::frameBursting [private]
 

int EtherMAC::framesSentInBurst [private]
 

double EtherMAC::interFrameGap [private]
 

double EtherMAC::jamDuration [private]
 

double EtherMAC::lowestTxrateSuggested [private]
 

MACAddress EtherMAC::myaddress [private]
 

unsigned long EtherMAC::numBackoffs [private]
 

cOutVector EtherMAC::numBackoffsVector [private]
 

unsigned long EtherMAC::numBytesReceivedOK [private]
 

cOutVector EtherMAC::numBytesReceivedOKVector [private]
 

unsigned long EtherMAC::numBytesSent [private]
 

cOutVector EtherMAC::numBytesSentVector [private]
 

unsigned long EtherMAC::numCollisions [private]
 

cOutVector EtherMAC::numCollisionsVector [private]
 

int EtherMAC::numConcurrentTransmissions [private]
 

unsigned long EtherMAC::numDroppedBitError [private]
 

cOutVector EtherMAC::numDroppedBitErrorVector [private]
 

unsigned long EtherMAC::numDroppedIfaceDown [private]
 

cOutVector EtherMAC::numDroppedIfaceDownVector [private]
 

unsigned long EtherMAC::numDroppedNotForUs [private]
 

cOutVector EtherMAC::numDroppedNotForUsVector [private]
 

unsigned long EtherMAC::numFramesFromHL [private]
 

unsigned long EtherMAC::numFramesPassedToHL [private]
 

cOutVector EtherMAC::numFramesPassedToHLVector [private]
 

unsigned long EtherMAC::numFramesReceivedOK [private]
 

cOutVector EtherMAC::numFramesReceivedOKVector [private]
 

unsigned long EtherMAC::numFramesSent [private]
 

cOutVector EtherMAC::numFramesSentVector [private]
 

unsigned long EtherMAC::numPauseFramesRcvd [private]
 

cOutVector EtherMAC::numPauseFramesRcvdVector [private]
 

unsigned long EtherMAC::numPauseFramesSent [private]
 

cOutVector EtherMAC::numPauseFramesSentVector [private]
 

std::string EtherMAC::oldConnColor [private]
 

int EtherMAC::pauseUnitsRequested [private]
 

bool EtherMAC::promiscuous [private]
 

IPassiveQueue* EtherMAC::queueModule [private]
 

int EtherMAC::receiveState [private]
 

double EtherMAC::shortestFrameDuration [private]
 

double EtherMAC::slotTime [private]
 

simtime_t EtherMAC::totalCollisionTime [private]
 

simtime_t EtherMAC::totalSuccessfulRxTxTime [private]
 

int EtherMAC::transmitState [private]
 

cQueue EtherMAC::txQueue [private]
 

int EtherMAC::txQueueLimit [private]
 

double EtherMAC::txrate [private]
 


The documentation for this class was generated from the following files:
Generated on Sat Apr 1 20:52:22 2006 for INET Framework for OMNeT++/OMNEST by  doxygen 1.4.1