MACRelayUnitPP.cc

Go to the documentation of this file.
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