MACRelayUnitBase Class Reference

#include <MACRelayUnitBase.h>

Inheritance diagram for MACRelayUnitBase:

MACRelayUnitNP MACRelayUnitPP

List of all members.


Detailed Description

Implements base switching functionality of Ethernet switches. Note that neither activity() nor handleMessage() is redefined here -- active behavior (incl. queueing and performance aspects) must be addressed in subclasses.

Protected Types

typedef std::map< MACAddress,
AddressEntry, MAC_compare
AddressTable

Protected Member Functions

virtual void initialize ()
virtual void handleAndDispatchFrame (EtherFrame *frame, int inputport)
virtual void broadcastFrame (EtherFrame *frame, int inputport)
virtual void readAddressTable (const char *fileName)
virtual void updateTableWithAddress (MACAddress &address, int portno)
virtual int getPortForAddress (MACAddress &address)
virtual void printAddressTable ()
virtual void removeAgedEntriesFromTable ()
virtual void removeOldestTableEntry ()
virtual void sendPauseFrame (int portno, int pauseUnits)

Protected Attributes

int numPorts
int addressTableSize
simtime_t agingTime
AddressTable addresstable
int seqNum

Classes

struct  AddressEntry
struct  MAC_compare

Member Typedef Documentation


Member Function Documentation

void MACRelayUnitBase::initialize (  )  [protected, virtual]

Read parameters parameters.

Reimplemented in MACRelayUnitNP, and MACRelayUnitPP.

Referenced by MACRelayUnitPP::initialize(), and MACRelayUnitNP::initialize().

00065 {
00066     // number of ports
00067     numPorts = gate("lowerLayerOut",0)->size();
00068     if (gate("lowerLayerIn",0)->size()!=numPorts)
00069         error("the sizes of the lowerLayerIn[] and lowerLayerOut[] gate vectors must be the same");
00070 
00071     // other parameters
00072     addressTableSize = par("addressTableSize");
00073     addressTableSize = addressTableSize >= 0 ? addressTableSize : 0;
00074 
00075     agingTime = par("agingTime");
00076     agingTime = agingTime > 0 ? agingTime : 10;
00077 
00078     // Option to pre-read in Address Table. To turn ot off, set addressTableFile to empty string
00079     const char *addressTableFile = par("addressTableFile");
00080     if (addressTableFile && *addressTableFile)
00081         readAddressTable(addressTableFile);
00082 
00083     seqNum = 0;
00084 
00085     WATCH_MAP(addresstable);
00086 }

void MACRelayUnitBase::handleAndDispatchFrame ( EtherFrame *  frame,
int  inputport 
) [protected, virtual]

Updates address table with source address, determines output port and sends out (or broadcasts) frame on ports. Includes calls to updateTableWithAddress() and getPortForAddress().

The message pointer should not be referenced any more after this call.

Referenced by MACRelayUnitPP::processFrame(), and MACRelayUnitNP::processFrame().

00089 {
00090     // update address table
00091     updateTableWithAddress(frame->getSrc(), inputport);
00092 
00093     // handle broadcast frames first
00094     if (frame->getDest().isBroadcast())
00095     {
00096         EV << "Broadcasting broadcast frame " << frame << endl;
00097         broadcastFrame(frame, inputport);
00098         return;
00099     }
00100 
00101     // Finds output port of destination address and sends to output port
00102     // if not found then broadcasts to all other ports instead
00103     int outputport = getPortForAddress(frame->getDest());
00104     if (inputport==outputport)
00105     {
00106         EV << "Output port is same as input port, " << frame->getFullName() <<
00107               " dest " << frame->getDest() << ", discarding frame\n";
00108         delete frame;
00109         return;
00110     }
00111     if (outputport>=0)
00112     {
00113         EV << "Sending frame " << frame << " with dest address " << frame->getDest() << " to port " << outputport << endl;
00114         send(frame, "lowerLayerOut", outputport);
00115     }
00116     else
00117     {
00118         EV << "Dest address " << frame->getDest() << " unknown, broadcasting frame " << frame << endl;
00119         broadcastFrame(frame, inputport);
00120     }
00121 }

void MACRelayUnitBase::broadcastFrame ( EtherFrame *  frame,
int  inputport 
) [protected, virtual]

Utility function: sends the frame on all ports except inputport. The message pointer should not be referenced any more after this call.

Referenced by handleAndDispatchFrame().

00124 {
00125     for (int i=0; i<numPorts; ++i)
00126         if (i!=inputport)
00127             send((EtherFrame*)frame->dup(), "lowerLayerOut", i);
00128     delete frame;
00129 }

void MACRelayUnitBase::readAddressTable ( const char *  fileName  )  [protected, virtual]

Pre-reads in entries for Address Table during initialization.

Referenced by initialize().

00232 {
00233     FILE *fp = fopen(fileName, "r");
00234     if (fp == NULL)
00235         error("cannot open address table file `%s'", fileName);
00236 
00237     //  Syntax of the file goes as:
00238     //  Address in hexadecimal representation, Portno
00239     //  ffffffff    1
00240     //  ffffeed1    2
00241     //  aabcdeff    3
00242     //
00243     //  etc...
00244     //
00245     //  Each iteration of the loop reads in an entire line i.e. up to '\n' or EOF characters
00246     //  and uses strtok to extract tokens from the resulting string
00247     char *line;
00248     int lineno = 0;
00249     while ((line = fgetline(fp)) != NULL)
00250     {
00251         lineno++;
00252 
00253         // lines beginning with '#' are treated as comments
00254         if (line[0]=='#')
00255             continue;
00256 
00257         // scan in hexaddress
00258         char *hexaddress = strtok(line, " \t");
00259         // scan in port number
00260         char *portno = strtok(NULL, " \t");
00261 
00262         // empty line?
00263         if (!hexaddress)
00264             continue;
00265 
00266         // broken line?
00267         if (!portno)
00268             error("line %d invalid in address table file `%s'", lineno, fileName);
00269 
00270         // Create an entry with address and portno and insert into table
00271         AddressEntry entry;
00272         entry.insertionTime = 0;
00273         entry.portno = atoi(portno);
00274         addresstable[MACAddress(hexaddress)] = entry;
00275 
00276         // Garbage collection before next iteration
00277         delete [] line;
00278     }
00279     fclose(fp);
00280 }

void MACRelayUnitBase::updateTableWithAddress ( MACAddress address,
int  portno 
) [protected, virtual]

Enters address into table.

Referenced by handleAndDispatchFrame().

00178 {
00179     AddressTable::iterator iter;
00180 
00181     iter = addresstable.find(address);
00182     if (iter == addresstable.end())
00183     {
00184         // Observe finite table size
00185         if (addressTableSize!=0 && addresstable.size() == (unsigned int)addressTableSize)
00186         {
00187             // lazy removal of aged entries: only if table gets full (this step is not strictly needed)
00188             EV << "Making room in Address Table by throwing out aged entries.\n";
00189             removeAgedEntriesFromTable();
00190 
00191             if (addresstable.size() == (unsigned int)addressTableSize)
00192                 removeOldestTableEntry();
00193         }
00194 
00195         // Add entry to table
00196         EV << "Adding entry to Address Table: "<< address << " --> port" << portno << "\n";
00197         AddressEntry entry;
00198         entry.portno = portno;
00199         entry.insertionTime = simTime();
00200         addresstable[address] = entry;
00201     }
00202     else
00203     {
00204         // Update existing entry
00205         EV << "Updating entry in Address Table: "<< address << " --> port" << portno << "\n";
00206         AddressEntry& entry = iter->second;
00207         entry.insertionTime = simTime();
00208         entry.portno = portno;
00209     }
00210 }

int MACRelayUnitBase::getPortForAddress ( MACAddress address  )  [protected, virtual]

Returns output port for address, or -1 if unknown.

Referenced by handleAndDispatchFrame().

00213 {
00214     AddressTable::iterator iter = addresstable.find(address);
00215     if (iter == addresstable.end())
00216     {
00217         // not found
00218         return -1;
00219     }
00220     if (iter->second.insertionTime + agingTime <= simTime())
00221     {
00222         // don't use (and throw out) aged entries
00223         EV << "Ignoring and deleting aged entry: "<< iter->first << " --> port" << iter->second.portno << "\n";
00224         addresstable.erase(iter);
00225         return -1;
00226     }
00227     return iter->second.portno;
00228 }

void MACRelayUnitBase::printAddressTable (  )  [protected, virtual]

Prints contents of address table on ev.

Referenced by MACRelayUnitPP::processFrame(), and MACRelayUnitNP::processFrame().

00132 {
00133     AddressTable::iterator iter;
00134     EV << "Address Table (" << addresstable.size() << " entries):\n";
00135     for (iter = addresstable.begin(); iter!=addresstable.end(); ++iter)
00136     {
00137         EV << "  " << iter->first << " --> port" << iter->second.portno <<
00138               (iter->second.insertionTime+agingTime <= simTime() ? " (aged)" : "") << endl;
00139     }
00140 }

void MACRelayUnitBase::removeAgedEntriesFromTable (  )  [protected, virtual]

Utility function: throws out all aged entries from table.

Referenced by updateTableWithAddress().

00143 {
00144     for (AddressTable::iterator iter = addresstable.begin(); iter != addresstable.end();)
00145     {
00146         AddressTable::iterator cur = iter++; // iter will get invalidated after erase()
00147         AddressEntry& entry = cur->second;
00148         if (entry.insertionTime + agingTime <= simTime())
00149         {
00150             EV << "Removing aged entry from Address Table: " <<
00151                   cur->first << " --> port" << cur->second.portno << "\n";
00152             addresstable.erase(cur);
00153         }
00154     }
00155 }

void MACRelayUnitBase::removeOldestTableEntry (  )  [protected, virtual]

Utility function: throws out oldest (not necessarily aged) entry from table.

Referenced by updateTableWithAddress().

00158 {
00159     AddressTable::iterator oldest = addresstable.end();
00160     simtime_t oldestInsertTime = simTime()+1;
00161     for (AddressTable::iterator iter = addresstable.begin(); iter != addresstable.end(); iter++)
00162     {
00163         if (iter->second.insertionTime < oldestInsertTime)
00164         {
00165             oldest = iter;
00166             oldestInsertTime = iter->second.insertionTime;
00167         }
00168     }
00169     if (oldest != addresstable.end())
00170     {
00171         EV << "Table full, removing oldest entry: " <<
00172               oldest->first << " --> port" << oldest->second.portno << "\n";
00173         addresstable.erase(oldest);
00174     }
00175 }

void MACRelayUnitBase::sendPauseFrame ( int  portno,
int  pauseUnits 
) [protected, virtual]

Utility function (for use by subclasses) to send a flow control PAUSE frame on the given port.

Referenced by MACRelayUnitPP::handleIncomingFrame(), and MACRelayUnitNP::handleIncomingFrame().

00284 {
00285     EV << "Creating and sending PAUSE frame on port " << portno << " with duration=" << pauseUnits << " units\n";
00286 
00287     // create Ethernet frame
00288     char framename[40];
00289     sprintf(framename, "pause-%d-%d", getId(), seqNum++);
00290     EtherPauseFrame *frame = new EtherPauseFrame(framename);
00291     frame->setPauseTime(pauseUnits);
00292 
00293     frame->setByteLength(ETHER_MAC_FRAME_BYTES+ETHER_PAUSE_COMMAND_BYTES);
00294     if (frame->getByteLength() < MIN_ETHERNET_FRAME)
00295         frame->setByteLength(MIN_ETHERNET_FRAME);
00296 
00297     send(frame, "lowerLayerOut", portno);
00298 }


Member Data Documentation

int MACRelayUnitBase::numPorts [protected]

simtime_t MACRelayUnitBase::agingTime [protected]

int MACRelayUnitBase::seqNum [protected]

Referenced by initialize(), and sendPauseFrame().


The documentation for this class was generated from the following files:

Generated on Fri Mar 20 18:51:20 2009 for INET Framework for OMNeT++/OMNEST by  doxygen 1.5.5