00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <stdio.h>
00020 #include <string.h>
00021 #include <omnetpp.h>
00022 #include "EtherMACBase.h"
00023 #include "IPassiveQueue.h"
00024 #include "IInterfaceTable.h"
00025 #include "InterfaceTableAccess.h"
00026
00027 static const double SPEED_OF_LIGHT = 200000000.0;
00028
00029 EtherMACBase::EtherMACBase()
00030 {
00031 nb = NULL;
00032 queueModule = NULL;
00033 interfaceEntry = NULL;
00034 endTxMsg = endIFGMsg = endPauseMsg = NULL;
00035 }
00036
00037 EtherMACBase::~EtherMACBase()
00038 {
00039 cancelAndDelete(endTxMsg);
00040 cancelAndDelete(endIFGMsg);
00041 cancelAndDelete(endPauseMsg);
00042 }
00043
00044 void EtherMACBase::initialize()
00045 {
00046 physOutGate = gate("phys$o");
00047
00048 initializeFlags();
00049
00050 initializeTxrate();
00051 WATCH(txrate);
00052
00053 initializeMACAddress();
00054 initializeQueueModule();
00055 initializeNotificationBoard();
00056 initializeStatistics();
00057
00058 registerInterface(txrate);
00059
00060
00061 txQueue.setName("txQueue");
00062
00063
00064 endTxMsg = new cMessage("EndTransmission", ENDTRANSMISSION);
00065 endIFGMsg = new cMessage("EndIFG", ENDIFG);
00066 endPauseMsg = new cMessage("EndPause", ENDPAUSE);
00067
00068
00069 transmitState = TX_IDLE_STATE;
00070 receiveState = RX_IDLE_STATE;
00071 WATCH(transmitState);
00072 WATCH(receiveState);
00073
00074
00075 pauseUnitsRequested = 0;
00076 WATCH(pauseUnitsRequested);
00077
00078
00079 txQueueLimit = par("txQueueLimit");
00080 WATCH(txQueueLimit);
00081 }
00082
00083 void EtherMACBase::initializeQueueModule()
00084 {
00085 if (par("queueModule").stringValue()[0])
00086 {
00087 cModule *module = getParentModule()->getSubmodule(par("queueModule").stringValue());
00088 queueModule = check_and_cast<IPassiveQueue *>(module);
00089 EV << "Requesting first frame from queue module\n";
00090 queueModule->requestPacket();
00091 }
00092 }
00093
00094 void EtherMACBase::initializeMACAddress()
00095 {
00096 const char *addrstr = par("address");
00097
00098 if (!strcmp(addrstr,"auto"))
00099 {
00100
00101 address = MACAddress::generateAutoAddress();
00102
00103
00104 par("address").setStringValue(address.str().c_str());
00105 }
00106 else
00107 {
00108 address.setAddress(addrstr);
00109 }
00110 }
00111
00112 void EtherMACBase::initializeNotificationBoard()
00113 {
00114 hasSubscribers = false;
00115 if (interfaceEntry) {
00116 nb = NotificationBoardAccess().getIfExists();
00117 notifDetails.setInterfaceEntry(interfaceEntry);
00118 nb->subscribe(this, NF_SUBSCRIBERLIST_CHANGED);
00119 updateHasSubcribers();
00120 }
00121 }
00122
00123 void EtherMACBase::initializeFlags()
00124 {
00125
00126 connected = physOutGate->getPathEndGate()->isConnected();
00127 if (!connected)
00128 EV << "MAC not connected to a network.\n";
00129 WATCH(connected);
00130
00131
00132
00133
00134
00135 disabled = false;
00136 WATCH(disabled);
00137
00138
00139 promiscuous = par("promiscuous");
00140 WATCH(promiscuous);
00141 }
00142
00143 void EtherMACBase::initializeStatistics()
00144 {
00145 framesSentInBurst = 0;
00146 bytesSentInBurst = 0;
00147
00148 numFramesSent = numFramesReceivedOK = numBytesSent = numBytesReceivedOK = 0;
00149 numFramesPassedToHL = numDroppedBitError = numDroppedNotForUs = 0;
00150 numFramesFromHL = numDroppedIfaceDown = 0;
00151 numPauseFramesRcvd = numPauseFramesSent = 0;
00152
00153 WATCH(framesSentInBurst);
00154 WATCH(bytesSentInBurst);
00155
00156 WATCH(numFramesSent);
00157 WATCH(numFramesReceivedOK);
00158 WATCH(numBytesSent);
00159 WATCH(numBytesReceivedOK);
00160 WATCH(numFramesFromHL);
00161 WATCH(numDroppedIfaceDown);
00162 WATCH(numDroppedBitError);
00163 WATCH(numDroppedNotForUs);
00164 WATCH(numFramesPassedToHL);
00165 WATCH(numPauseFramesRcvd);
00166 WATCH(numPauseFramesSent);
00167
00168 numFramesSentVector.setName("framesSent");
00169 numFramesReceivedOKVector.setName("framesReceivedOK");
00170 numBytesSentVector.setName("bytesSent");
00171 numBytesReceivedOKVector.setName("bytesReceivedOK");
00172 numDroppedIfaceDownVector.setName("framesDroppedIfaceDown");
00173 numDroppedBitErrorVector.setName("framesDroppedBitError");
00174 numDroppedNotForUsVector.setName("framesDroppedNotForUs");
00175 numFramesPassedToHLVector.setName("framesPassedToHL");
00176 numPauseFramesRcvdVector.setName("pauseFramesRcvd");
00177 numPauseFramesSentVector.setName("pauseFramesSent");
00178 }
00179
00180 void EtherMACBase::registerInterface(double txrate)
00181 {
00182 IInterfaceTable *ift = InterfaceTableAccess().getIfExists();
00183 if (!ift)
00184 return;
00185
00186 interfaceEntry = new InterfaceEntry();
00187
00188
00189 char *interfaceName = new char[strlen(getParentModule()->getFullName())+1];
00190 char *d=interfaceName;
00191 for (const char *s=getParentModule()->getFullName(); *s; s++)
00192 if (isalnum(*s))
00193 *d++ = *s;
00194 *d = '\0';
00195
00196 interfaceEntry->setName(interfaceName);
00197 delete [] interfaceName;
00198
00199
00200 interfaceEntry->setDatarate(txrate);
00201
00202
00203 interfaceEntry->setMACAddress(address);
00204 interfaceEntry->setInterfaceToken(address.formInterfaceIdentifier());
00205
00206
00207
00208
00209
00210 interfaceEntry->setMtu(par("mtu"));
00211
00212
00213 interfaceEntry->setMulticast(true);
00214 interfaceEntry->setBroadcast(true);
00215
00216
00217 ift->addInterface(interfaceEntry, this);
00218 }
00219
00220
00221 bool EtherMACBase::checkDestinationAddress(EtherFrame *frame)
00222 {
00223
00224
00225 if (!promiscuous && !frame->getDest().isBroadcast() && !frame->getDest().equals(address))
00226 {
00227 EV << "Frame `" << frame->getName() <<"' not destined to us, discarding\n";
00228 numDroppedNotForUs++;
00229 numDroppedNotForUsVector.record(numDroppedNotForUs);
00230 delete frame;
00231
00232 return false;
00233 }
00234
00235 return true;
00236 }
00237
00238 void EtherMACBase::calculateParameters()
00239 {
00240 if (disabled || !connected)
00241 {
00242 bitTime = slotTime = interFrameGap = jamDuration = shortestFrameDuration = 0;
00243 carrierExtension = frameBursting = false;
00244 return;
00245 }
00246
00247 if (txrate != ETHERNET_TXRATE && txrate != FAST_ETHERNET_TXRATE &&
00248 txrate != GIGABIT_ETHERNET_TXRATE && txrate != FAST_GIGABIT_ETHERNET_TXRATE)
00249 {
00250 error("nonstandard transmission rate %g, must be %g, %g, %g or %g bit/sec",
00251 txrate, ETHERNET_TXRATE, FAST_ETHERNET_TXRATE, GIGABIT_ETHERNET_TXRATE, FAST_GIGABIT_ETHERNET_TXRATE);
00252 }
00253
00254 bitTime = 1/(double)txrate;
00255
00256
00257 if (txrate==ETHERNET_TXRATE || txrate==FAST_ETHERNET_TXRATE)
00258 slotTime = SLOT_TIME;
00259 else
00260 slotTime = GIGABIT_SLOT_TIME;
00261
00262
00263 frameBursting = (txrate==GIGABIT_ETHERNET_TXRATE || txrate==FAST_GIGABIT_ETHERNET_TXRATE);
00264 carrierExtension = (slotTime == GIGABIT_SLOT_TIME && !duplexMode);
00265
00266 interFrameGap = INTERFRAME_GAP_BITS/(double)txrate;
00267 jamDuration = 8*JAM_SIGNAL_BYTES*bitTime;
00268 shortestFrameDuration = carrierExtension ? GIGABIT_MIN_FRAME_WITH_EXT : MIN_ETHERNET_FRAME;
00269 }
00270
00271 void EtherMACBase::printParameters()
00272 {
00273
00274 EV << "MAC address: " << address << (promiscuous ? ", promiscuous mode" : "") << endl;
00275 EV << "txrate: " << txrate << ", " << (duplexMode ? "duplex" : "half-duplex") << endl;
00276 #if 0
00277 EV << "bitTime: " << bitTime << endl;
00278 EV << "carrierExtension: " << carrierExtension << endl;
00279 EV << "frameBursting: " << frameBursting << endl;
00280 EV << "slotTime: " << slotTime << endl;
00281 EV << "interFrameGap: " << interFrameGap << endl;
00282 EV << endl;
00283 #endif
00284 }
00285
00286 void EtherMACBase::processFrameFromUpperLayer(EtherFrame *frame)
00287 {
00288 EV << "Received frame from upper layer: " << frame << endl;
00289
00290 if (frame->getDest().equals(address))
00291 {
00292 error("logic error: frame %s from higher layer has local MAC address as dest (%s)",
00293 frame->getFullName(), frame->getDest().str().c_str());
00294 }
00295
00296 if (frame->getByteLength() > MAX_ETHERNET_FRAME)
00297 error("packet from higher layer (%d bytes) exceeds maximum Ethernet frame size (%d)", (int)(frame->getByteLength()), MAX_ETHERNET_FRAME);
00298
00299
00300 bool isPauseFrame = (dynamic_cast<EtherPauseFrame*>(frame)!=NULL);
00301 if (!isPauseFrame)
00302 {
00303 numFramesFromHL++;
00304
00305 if (txQueueLimit && txQueue.length()>txQueueLimit)
00306 error("txQueue length exceeds %d -- this is probably due to "
00307 "a bogus app model generating excessive traffic "
00308 "(or if this is normal, increase txQueueLimit!)",
00309 txQueueLimit);
00310
00311
00312 if (frame->getSrc().isUnspecified())
00313 frame->setSrc(address);
00314
00315
00316 EV << "Packet " << frame << " arrived from higher layers, enqueueing\n";
00317 txQueue.insert(frame);
00318 }
00319 else
00320 {
00321 EV << "PAUSE received from higher layer\n";
00322
00323
00324 if (!txQueue.empty())
00325 txQueue.insertBefore(txQueue.front(), frame);
00326 else
00327 txQueue.insert(frame);
00328 }
00329
00330 }
00331
00332 void EtherMACBase::processMsgFromNetwork(cPacket *frame)
00333 {
00334 EV << "Received frame from network: " << frame << endl;
00335
00336
00337 if (dynamic_cast<EtherFrame*>(frame)==NULL && dynamic_cast<EtherJam*>(frame)==NULL)
00338 error("message with unexpected message class '%s' arrived from network (name='%s')",
00339 frame->getClassName(), frame->getFullName());
00340
00341
00342 if (!duplexMode && simTime()-frame->getSendingTime()>=shortestFrameDuration)
00343 error("very long frame propagation time detected, maybe cable exceeds maximum allowed length? "
00344 "(%lgs corresponds to an approx. %lgm cable)",
00345 SIMTIME_STR(simTime() - frame->getSendingTime()),
00346 SIMTIME_STR((simTime() - frame->getSendingTime())*SPEED_OF_LIGHT));
00347 }
00348
00349 void EtherMACBase::frameReceptionComplete(EtherFrame *frame)
00350 {
00351 int pauseUnits;
00352 EtherPauseFrame *pauseFrame;
00353
00354 if ((pauseFrame=dynamic_cast<EtherPauseFrame*>(frame))!=NULL)
00355 {
00356 pauseUnits = pauseFrame->getPauseTime();
00357 delete frame;
00358 numPauseFramesRcvd++;
00359 numPauseFramesRcvdVector.record(numPauseFramesRcvd);
00360 processPauseCommand(pauseUnits);
00361 }
00362 else
00363 {
00364 processReceivedDataFrame((EtherFrame *)frame);
00365 }
00366 }
00367
00368 void EtherMACBase::processReceivedDataFrame(EtherFrame *frame)
00369 {
00370
00371 if (frame->hasBitError())
00372 {
00373 numDroppedBitError++;
00374 numDroppedBitErrorVector.record(numDroppedBitError);
00375 delete frame;
00376 return;
00377 }
00378
00379
00380 frame->addByteLength(-PREAMBLE_BYTES-SFD_BYTES);
00381
00382
00383 numFramesReceivedOK++;
00384 numBytesReceivedOK += frame->getByteLength();
00385 numFramesReceivedOKVector.record(numFramesReceivedOK);
00386 numBytesReceivedOKVector.record(numBytesReceivedOK);
00387
00388 if (!checkDestinationAddress(frame))
00389 return;
00390
00391 numFramesPassedToHL++;
00392 numFramesPassedToHLVector.record(numFramesPassedToHL);
00393
00394
00395 send(frame, "upperLayerOut");
00396 }
00397
00398 void EtherMACBase::processPauseCommand(int pauseUnits)
00399 {
00400 if (transmitState==TX_IDLE_STATE)
00401 {
00402 EV << "PAUSE frame received, pausing for " << pauseUnitsRequested << " time units\n";
00403 if (pauseUnits>0)
00404 scheduleEndPausePeriod(pauseUnits);
00405 }
00406 else if (transmitState==PAUSE_STATE)
00407 {
00408 EV << "PAUSE frame received, pausing for " << pauseUnitsRequested << " more time units from now\n";
00409 cancelEvent(endPauseMsg);
00410 if (pauseUnits>0)
00411 scheduleEndPausePeriod(pauseUnits);
00412 }
00413 else
00414 {
00415
00416
00417 EV << "PAUSE frame received, storing pause request\n";
00418 pauseUnitsRequested = pauseUnits;
00419 }
00420 }
00421
00422 void EtherMACBase::handleEndIFGPeriod()
00423 {
00424 if (transmitState!=WAIT_IFG_STATE)
00425 error("Not in WAIT_IFG_STATE at the end of IFG period");
00426
00427 if (txQueue.empty())
00428 error("End of IFG and no frame to transmit");
00429
00430
00431 cPacket *frame = (cPacket *)txQueue.front();
00432 EV << "IFG elapsed, now begin transmission of frame " << frame << endl;
00433
00434
00435 if (carrierExtension && frame->getByteLength() < GIGABIT_MIN_FRAME_WITH_EXT)
00436 {
00437 EV << "Performing carrier extension of small frame\n";
00438 frame->setByteLength(GIGABIT_MIN_FRAME_WITH_EXT);
00439 }
00440
00441
00442 if (frameBursting)
00443 {
00444 EV << "Starting frame burst\n";
00445 framesSentInBurst = 0;
00446 bytesSentInBurst = 0;
00447 }
00448 }
00449
00450 void EtherMACBase::handleEndTxPeriod()
00451 {
00452
00453 if (transmitState!=TRANSMITTING_STATE || (!duplexMode && receiveState!=RX_IDLE_STATE))
00454 error("End of transmission, and incorrect state detected");
00455
00456 if (txQueue.empty())
00457 error("Frame under transmission cannot be found");
00458
00459
00460 cPacket *frame = (cPacket *)txQueue.pop();
00461
00462 numFramesSent++;
00463 numBytesSent += frame->getByteLength();
00464 numFramesSentVector.record(numFramesSent);
00465 numBytesSentVector.record(numBytesSent);
00466
00467 if (dynamic_cast<EtherPauseFrame*>(frame)!=NULL)
00468 {
00469 numPauseFramesSent++;
00470 numPauseFramesSentVector.record(numPauseFramesSent);
00471 }
00472
00473 EV << "Transmission of " << frame << " successfully completed\n";
00474 delete frame;
00475 }
00476
00477 void EtherMACBase::handleEndPausePeriod()
00478 {
00479 if (transmitState != PAUSE_STATE)
00480 error("At end of PAUSE not in PAUSE_STATE!");
00481 EV << "Pause finished, resuming transmissions\n";
00482 beginSendFrames();
00483 }
00484
00485 void EtherMACBase::processMessageWhenNotConnected(cMessage *msg)
00486 {
00487 EV << "Interface is not connected -- dropping packet " << msg << endl;
00488 delete msg;
00489 numDroppedIfaceDown++;
00490 }
00491
00492 void EtherMACBase::processMessageWhenDisabled(cMessage *msg)
00493 {
00494 EV << "MAC is disabled -- dropping message " << msg << endl;
00495 delete msg;
00496 }
00497
00498 void EtherMACBase::scheduleEndIFGPeriod()
00499 {
00500 scheduleAt(simTime()+interFrameGap, endIFGMsg);
00501 transmitState = WAIT_IFG_STATE;
00502 }
00503
00504 void EtherMACBase::scheduleEndTxPeriod(cPacket *frame)
00505 {
00506 scheduleAt(simTime()+frame->getBitLength()*bitTime, endTxMsg);
00507 transmitState = TRANSMITTING_STATE;
00508 }
00509
00510 void EtherMACBase::scheduleEndPausePeriod(int pauseUnits)
00511 {
00512
00513 simtime_t pausePeriod = pauseUnits*PAUSE_BITTIME*bitTime;
00514 scheduleAt(simTime()+pausePeriod, endPauseMsg);
00515 transmitState = PAUSE_STATE;
00516 }
00517
00518 bool EtherMACBase::checkAndScheduleEndPausePeriod()
00519 {
00520 if (pauseUnitsRequested>0)
00521 {
00522
00523 EV << "Going to PAUSE mode for " << pauseUnitsRequested << " time units\n";
00524
00525 scheduleEndPausePeriod(pauseUnitsRequested);
00526 pauseUnitsRequested = 0;
00527 return true;
00528 }
00529
00530 return false;
00531 }
00532
00533 void EtherMACBase::beginSendFrames()
00534 {
00535 if (!txQueue.empty())
00536 {
00537
00538 EV << "Transmit next frame in output queue, after IFG period\n";
00539 scheduleEndIFGPeriod();
00540 }
00541 else
00542 {
00543 transmitState = TX_IDLE_STATE;
00544 if (queueModule)
00545 {
00546
00547 EV << "Requesting another frame from queue module\n";
00548 queueModule->requestPacket();
00549 }
00550 else
00551 {
00552
00553 EV << "No more frames to send, transmitter set to idle\n";
00554 }
00555 }
00556 }
00557
00558 void EtherMACBase::fireChangeNotification(int type, cPacket *msg)
00559 {
00560 if (nb) {
00561 notifDetails.setPacket(msg);
00562 nb->fireChangeNotification(type, ¬ifDetails);
00563 }
00564 }
00565
00566 void EtherMACBase::finish()
00567 {
00568 if (!disabled)
00569 {
00570 simtime_t t = simTime();
00571 recordScalar("simulated time", t);
00572 recordScalar("txrate (Mb)", txrate/1000000);
00573 recordScalar("full duplex", duplexMode);
00574 recordScalar("frames sent", numFramesSent);
00575 recordScalar("frames rcvd", numFramesReceivedOK);
00576 recordScalar("bytes sent", numBytesSent);
00577 recordScalar("bytes rcvd", numBytesReceivedOK);
00578 recordScalar("frames from higher layer", numFramesFromHL);
00579 recordScalar("frames from higher layer dropped (iface down)", numDroppedIfaceDown);
00580 recordScalar("frames dropped (bit error)", numDroppedBitError);
00581 recordScalar("frames dropped (not for us)", numDroppedNotForUs);
00582 recordScalar("frames passed up to HL", numFramesPassedToHL);
00583 recordScalar("PAUSE frames sent", numPauseFramesSent);
00584 recordScalar("PAUSE frames rcvd", numPauseFramesRcvd);
00585
00586 if (t>0)
00587 {
00588 recordScalar("frames/sec sent", numFramesSent/t);
00589 recordScalar("frames/sec rcvd", numFramesReceivedOK/t);
00590 recordScalar("bits/sec sent", 8*numBytesSent/t);
00591 recordScalar("bits/sec rcvd", 8*numBytesReceivedOK/t);
00592 }
00593 }
00594 }
00595
00596 void EtherMACBase::updateDisplayString()
00597 {
00598
00599 const char *color;
00600 if (receiveState==RX_COLLISION_STATE)
00601 color = "red";
00602 else if (transmitState==TRANSMITTING_STATE)
00603 color = "yellow";
00604 else if (transmitState==JAMMING_STATE)
00605 color = "red";
00606 else if (receiveState==RECEIVING_STATE)
00607 color = "#4040ff";
00608 else if (transmitState==BACKOFF_STATE)
00609 color = "white";
00610 else if (transmitState==PAUSE_STATE)
00611 color = "gray";
00612 else
00613 color = "";
00614 getDisplayString().setTagArg("i",1,color);
00615 if (!strcmp(getParentModule()->getClassName(),"EthernetInterface"))
00616 getParentModule()->getDisplayString().setTagArg("i",1,color);
00617
00618
00619 updateConnectionColor(transmitState);
00620
00621 #if 0
00622
00623 const char *txStateName;
00624 switch (transmitState) {
00625 case TX_IDLE_STATE: txStateName="IDLE"; break;
00626 case WAIT_IFG_STATE: txStateName="WAIT_IFG"; break;
00627 case TRANSMITTING_STATE: txStateName="TX"; break;
00628 case JAMMING_STATE: txStateName="JAM"; break;
00629 case BACKOFF_STATE: txStateName="BACKOFF"; break;
00630 case PAUSE_STATE: txStateName="PAUSE"; break;
00631 default: error("wrong tx state");
00632 }
00633 const char *rxStateName;
00634 switch (receiveState) {
00635 case RX_IDLE_STATE: rxStateName="IDLE"; break;
00636 case RECEIVING_STATE: rxStateName="RX"; break;
00637 case RX_COLLISION_STATE: rxStateName="COLL"; break;
00638 default: error("wrong rx state");
00639 }
00640
00641 char buf[80];
00642 sprintf(buf, "tx:%s rx: %s\n#boff:%d #cTx:%d",
00643 txStateName, rxStateName, backoffs, numConcurrentTransmissions);
00644 getDisplayString().setTagArg("t",0,buf);
00645 #endif
00646 }
00647
00648 void EtherMACBase::updateConnectionColor(int txState)
00649 {
00650 const char *color;
00651 if (txState==TRANSMITTING_STATE)
00652 color = "yellow";
00653 else if (txState==JAMMING_STATE || txState==BACKOFF_STATE)
00654 color = "red";
00655 else
00656 color = "";
00657
00658 cGate *g = physOutGate;
00659 while (g && g->getType()==cGate::OUTPUT)
00660 {
00661 g->getDisplayString().setTagArg("ls",0,color);
00662 g->getDisplayString().setTagArg("ls",1, color[0] ? "3" : "1");
00663 g = g->getNextGate();
00664 }
00665 }
00666
00667 void EtherMACBase::receiveChangeNotification(int category, const cPolymorphic *)
00668 {
00669 if (category==NF_SUBSCRIBERLIST_CHANGED)
00670 updateHasSubcribers();
00671 }
00672
00673