|
INET Framework for OMNeT++/OMNEST
|
00001 /* 00002 * Copyright (C) 2003 Andras Varga; CTIE, Monash University, Australia 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 "MACRelayUnitPP.h" 00019 #include "EtherFrame_m.h" 00020 #include "Ethernet.h" 00021 #include "MACAddress.h" 00022 00023 00024 Define_Module( MACRelayUnitPP ); 00025 00026 00027 /* unused for now 00028 static std::ostream& operator<< (std::ostream& os, cMessage *msg) 00029 { 00030 os << "(" << msg->getClassName() << ")" << msg->getFullName(); 00031 return os; 00032 } 00033 */ 00034 00035 MACRelayUnitPP::MACRelayUnitPP() 00036 { 00037 buffer = NULL; 00038 } 00039 00040 MACRelayUnitPP::~MACRelayUnitPP() 00041 { 00042 delete [] buffer; 00043 } 00044 00045 void MACRelayUnitPP::initialize() 00046 { 00047 MACRelayUnitBase::initialize(); 00048 00049 bufferLevel.setName("buffer level"); 00050 00051 numProcessedFrames = numDroppedFrames = 0; 00052 WATCH(numProcessedFrames); 00053 WATCH(numDroppedFrames); 00054 00055 processingTime = par("processingTime"); 00056 bufferSize = par("bufferSize"); 00057 highWatermark = par("highWatermark"); 00058 pauseUnits = par("pauseUnits"); 00059 00060 // 1 pause unit is 512 bit times; we assume 100Mb MACs here. 00061 // We send a pause again when previous one is about to expire. 00062 pauseInterval = pauseUnits*512.0/100000.0; 00063 00064 pauseLastSent = 0; 00065 WATCH(pauseLastSent); 00066 00067 bufferUsed = 0; 00068 WATCH(bufferUsed); 00069 00070 buffer = new PortBuffer[numPorts]; 00071 for (int i = 0; i < numPorts; ++i) 00072 { 00073 buffer[i].port = i; 00074 buffer[i].cpuBusy = false; 00075 00076 char qname[20]; 00077 sprintf(qname,"portQueue%d",i); 00078 buffer[i].queue.setName(qname); 00079 } 00080 00081 EV << "Parameters of (" << getClassName() << ") " << getFullPath() << "\n"; 00082 EV << "processing time: " << processingTime << "\n"; 00083 EV << "ports: " << numPorts << "\n"; 00084 EV << "buffer size: " << bufferSize << "\n"; 00085 EV << "address table size: " << addressTableSize << "\n"; 00086 EV << "aging time: " << agingTime << "\n"; 00087 EV << "high watermark: " << highWatermark << "\n"; 00088 EV << "pause time: " << pauseUnits << "\n"; 00089 EV << "\n"; 00090 } 00091 00092 void MACRelayUnitPP::handleMessage(cMessage *msg) 00093 { 00094 if (!msg->isSelfMessage()) 00095 { 00096 // Frame received from MAC unit 00097 handleIncomingFrame(check_and_cast<EtherFrame *>(msg)); 00098 } 00099 else 00100 { 00101 // Self message signal used to indicate a frame has been finished processing 00102 processFrame(msg); 00103 } 00104 } 00105 00106 void MACRelayUnitPP::handleIncomingFrame(EtherFrame *frame) 00107 { 00108 // If buffer not full, insert payload frame into buffer and process the frame in parallel. 00109 00110 long length = frame->getByteLength(); 00111 if (length + bufferUsed < bufferSize) 00112 { 00113 int inputport = frame->getArrivalGate()->getIndex(); 00114 buffer[inputport].queue.insert(frame); 00115 buffer[inputport].port = inputport; 00116 bufferUsed += length; 00117 00118 // send PAUSE if above watermark 00119 if (pauseUnits>0 && highWatermark>0 && bufferUsed>=highWatermark && simTime()-pauseLastSent>pauseInterval) 00120 { 00121 // send PAUSE on all ports 00122 for (int i=0; i<numPorts; i++) 00123 sendPauseFrame(i, pauseUnits); 00124 pauseLastSent = simTime(); 00125 } 00126 00127 if (buffer[inputport].cpuBusy) 00128 { 00129 EV << "Port CPU " << inputport << " busy, incoming frame " << frame << " enqueued for later processing\n"; 00130 } 00131 else 00132 { 00133 EV << "Port CPU " << inputport << " free, begin processing of incoming frame " << frame << endl; 00134 buffer[inputport].cpuBusy = true; 00135 cMessage *msg = new cMessage("endProcessing"); 00136 msg->setContextPointer(&buffer[inputport]); 00137 scheduleAt(simTime() + processingTime, msg); 00138 } 00139 } 00140 // Drop the frame and record the number of dropped frames 00141 else 00142 { 00143 EV << "Buffer full, dropping frame " << frame << endl; 00144 delete frame; 00145 ++numDroppedFrames; 00146 } 00147 00148 // Record statistics of buffer usage levels 00149 bufferLevel.record(bufferUsed); 00150 } 00151 00152 void MACRelayUnitPP::processFrame(cMessage *msg) 00153 { 00154 // Extract frame from the appropriate buffer; 00155 PortBuffer *pBuff = (PortBuffer*)msg->getContextPointer(); 00156 EtherFrame *frame = (EtherFrame*)pBuff->queue.pop(); 00157 long length = frame->getByteLength(); 00158 int inputport = pBuff->port; 00159 00160 EV << "Port CPU " << inputport << " completed processing of frame " << frame << endl; 00161 00162 handleAndDispatchFrame(frame, inputport); 00163 printAddressTable(); 00164 00165 bufferUsed -= length; 00166 bufferLevel.record(bufferUsed); 00167 00168 numProcessedFrames++; 00169 00170 // Process next frame in queue if they are pending 00171 if (!pBuff->queue.empty()) 00172 { 00173 EV << "Begin processing of next frame\n"; 00174 scheduleAt(simTime()+processingTime, msg); 00175 } 00176 else 00177 { 00178 EV << "Port CPU idle\n"; 00179 pBuff->cpuBusy = false; 00180 delete msg; 00181 } 00182 } 00183 00184 void MACRelayUnitPP::finish() 00185 { 00186 recordScalar("processed frames", numProcessedFrames); 00187 recordScalar("dropped frames", numDroppedFrames); 00188 } 00189