00001 // 00002 // Copyright (C) 2006 Levente Meszaros 00003 // 00004 // This program is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public License 00006 // as published by the Free Software Foundation; either version 2 00007 // of the License, or (at your option) any later version. 00008 // 00009 // This program is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU Lesser General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU Lesser General Public License 00015 // along with this program; if not, see <http://www.gnu.org/licenses/>. 00016 // 00017 00018 #include <stdio.h> 00019 #include <string.h> 00020 #include <omnetpp.h> 00021 #include "EtherMAC2.h" 00022 #include "IPassiveQueue.h" 00023 #include "NotificationBoard.h" 00024 #include "NotifierConsts.h" 00025 00026 Define_Module(EtherMAC2); 00027 00028 EtherMAC2::EtherMAC2() 00029 { 00030 } 00031 00032 void EtherMAC2::initialize() 00033 { 00034 EtherMACBase::initialize(); 00035 00036 duplexMode = true; 00037 calculateParameters(); 00038 00039 beginSendFrames(); 00040 } 00041 00042 void EtherMAC2::initializeTxrate() 00043 { 00044 // if we're connected, find the gate with transmission rate 00045 txrate = 0; 00046 00047 if (connected) 00048 { 00049 // obtain txrate from channel. As a side effect, this also asserts 00050 // that the other end is an EtherMAC2, since normal EtherMAC 00051 // insists that the connection has *no* datarate set. 00052 // if we're connected, get the gate with transmission rate 00053 cChannel *datarateChannel = physOutGate->getTransmissionChannel(); 00054 txrate = datarateChannel->par("datarate").doubleValue(); 00055 } 00056 } 00057 00058 void EtherMAC2::handleMessage(cMessage *msg) 00059 { 00060 if (!connected) 00061 processMessageWhenNotConnected(msg); 00062 else if (disabled) 00063 processMessageWhenDisabled(msg); 00064 else if (msg->isSelfMessage()) 00065 { 00066 EV << "Self-message " << msg << " received\n"; 00067 00068 if (msg == endTxMsg) 00069 handleEndTxPeriod(); 00070 else if (msg == endIFGMsg) 00071 handleEndIFGPeriod(); 00072 else if (msg == endPauseMsg) 00073 handleEndPausePeriod(); 00074 else 00075 error("Unknown self message received!"); 00076 } 00077 else 00078 { 00079 if (msg->getArrivalGate() == gate("upperLayerIn")) 00080 processFrameFromUpperLayer(check_and_cast<EtherFrame *>(msg)); 00081 else if (msg->getArrivalGate() == gate("phys$i")) 00082 processMsgFromNetwork(check_and_cast<EtherFrame *>(msg)); 00083 else 00084 error("Message received from unknown gate!"); 00085 } 00086 00087 if (ev.isGUI()) updateDisplayString(); 00088 } 00089 00090 void EtherMAC2::startFrameTransmission() 00091 { 00092 EtherFrame *origFrame = (EtherFrame *)txQueue.front(); 00093 EV << "Transmitting a copy of frame " << origFrame << endl; 00094 00095 EtherFrame *frame = (EtherFrame *) origFrame->dup(); 00096 frame->addByteLength(PREAMBLE_BYTES+SFD_BYTES); 00097 00098 if (hasSubscribers) 00099 { 00100 // fire notification 00101 notifDetails.setPacket(frame); 00102 nb->fireChangeNotification(NF_PP_TX_BEGIN, ¬ifDetails); 00103 } 00104 00105 // fill in src address if not set 00106 if (frame->getSrc().isUnspecified()) 00107 frame->setSrc(address); 00108 00109 // send 00110 EV << "Starting transmission of " << frame << endl; 00111 send(frame, physOutGate); 00112 scheduleEndTxPeriod(frame); 00113 00114 // update burst variables 00115 if (frameBursting) 00116 { 00117 bytesSentInBurst = frame->getByteLength(); 00118 framesSentInBurst++; 00119 } 00120 } 00121 00122 void EtherMAC2::processFrameFromUpperLayer(EtherFrame *frame) 00123 { 00124 EtherMACBase::processFrameFromUpperLayer(frame); 00125 00126 if (transmitState == TX_IDLE_STATE) 00127 startFrameTransmission(); 00128 } 00129 00130 void EtherMAC2::processMsgFromNetwork(cPacket *msg) 00131 { 00132 EtherMACBase::processMsgFromNetwork(msg); 00133 EtherFrame *frame = check_and_cast<EtherFrame *>(msg); 00134 00135 if (hasSubscribers) 00136 { 00137 // fire notification 00138 notifDetails.setPacket(frame); 00139 nb->fireChangeNotification(NF_PP_RX_END, ¬ifDetails); 00140 } 00141 00142 if (checkDestinationAddress(frame)) 00143 frameReceptionComplete(frame); 00144 } 00145 00146 void EtherMAC2::handleEndIFGPeriod() 00147 { 00148 EtherMACBase::handleEndIFGPeriod(); 00149 00150 startFrameTransmission(); 00151 } 00152 00153 void EtherMAC2::handleEndTxPeriod() 00154 { 00155 if (hasSubscribers) 00156 { 00157 // fire notification 00158 notifDetails.setPacket((cPacket *)txQueue.front()); 00159 nb->fireChangeNotification(NF_PP_TX_END, ¬ifDetails); 00160 } 00161 00162 if (checkAndScheduleEndPausePeriod()) 00163 return; 00164 00165 EtherMACBase::handleEndTxPeriod(); 00166 00167 beginSendFrames(); 00168 } 00169 00170 void EtherMAC2::updateHasSubcribers() 00171 { 00172 hasSubscribers = nb->hasSubscribers(NF_PP_TX_BEGIN) || 00173 nb->hasSubscribers(NF_PP_TX_END) || 00174 nb->hasSubscribers(NF_PP_RX_END); 00175 } 00176