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

MACRelayUnitNP.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 "MACRelayUnitNP.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( MACRelayUnitNP );
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 MACRelayUnitNP::initialize()
00054 {
00055     MACRelayUnitBase::initialize();
00056 
00057     bufferLevel.setName("buffer level");
00058     queue.setName("queue");
00059 
00060     numProcessedFrames = numDroppedFrames = 0;
00061     WATCH(numProcessedFrames);
00062     WATCH(numDroppedFrames);
00063 
00064     numCPUs = par("numCPUs");
00065 
00066     processingTime    = par("processingTime");
00067     bufferSize = par("bufferSize");
00068     highWatermark = par("highWatermark");
00069     pauseUnits = par("pauseUnits");
00070 
00071     // 1 pause unit is 512 bit times; we assume 100Mb MACs here.
00072     // We send a pause again when previous one is about to expire.
00073     pauseInterval = pauseUnits*512.0/100000.0;
00074 
00075     pauseLastSent = 0;
00076     WATCH(pauseLastSent);
00077 
00078     bufferUsed = 0;
00079     WATCH(bufferUsed);
00080 
00081     endProcEvents = new cMessage *[numCPUs];
00082     for (int i=0; i<numCPUs; i++)
00083     {
00084         char msgname[20];
00085         sprintf(msgname, "endProcessing-cpu%d", i);
00086         endProcEvents[i] = new cMessage(msgname,i);
00087     }
00088 
00089     EV << "Parameters of (" << className() << ") " << fullPath() << "\n";
00090     EV << "number of processors: " << numCPUs << "\n";
00091     EV << "processing time: " << processingTime << "\n";
00092     EV << "ports: " << numPorts << "\n";
00093     EV << "buffer size: " << bufferSize << "\n";
00094     EV << "address table size: " << addressTableSize << "\n";
00095     EV << "aging time: " << agingTime << "\n";
00096     EV << "high watermark: " << highWatermark << "\n";
00097     EV << "pause time: " << pauseUnits << "\n";
00098     EV << "\n";
00099 }
00100 
00101 void MACRelayUnitNP::handleMessage(cMessage *msg)
00102 {
00103     if (!msg->isSelfMessage())
00104     {
00105         // Frame received from MAC unit
00106         if (msg->kind()!=ETH_FRAME)
00107             error("Unknown incoming frame");
00108 
00109         handleIncomingFrame((EtherFrame *)msg);
00110     }
00111     else
00112     {
00113         // Self message signal used to indicate a frame has been finished processing
00114         processFrame(msg);
00115     }
00116 }
00117 
00118 void MACRelayUnitNP::handleIncomingFrame(EtherFrame *frame)
00119 {
00120     // If buffer not full, insert payload frame into buffer and process the frame in parallel.
00121 
00122     long length = frame->length()/8;
00123     if (length + bufferUsed < bufferSize)
00124     {
00125         bufferUsed += length;
00126 
00127         // send PAUSE if above watermark
00128         if (pauseUnits>0 && highWatermark>0 && bufferUsed>=highWatermark && pauseLastSent-simTime()>pauseInterval)
00129         {
00130             // send PAUSE on all ports
00131             for (int i=0; i<numPorts; i++)
00132                 sendPauseFrame(i, pauseUnits);
00133             pauseLastSent = simTime();
00134         }
00135 
00136         // assign frame to a free CPU (if there is one)
00137         int i;
00138         for (i=0; i<numCPUs; i++)
00139             if (!endProcEvents[i]->isScheduled())
00140                 break;
00141         if (i==numCPUs)
00142         {
00143             EV << "All CPUs busy, enqueueing incoming frame " << frame << " for later processing\n";
00144             queue.insert(frame);
00145         }
00146         else
00147         {
00148             EV << "Idle CPU-" << i << " starting processing of incoming frame " << frame << endl;
00149             cMessage *msg = endProcEvents[i];
00150             msg->encapsulate(frame);
00151             scheduleAt(simTime() + processingTime, msg);
00152         }
00153     }
00154     // Drop the frame and record the number of dropped frames
00155     else
00156     {
00157         EV << "Buffer full, dropping frame " << frame << endl;
00158         delete frame;
00159         ++numDroppedFrames;
00160     }
00161 
00162     // Record statistics of buffer usage levels
00163     bufferLevel.record(bufferUsed);
00164 }
00165 
00166 void MACRelayUnitNP::processFrame(cMessage *msg)
00167 {
00168     int cpu = msg->kind();
00169     EtherFrame *frame = (EtherFrame *) msg->decapsulate();
00170     long length = frame->length()/8;
00171     int inputport = frame->arrivalGate()->index();
00172 
00173     EV << "CPU-" << cpu << " completed processing of frame " << frame << endl;
00174 
00175     handleAndDispatchFrame(frame, inputport);
00176     printAddressTable();
00177 
00178     bufferUsed -= length;
00179     bufferLevel.record(bufferUsed);
00180 
00181     numProcessedFrames++;
00182 
00183     // Process next frame in queue if they are pending
00184     if (!queue.empty())
00185     {
00186         EtherFrame *newframe = (EtherFrame *) queue.pop();
00187         msg->encapsulate(newframe);
00188         EV << "CPU-" << cpu << " starting processing of frame " << newframe << endl;
00189         scheduleAt(simTime()+processingTime, msg);
00190     }
00191     else
00192     {
00193         EV << "CPU-" << cpu << " idle\n";
00194     }
00195 }
00196 
00197 void MACRelayUnitNP::finish()
00198 {
00199     if (par("writeScalars").boolValue())
00200     {
00201         recordScalar("processed frames", numProcessedFrames);
00202         recordScalar("dropped frames", numDroppedFrames);
00203     }
00204 }
00205 

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