PageRenderTime 47ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/INET-OverSim-20101019/src/linklayer/ethernet/EtherMACBase.cc

https://bitbucket.org/indigopony/omnetproject
C++ | 673 lines | 503 code | 101 blank | 69 comment | 82 complexity | 0f1966c9a8bce860830cd8bf7b7fa58f MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, GPL-2.0, Apache-2.0, JSON
  1. //
  2. // Copyright (C) 2006 Levente Meszaros
  3. // Copyright (C) 2004 Andras Varga
  4. //
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU Lesser General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU Lesser General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU Lesser General Public License
  16. // along with this program; if not, see <http://www.gnu.org/licenses/>.
  17. //
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <omnetpp.h>
  21. #include "EtherMACBase.h"
  22. #include "IPassiveQueue.h"
  23. #include "IInterfaceTable.h"
  24. #include "InterfaceTableAccess.h"
  25. static const double SPEED_OF_LIGHT = 200000000.0;
  26. EtherMACBase::EtherMACBase()
  27. {
  28. nb = NULL;
  29. queueModule = NULL;
  30. interfaceEntry = NULL;
  31. endTxMsg = endIFGMsg = endPauseMsg = NULL;
  32. }
  33. EtherMACBase::~EtherMACBase()
  34. {
  35. cancelAndDelete(endTxMsg);
  36. cancelAndDelete(endIFGMsg);
  37. cancelAndDelete(endPauseMsg);
  38. }
  39. void EtherMACBase::initialize()
  40. {
  41. physOutGate = gate("phys$o");
  42. initializeFlags();
  43. initializeTxrate();
  44. WATCH(txrate);
  45. initializeMACAddress();
  46. initializeQueueModule();
  47. initializeNotificationBoard();
  48. initializeStatistics();
  49. registerInterface(txrate); // needs MAC address
  50. // initialize queue
  51. txQueue.setName("txQueue");
  52. // initialize self messages
  53. endTxMsg = new cMessage("EndTransmission", ENDTRANSMISSION);
  54. endIFGMsg = new cMessage("EndIFG", ENDIFG);
  55. endPauseMsg = new cMessage("EndPause", ENDPAUSE);
  56. // initialize states
  57. transmitState = TX_IDLE_STATE;
  58. receiveState = RX_IDLE_STATE;
  59. WATCH(transmitState);
  60. WATCH(receiveState);
  61. // initalize pause
  62. pauseUnitsRequested = 0;
  63. WATCH(pauseUnitsRequested);
  64. // initialize queue limit
  65. txQueueLimit = par("txQueueLimit");
  66. WATCH(txQueueLimit);
  67. }
  68. void EtherMACBase::initializeQueueModule()
  69. {
  70. if (par("queueModule").stringValue()[0])
  71. {
  72. cModule *module = getParentModule()->getSubmodule(par("queueModule").stringValue());
  73. queueModule = check_and_cast<IPassiveQueue *>(module);
  74. EV << "Requesting first frame from queue module\n";
  75. queueModule->requestPacket();
  76. }
  77. }
  78. void EtherMACBase::initializeMACAddress()
  79. {
  80. const char *addrstr = par("address");
  81. if (!strcmp(addrstr,"auto"))
  82. {
  83. // assign automatic address
  84. address = MACAddress::generateAutoAddress();
  85. // change module parameter from "auto" to concrete address
  86. par("address").setStringValue(address.str().c_str());
  87. }
  88. else
  89. {
  90. address.setAddress(addrstr);
  91. }
  92. }
  93. void EtherMACBase::initializeNotificationBoard()
  94. {
  95. hasSubscribers = false;
  96. if (interfaceEntry) {
  97. nb = NotificationBoardAccess().getIfExists();
  98. notifDetails.setInterfaceEntry(interfaceEntry);
  99. nb->subscribe(this, NF_SUBSCRIBERLIST_CHANGED);
  100. updateHasSubcribers();
  101. }
  102. }
  103. void EtherMACBase::initializeFlags()
  104. {
  105. // initialize connected flag
  106. connected = physOutGate->getPathEndGate()->isConnected();
  107. if (!connected)
  108. EV << "MAC not connected to a network.\n";
  109. WATCH(connected);
  110. // TODO: this should be settable from the gui
  111. // initialize disabled flag
  112. // Note: it is currently not supported to enable a disabled MAC at runtime.
  113. // Difficulties: (1) autoconfig (2) how to pick up channel state (free, tx, collision etc)
  114. disabled = false;
  115. WATCH(disabled);
  116. // initialize promiscuous flag
  117. promiscuous = par("promiscuous");
  118. WATCH(promiscuous);
  119. }
  120. void EtherMACBase::initializeStatistics()
  121. {
  122. framesSentInBurst = 0;
  123. bytesSentInBurst = 0;
  124. numFramesSent = numFramesReceivedOK = numBytesSent = numBytesReceivedOK = 0;
  125. numFramesPassedToHL = numDroppedBitError = numDroppedNotForUs = 0;
  126. numFramesFromHL = numDroppedIfaceDown = 0;
  127. numPauseFramesRcvd = numPauseFramesSent = 0;
  128. WATCH(framesSentInBurst);
  129. WATCH(bytesSentInBurst);
  130. WATCH(numFramesSent);
  131. WATCH(numFramesReceivedOK);
  132. WATCH(numBytesSent);
  133. WATCH(numBytesReceivedOK);
  134. WATCH(numFramesFromHL);
  135. WATCH(numDroppedIfaceDown);
  136. WATCH(numDroppedBitError);
  137. WATCH(numDroppedNotForUs);
  138. WATCH(numFramesPassedToHL);
  139. WATCH(numPauseFramesRcvd);
  140. WATCH(numPauseFramesSent);
  141. numFramesSentVector.setName("framesSent");
  142. numFramesReceivedOKVector.setName("framesReceivedOK");
  143. numBytesSentVector.setName("bytesSent");
  144. numBytesReceivedOKVector.setName("bytesReceivedOK");
  145. numDroppedIfaceDownVector.setName("framesDroppedIfaceDown");
  146. numDroppedBitErrorVector.setName("framesDroppedBitError");
  147. numDroppedNotForUsVector.setName("framesDroppedNotForUs");
  148. numFramesPassedToHLVector.setName("framesPassedToHL");
  149. numPauseFramesRcvdVector.setName("pauseFramesRcvd");
  150. numPauseFramesSentVector.setName("pauseFramesSent");
  151. }
  152. void EtherMACBase::registerInterface(double txrate)
  153. {
  154. IInterfaceTable *ift = InterfaceTableAccess().getIfExists();
  155. if (!ift)
  156. return;
  157. interfaceEntry = new InterfaceEntry();
  158. // interface name: our module name without special characters ([])
  159. char *interfaceName = new char[strlen(getParentModule()->getFullName())+1];
  160. char *d=interfaceName;
  161. for (const char *s=getParentModule()->getFullName(); *s; s++)
  162. if (isalnum(*s))
  163. *d++ = *s;
  164. *d = '\0';
  165. interfaceEntry->setName(interfaceName);
  166. delete [] interfaceName;
  167. // data rate
  168. interfaceEntry->setDatarate(txrate);
  169. // generate a link-layer address to be used as interface token for IPv6
  170. interfaceEntry->setMACAddress(address);
  171. interfaceEntry->setInterfaceToken(address.formInterfaceIdentifier());
  172. //InterfaceToken token(0, simulation.getUniqueNumber(), 64);
  173. //interfaceEntry->setInterfaceToken(token);
  174. // MTU: typical values are 576 (Internet de facto), 1500 (Ethernet-friendly),
  175. // 4000 (on some point-to-point links), 4470 (Cisco routers default, FDDI compatible)
  176. interfaceEntry->setMtu(par("mtu"));
  177. // capabilities
  178. interfaceEntry->setMulticast(true);
  179. interfaceEntry->setBroadcast(true);
  180. // add
  181. ift->addInterface(interfaceEntry, this);
  182. }
  183. bool EtherMACBase::checkDestinationAddress(EtherFrame *frame)
  184. {
  185. // If not set to promiscuous = on, then checks if received frame contains destination MAC address
  186. // matching port's MAC address, also checks if broadcast bit is set
  187. if (!promiscuous && !frame->getDest().isBroadcast() && !frame->getDest().equals(address))
  188. {
  189. EV << "Frame `" << frame->getName() <<"' not destined to us, discarding\n";
  190. numDroppedNotForUs++;
  191. numDroppedNotForUsVector.record(numDroppedNotForUs);
  192. delete frame;
  193. return false;
  194. }
  195. return true;
  196. }
  197. void EtherMACBase::calculateParameters()
  198. {
  199. if (disabled || !connected)
  200. {
  201. bitTime = slotTime = interFrameGap = jamDuration = shortestFrameDuration = 0;
  202. carrierExtension = frameBursting = false;
  203. return;
  204. }
  205. if (txrate != ETHERNET_TXRATE && txrate != FAST_ETHERNET_TXRATE &&
  206. txrate != GIGABIT_ETHERNET_TXRATE && txrate != FAST_GIGABIT_ETHERNET_TXRATE)
  207. {
  208. error("nonstandard transmission rate %g, must be %g, %g, %g or %g bit/sec",
  209. txrate, ETHERNET_TXRATE, FAST_ETHERNET_TXRATE, GIGABIT_ETHERNET_TXRATE, FAST_GIGABIT_ETHERNET_TXRATE);
  210. }
  211. bitTime = 1/(double)txrate;
  212. // set slot time
  213. if (txrate==ETHERNET_TXRATE || txrate==FAST_ETHERNET_TXRATE)
  214. slotTime = SLOT_TIME;
  215. else
  216. slotTime = GIGABIT_SLOT_TIME;
  217. // only if Gigabit Ethernet
  218. frameBursting = (txrate==GIGABIT_ETHERNET_TXRATE || txrate==FAST_GIGABIT_ETHERNET_TXRATE);
  219. carrierExtension = (slotTime == GIGABIT_SLOT_TIME && !duplexMode);
  220. interFrameGap = INTERFRAME_GAP_BITS/(double)txrate;
  221. jamDuration = 8*JAM_SIGNAL_BYTES*bitTime;
  222. shortestFrameDuration = carrierExtension ? GIGABIT_MIN_FRAME_WITH_EXT : MIN_ETHERNET_FRAME;
  223. }
  224. void EtherMACBase::printParameters()
  225. {
  226. // Dump parameters
  227. EV << "MAC address: " << address << (promiscuous ? ", promiscuous mode" : "") << endl;
  228. EV << "txrate: " << txrate << ", " << (duplexMode ? "duplex" : "half-duplex") << endl;
  229. #if 0
  230. EV << "bitTime: " << bitTime << endl;
  231. EV << "carrierExtension: " << carrierExtension << endl;
  232. EV << "frameBursting: " << frameBursting << endl;
  233. EV << "slotTime: " << slotTime << endl;
  234. EV << "interFrameGap: " << interFrameGap << endl;
  235. EV << endl;
  236. #endif
  237. }
  238. void EtherMACBase::processFrameFromUpperLayer(EtherFrame *frame)
  239. {
  240. EV << "Received frame from upper layer: " << frame << endl;
  241. if (frame->getDest().equals(address))
  242. {
  243. error("logic error: frame %s from higher layer has local MAC address as dest (%s)",
  244. frame->getFullName(), frame->getDest().str().c_str());
  245. }
  246. if (frame->getByteLength() > MAX_ETHERNET_FRAME)
  247. error("packet from higher layer (%d bytes) exceeds maximum Ethernet frame size (%d)", (int)(frame->getByteLength()), MAX_ETHERNET_FRAME);
  248. // must be EtherFrame (or EtherPauseFrame) from upper layer
  249. bool isPauseFrame = (dynamic_cast<EtherPauseFrame*>(frame)!=NULL);
  250. if (!isPauseFrame)
  251. {
  252. numFramesFromHL++;
  253. if (txQueueLimit && txQueue.length()>txQueueLimit)
  254. error("txQueue length exceeds %d -- this is probably due to "
  255. "a bogus app model generating excessive traffic "
  256. "(or if this is normal, increase txQueueLimit!)",
  257. txQueueLimit);
  258. // fill in src address if not set
  259. if (frame->getSrc().isUnspecified())
  260. frame->setSrc(address);
  261. // store frame and possibly begin transmitting
  262. EV << "Packet " << frame << " arrived from higher layers, enqueueing\n";
  263. txQueue.insert(frame);
  264. }
  265. else
  266. {
  267. EV << "PAUSE received from higher layer\n";
  268. // PAUSE frames enjoy priority -- they're transmitted before all other frames queued up
  269. if (!txQueue.empty())
  270. txQueue.insertBefore(txQueue.front(), frame); // front() frame is probably being transmitted
  271. else
  272. txQueue.insert(frame);
  273. }
  274. }
  275. void EtherMACBase::processMsgFromNetwork(cPacket *frame)
  276. {
  277. EV << "Received frame from network: " << frame << endl;
  278. // frame must be EtherFrame or EtherJam
  279. if (dynamic_cast<EtherFrame*>(frame)==NULL && dynamic_cast<EtherJam*>(frame)==NULL)
  280. error("message with unexpected message class '%s' arrived from network (name='%s')",
  281. frame->getClassName(), frame->getFullName());
  282. // detect cable length violation in half-duplex mode
  283. if (!duplexMode && simTime()-frame->getSendingTime()>=shortestFrameDuration)
  284. error("very long frame propagation time detected, maybe cable exceeds maximum allowed length? "
  285. "(%lgs corresponds to an approx. %lgm cable)",
  286. SIMTIME_STR(simTime() - frame->getSendingTime()),
  287. SIMTIME_STR((simTime() - frame->getSendingTime())*SPEED_OF_LIGHT));
  288. }
  289. void EtherMACBase::frameReceptionComplete(EtherFrame *frame)
  290. {
  291. int pauseUnits;
  292. EtherPauseFrame *pauseFrame;
  293. if ((pauseFrame=dynamic_cast<EtherPauseFrame*>(frame))!=NULL)
  294. {
  295. pauseUnits = pauseFrame->getPauseTime();
  296. delete frame;
  297. numPauseFramesRcvd++;
  298. numPauseFramesRcvdVector.record(numPauseFramesRcvd);
  299. processPauseCommand(pauseUnits);
  300. }
  301. else
  302. {
  303. processReceivedDataFrame((EtherFrame *)frame);
  304. }
  305. }
  306. void EtherMACBase::processReceivedDataFrame(EtherFrame *frame)
  307. {
  308. // bit errors
  309. if (frame->hasBitError())
  310. {
  311. numDroppedBitError++;
  312. numDroppedBitErrorVector.record(numDroppedBitError);
  313. delete frame;
  314. return;
  315. }
  316. // strip preamble and SFD
  317. frame->addByteLength(-PREAMBLE_BYTES-SFD_BYTES);
  318. // statistics
  319. numFramesReceivedOK++;
  320. numBytesReceivedOK += frame->getByteLength();
  321. numFramesReceivedOKVector.record(numFramesReceivedOK);
  322. numBytesReceivedOKVector.record(numBytesReceivedOK);
  323. if (!checkDestinationAddress(frame))
  324. return;
  325. numFramesPassedToHL++;
  326. numFramesPassedToHLVector.record(numFramesPassedToHL);
  327. // pass up to upper layer
  328. send(frame, "upperLayerOut");
  329. }
  330. void EtherMACBase::processPauseCommand(int pauseUnits)
  331. {
  332. if (transmitState==TX_IDLE_STATE)
  333. {
  334. EV << "PAUSE frame received, pausing for " << pauseUnitsRequested << " time units\n";
  335. if (pauseUnits>0)
  336. scheduleEndPausePeriod(pauseUnits);
  337. }
  338. else if (transmitState==PAUSE_STATE)
  339. {
  340. EV << "PAUSE frame received, pausing for " << pauseUnitsRequested << " more time units from now\n";
  341. cancelEvent(endPauseMsg);
  342. if (pauseUnits>0)
  343. scheduleEndPausePeriod(pauseUnits);
  344. }
  345. else
  346. {
  347. // transmitter busy -- wait until it finishes with current frame (endTx)
  348. // and then it'll go to PAUSE state
  349. EV << "PAUSE frame received, storing pause request\n";
  350. pauseUnitsRequested = pauseUnits;
  351. }
  352. }
  353. void EtherMACBase::handleEndIFGPeriod()
  354. {
  355. if (transmitState!=WAIT_IFG_STATE)
  356. error("Not in WAIT_IFG_STATE at the end of IFG period");
  357. if (txQueue.empty())
  358. error("End of IFG and no frame to transmit");
  359. // End of IFG period, okay to transmit, if Rx idle OR duplexMode
  360. cPacket *frame = (cPacket *)txQueue.front();
  361. EV << "IFG elapsed, now begin transmission of frame " << frame << endl;
  362. // Perform carrier extension if in Gigabit Ethernet
  363. if (carrierExtension && frame->getByteLength() < GIGABIT_MIN_FRAME_WITH_EXT)
  364. {
  365. EV << "Performing carrier extension of small frame\n";
  366. frame->setByteLength(GIGABIT_MIN_FRAME_WITH_EXT);
  367. }
  368. // start frame burst, if enabled
  369. if (frameBursting)
  370. {
  371. EV << "Starting frame burst\n";
  372. framesSentInBurst = 0;
  373. bytesSentInBurst = 0;
  374. }
  375. }
  376. void EtherMACBase::handleEndTxPeriod()
  377. {
  378. // we only get here if transmission has finished successfully, without collision
  379. if (transmitState!=TRANSMITTING_STATE || (!duplexMode && receiveState!=RX_IDLE_STATE))
  380. error("End of transmission, and incorrect state detected");
  381. if (txQueue.empty())
  382. error("Frame under transmission cannot be found");
  383. // get frame from buffer
  384. cPacket *frame = (cPacket *)txQueue.pop();
  385. numFramesSent++;
  386. numBytesSent += frame->getByteLength();
  387. numFramesSentVector.record(numFramesSent);
  388. numBytesSentVector.record(numBytesSent);
  389. if (dynamic_cast<EtherPauseFrame*>(frame)!=NULL)
  390. {
  391. numPauseFramesSent++;
  392. numPauseFramesSentVector.record(numPauseFramesSent);
  393. }
  394. EV << "Transmission of " << frame << " successfully completed\n";
  395. delete frame;
  396. }
  397. void EtherMACBase::handleEndPausePeriod()
  398. {
  399. if (transmitState != PAUSE_STATE)
  400. error("At end of PAUSE not in PAUSE_STATE!");
  401. EV << "Pause finished, resuming transmissions\n";
  402. beginSendFrames();
  403. }
  404. void EtherMACBase::processMessageWhenNotConnected(cMessage *msg)
  405. {
  406. EV << "Interface is not connected -- dropping packet " << msg << endl;
  407. delete msg;
  408. numDroppedIfaceDown++;
  409. }
  410. void EtherMACBase::processMessageWhenDisabled(cMessage *msg)
  411. {
  412. EV << "MAC is disabled -- dropping message " << msg << endl;
  413. delete msg;
  414. }
  415. void EtherMACBase::scheduleEndIFGPeriod()
  416. {
  417. scheduleAt(simTime()+interFrameGap, endIFGMsg);
  418. transmitState = WAIT_IFG_STATE;
  419. }
  420. void EtherMACBase::scheduleEndTxPeriod(cPacket *frame)
  421. {
  422. scheduleAt(simTime()+frame->getBitLength()*bitTime, endTxMsg);
  423. transmitState = TRANSMITTING_STATE;
  424. }
  425. void EtherMACBase::scheduleEndPausePeriod(int pauseUnits)
  426. {
  427. // length is interpreted as 512-bit-time units
  428. simtime_t pausePeriod = pauseUnits*PAUSE_BITTIME*bitTime;
  429. scheduleAt(simTime()+pausePeriod, endPauseMsg);
  430. transmitState = PAUSE_STATE;
  431. }
  432. bool EtherMACBase::checkAndScheduleEndPausePeriod()
  433. {
  434. if (pauseUnitsRequested>0)
  435. {
  436. // if we received a PAUSE frame recently, go into PAUSE state
  437. EV << "Going to PAUSE mode for " << pauseUnitsRequested << " time units\n";
  438. scheduleEndPausePeriod(pauseUnitsRequested);
  439. pauseUnitsRequested = 0;
  440. return true;
  441. }
  442. return false;
  443. }
  444. void EtherMACBase::beginSendFrames()
  445. {
  446. if (!txQueue.empty())
  447. {
  448. // Other frames are queued, therefore wait IFG period and transmit next frame
  449. EV << "Transmit next frame in output queue, after IFG period\n";
  450. scheduleEndIFGPeriod();
  451. }
  452. else
  453. {
  454. transmitState = TX_IDLE_STATE;
  455. if (queueModule)
  456. {
  457. // tell queue module that we've become idle
  458. EV << "Requesting another frame from queue module\n";
  459. queueModule->requestPacket();
  460. }
  461. else
  462. {
  463. // No more frames set transmitter to idle
  464. EV << "No more frames to send, transmitter set to idle\n";
  465. }
  466. }
  467. }
  468. void EtherMACBase::fireChangeNotification(int type, cPacket *msg)
  469. {
  470. if (nb) {
  471. notifDetails.setPacket(msg);
  472. nb->fireChangeNotification(type, &notifDetails);
  473. }
  474. }
  475. void EtherMACBase::finish()
  476. {
  477. if (!disabled)
  478. {
  479. simtime_t t = simTime();
  480. recordScalar("simulated time", t);
  481. recordScalar("txrate (Mb)", txrate/1000000);
  482. recordScalar("full duplex", duplexMode);
  483. recordScalar("frames sent", numFramesSent);
  484. recordScalar("frames rcvd", numFramesReceivedOK);
  485. recordScalar("bytes sent", numBytesSent);
  486. recordScalar("bytes rcvd", numBytesReceivedOK);
  487. recordScalar("frames from higher layer", numFramesFromHL);
  488. recordScalar("frames from higher layer dropped (iface down)", numDroppedIfaceDown);
  489. recordScalar("frames dropped (bit error)", numDroppedBitError);
  490. recordScalar("frames dropped (not for us)", numDroppedNotForUs);
  491. recordScalar("frames passed up to HL", numFramesPassedToHL);
  492. recordScalar("PAUSE frames sent", numPauseFramesSent);
  493. recordScalar("PAUSE frames rcvd", numPauseFramesRcvd);
  494. if (t>0)
  495. {
  496. recordScalar("frames/sec sent", numFramesSent/t);
  497. recordScalar("frames/sec rcvd", numFramesReceivedOK/t);
  498. recordScalar("bits/sec sent", 8*numBytesSent/t);
  499. recordScalar("bits/sec rcvd", 8*numBytesReceivedOK/t);
  500. }
  501. }
  502. }
  503. void EtherMACBase::updateDisplayString()
  504. {
  505. // icon coloring
  506. const char *color;
  507. if (receiveState==RX_COLLISION_STATE)
  508. color = "red";
  509. else if (transmitState==TRANSMITTING_STATE)
  510. color = "yellow";
  511. else if (transmitState==JAMMING_STATE)
  512. color = "red";
  513. else if (receiveState==RECEIVING_STATE)
  514. color = "#4040ff";
  515. else if (transmitState==BACKOFF_STATE)
  516. color = "white";
  517. else if (transmitState==PAUSE_STATE)
  518. color = "gray";
  519. else
  520. color = "";
  521. getDisplayString().setTagArg("i",1,color);
  522. if (!strcmp(getParentModule()->getClassName(),"EthernetInterface"))
  523. getParentModule()->getDisplayString().setTagArg("i",1,color);
  524. // connection coloring
  525. updateConnectionColor(transmitState);
  526. #if 0
  527. // this code works but didn't turn out to be very useful
  528. const char *txStateName;
  529. switch (transmitState) {
  530. case TX_IDLE_STATE: txStateName="IDLE"; break;
  531. case WAIT_IFG_STATE: txStateName="WAIT_IFG"; break;
  532. case TRANSMITTING_STATE: txStateName="TX"; break;
  533. case JAMMING_STATE: txStateName="JAM"; break;
  534. case BACKOFF_STATE: txStateName="BACKOFF"; break;
  535. case PAUSE_STATE: txStateName="PAUSE"; break;
  536. default: error("wrong tx state");
  537. }
  538. const char *rxStateName;
  539. switch (receiveState) {
  540. case RX_IDLE_STATE: rxStateName="IDLE"; break;
  541. case RECEIVING_STATE: rxStateName="RX"; break;
  542. case RX_COLLISION_STATE: rxStateName="COLL"; break;
  543. default: error("wrong rx state");
  544. }
  545. char buf[80];
  546. sprintf(buf, "tx:%s rx: %s\n#boff:%d #cTx:%d",
  547. txStateName, rxStateName, backoffs, numConcurrentTransmissions);
  548. getDisplayString().setTagArg("t",0,buf);
  549. #endif
  550. }
  551. void EtherMACBase::updateConnectionColor(int txState)
  552. {
  553. const char *color;
  554. if (txState==TRANSMITTING_STATE)
  555. color = "yellow";
  556. else if (txState==JAMMING_STATE || txState==BACKOFF_STATE)
  557. color = "red";
  558. else
  559. color = "";
  560. cGate *g = physOutGate;
  561. while (g && g->getType()==cGate::OUTPUT)
  562. {
  563. g->getDisplayString().setTagArg("o",0,color);
  564. g->getDisplayString().setTagArg("o",1, color[0] ? "3" : "1");
  565. g = g->getNextGate();
  566. }
  567. }
  568. void EtherMACBase::receiveChangeNotification(int category, const cPolymorphic *)
  569. {
  570. if (category==NF_SUBSCRIBERLIST_CHANGED)
  571. updateHasSubcribers();
  572. }