Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

MACRelayUnitPP.cc

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2003 CTIE, Monash University
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU 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 General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 #ifdef _MSC_VER
00020 #pragma warning(disable:4786)
00021 #endif
00022 
00023 
00024 #include "MACRelayUnitPP.h"
00025 
00026 #include "EtherFrame_m.h"
00027 #include "utils.h"
00028 #include "Ethernet.h"
00029 #include "MACAddress.h"
00030 
00031 
00032 
00033 Define_Module( MACRelayUnitPP );
00034 
00035 
00036 
00037 #ifndef OPP3
00038 static cEnvir& operator<< (cEnvir& ev, const MACAddress& addr)
00039 {
00040     char buf[20];
00041     EV << addr.toHexString(buf);
00042     return ev;
00043 }
00044 #endif
00045 
00046 static cEnvir& operator<< (cEnvir& ev, cMessage *msg)
00047 {
00048     ev.printf("(%s)%s",msg->className(),msg->fullName());
00049     return ev;
00050 }
00051 
00052 
00053 void MACRelayUnitPP::initialize()
00054 {
00055     MACRelayUnitBase::initialize();
00056 
00057     bufferLevel.setName("buffer level");
00058 
00059     numProcessedFrames = numDroppedFrames = 0;
00060     WATCH(numProcessedFrames);
00061     WATCH(numDroppedFrames);
00062 
00063     processingTime = par("processingTime");
00064     bufferSize = par("bufferSize");
00065     highWatermark = par("highWatermark");
00066     pauseUnits = par("pauseUnits");
00067 
00068     // 1 pause unit is 512 bit times; we assume 100Mb MACs here.
00069     // We send a pause again when previous one is about to expire.
00070     pauseInterval = pauseUnits*512.0/100000.0;
00071 
00072     pauseLastSent = 0;
00073     WATCH(pauseLastSent);
00074 
00075     bufferUsed = 0;
00076     WATCH(bufferUsed);
00077 
00078     buffer = new PortBuffer[numPorts];
00079     for (int i = 0; i < numPorts; ++i)
00080     {
00081         buffer[i].port = i;
00082         buffer[i].cpuBusy = false;
00083 
00084         char qname[20];
00085         sprintf(qname,"portQueue%d",i);
00086         buffer[i].queue.setName(qname);
00087     }
00088 
00089     EV << "Parameters of (" << className() << ") " << fullPath() << "\n";
00090     EV << "processing time: " << processingTime << "\n";
00091     EV << "ports: " << numPorts << "\n";
00092     EV << "buffer size: " << bufferSize << "\n";
00093     EV << "address table size: " << addressTableSize << "\n";
00094     EV << "aging time: " << agingTime << "\n";
00095     EV << "high watermark: " << highWatermark << "\n";
00096     EV << "pause time: " << pauseUnits << "\n";
00097     EV << "\n";
00098 }
00099 
00100 void MACRelayUnitPP::handleMessage(cMessage *msg)
00101 {
00102     if (!msg->isSelfMessage())
00103     {
00104         // Frame received from MAC unit
00105         if (msg->kind()!=ETH_FRAME)
00106             error("Unknown incoming frame");
00107 
00108         handleIncomingFrame((EtherFrame *)msg);
00109     }
00110     else
00111     {
00112         // Self message signal used to indicate a frame has been finished processing
00113         processFrame(msg);
00114     }
00115 }
00116 
00117 void MACRelayUnitPP::handleIncomingFrame(EtherFrame *frame)
00118 {
00119     // If buffer not full, insert payload frame into buffer and process the frame in parallel.
00120 
00121     long length = frame->length()/8;
00122     if (length + bufferUsed < bufferSize)
00123     {
00124         int inputport = frame->arrivalGate()->index();
00125         buffer[inputport].queue.insert(frame);
00126         buffer[inputport].port = inputport;
00127         bufferUsed += length;
00128 
00129         // send PAUSE if above watermark
00130         if (pauseUnits>0 && highWatermark>0 && bufferUsed>=highWatermark && pauseLastSent-simTime()>pauseInterval)
00131         {
00132             // send PAUSE on all ports
00133             for (int i=0; i<numPorts; i++)
00134                 sendPauseFrame(i, pauseUnits);
00135             pauseLastSent = simTime();
00136         }
00137 
00138         if (buffer[inputport].cpuBusy)
00139         {
00140             EV << "Port CPU " << inputport << " busy, incoming frame " << frame << " enqueued for later processing\n";
00141         }
00142         else
00143         {
00144             EV << "Port CPU " << inputport << " free, begin processing of incoming frame " << frame << endl;
00145             buffer[inputport].cpuBusy = true;
00146             cMessage *msg = new cMessage("endProcessing");
00147             msg->setContextPointer(&buffer[inputport]);
00148             scheduleAt(simTime() + processingTime, msg);
00149         }
00150     }
00151     // Drop the frame and record the number of dropped frames
00152     else
00153     {
00154         EV << "Buffer full, dropping frame " << frame << endl;
00155         delete frame;
00156         ++numDroppedFrames;
00157     }
00158 
00159     // Record statistics of buffer usage levels
00160     bufferLevel.record(bufferUsed);
00161 }
00162 
00163 void MACRelayUnitPP::processFrame(cMessage *msg)
00164 {
00165     // Extract frame from the appropriate buffer;
00166     PortBuffer *pBuff = (PortBuffer*)msg->contextPointer();
00167     EtherFrame *frame = (EtherFrame*)pBuff->queue.pop();
00168     long length = frame->length()/8;
00169     int inputport = pBuff->port;
00170 
00171     EV << "Port CPU " << inputport << " completed processing of frame " << frame << endl;
00172 
00173     handleAndDispatchFrame(frame, inputport);
00174     printAddressTable();
00175 
00176     bufferUsed -= length;
00177     bufferLevel.record(bufferUsed);
00178 
00179     numProcessedFrames++;
00180 
00181     // Process next frame in queue if they are pending
00182     if (!pBuff->queue.empty())
00183     {
00184         EV << "Begin processing of next frame\n";
00185         scheduleAt(simTime()+processingTime, msg);
00186     }
00187     else
00188     {
00189         EV << "Port CPU idle\n";
00190         pBuff->cpuBusy = false;
00191         delete msg;
00192     }
00193 }
00194 
00195 void MACRelayUnitPP::finish()
00196 {
00197     if (par("writeScalars").boolValue())
00198     {
00199         recordScalar("processed frames", numProcessedFrames);
00200         recordScalar("dropped frames", numDroppedFrames);
00201     }
00202 }
00203 

Generated on Sat May 15 20:30:43 2004 for Ethernet by doxygen1.2.17