#include <MACRelayUnitNP.h>
Inheritance diagram for MACRelayUnitNP:

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