INET Framework for OMNeT++/OMNEST
MACRelayUnitBase Class Reference

#include <MACRelayUnitBase.h>

Inheritance diagram for MACRelayUnitBase:
MACRelayUnitNP MACRelayUnitPP

List of all members.

Classes

struct  AddressEntry
struct  MAC_compare

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

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.


Member Typedef Documentation


Member Function Documentation

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().

{
    for (int i=0; i<numPorts; ++i)
        if (i!=inputport)
            send((EtherFrame*)frame->dup(), "lowerLayerOut", i);
    delete frame;
}
int MACRelayUnitBase::getPortForAddress ( MACAddress address) [protected, virtual]

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

Referenced by handleAndDispatchFrame().

{
    AddressTable::iterator iter = addresstable.find(address);
    if (iter == addresstable.end())
    {
        // not found
        return -1;
    }
    if (iter->second.insertionTime + agingTime <= simTime())
    {
        // don't use (and throw out) aged entries
        EV << "Ignoring and deleting aged entry: "<< iter->first << " --> port" << iter->second.portno << "\n";
        addresstable.erase(iter);
        return -1;
    }
    return iter->second.portno;
}
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().

{
    // update address table
    updateTableWithAddress(frame->getSrc(), inputport);

    // handle broadcast frames first
    if (frame->getDest().isBroadcast())
    {
        EV << "Broadcasting broadcast frame " << frame << endl;
        broadcastFrame(frame, inputport);
        return;
    }

    // Finds output port of destination address and sends to output port
    // if not found then broadcasts to all other ports instead
    int outputport = getPortForAddress(frame->getDest());
    if (inputport==outputport)
    {
        EV << "Output port is same as input port, " << frame->getFullName() <<
              " dest " << frame->getDest() << ", discarding frame\n";
        delete frame;
        return;
    }
    if (outputport>=0)
    {
        EV << "Sending frame " << frame << " with dest address " << frame->getDest() << " to port " << outputport << endl;
        send(frame, "lowerLayerOut", outputport);
    }
    else
    {
        EV << "Dest address " << frame->getDest() << " unknown, broadcasting frame " << frame << endl;
        broadcastFrame(frame, inputport);
    }
}
void MACRelayUnitBase::initialize ( ) [protected, virtual]

Read parameters parameters.

Reimplemented in MACRelayUnitNP, and MACRelayUnitPP.

{
    // number of ports
    numPorts = gate("lowerLayerOut",0)->size();
    if (gate("lowerLayerIn",0)->size()!=numPorts)
        error("the sizes of the lowerLayerIn[] and lowerLayerOut[] gate vectors must be the same");

    // other parameters
    addressTableSize = par("addressTableSize");
    addressTableSize = addressTableSize >= 0 ? addressTableSize : 0;

    agingTime = par("agingTime");
    agingTime = agingTime > 0 ? agingTime : 10;

    // Option to pre-read in Address Table. To turn ot off, set addressTableFile to empty string
    const char *addressTableFile = par("addressTableFile");
    if (addressTableFile && *addressTableFile)
        readAddressTable(addressTableFile);

    seqNum = 0;

    WATCH_MAP(addresstable);
}
void MACRelayUnitBase::printAddressTable ( ) [protected, virtual]

Prints contents of address table on ev.

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

{
    AddressTable::iterator iter;
    EV << "Address Table (" << addresstable.size() << " entries):\n";
    for (iter = addresstable.begin(); iter!=addresstable.end(); ++iter)
    {
        EV << "  " << iter->first << " --> port" << iter->second.portno <<
              (iter->second.insertionTime+agingTime <= simTime() ? " (aged)" : "") << endl;
    }
}
void MACRelayUnitBase::readAddressTable ( const char *  fileName) [protected, virtual]

Pre-reads in entries for Address Table during initialization.

Referenced by initialize().

{
    FILE *fp = fopen(fileName, "r");
    if (fp == NULL)
        error("cannot open address table file `%s'", fileName);

    //  Syntax of the file goes as:
    //  Address in hexadecimal representation, Portno
    //  ffffffff    1
    //  ffffeed1    2
    //  aabcdeff    3
    //
    //  etc...
    //
    //  Each iteration of the loop reads in an entire line i.e. up to '\n' or EOF characters
    //  and uses strtok to extract tokens from the resulting string
    char *line;
    int lineno = 0;
    while ((line = fgetline(fp)) != NULL)
    {
        lineno++;

        // lines beginning with '#' are treated as comments
        if (line[0]=='#')
            continue;

        // scan in hexaddress
        char *hexaddress = strtok(line, " \t");
        // scan in port number
        char *portno = strtok(NULL, " \t");

        // empty line?
        if (!hexaddress)
            continue;

        // broken line?
        if (!portno)
            error("line %d invalid in address table file `%s'", lineno, fileName);

        // Create an entry with address and portno and insert into table
        AddressEntry entry;
        entry.insertionTime = 0;
        entry.portno = atoi(portno);
        addresstable[MACAddress(hexaddress)] = entry;

        // Garbage collection before next iteration
        delete [] line;
    }
    fclose(fp);
}
void MACRelayUnitBase::removeAgedEntriesFromTable ( ) [protected, virtual]

Utility function: throws out all aged entries from table.

Referenced by updateTableWithAddress().

{
    for (AddressTable::iterator iter = addresstable.begin(); iter != addresstable.end();)
    {
        AddressTable::iterator cur = iter++; // iter will get invalidated after erase()
        AddressEntry& entry = cur->second;
        if (entry.insertionTime + agingTime <= simTime())
        {
            EV << "Removing aged entry from Address Table: " <<
                  cur->first << " --> port" << cur->second.portno << "\n";
            addresstable.erase(cur);
        }
    }
}
void MACRelayUnitBase::removeOldestTableEntry ( ) [protected, virtual]

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

Referenced by updateTableWithAddress().

{
    AddressTable::iterator oldest = addresstable.end();
    simtime_t oldestInsertTime = simTime()+1;
    for (AddressTable::iterator iter = addresstable.begin(); iter != addresstable.end(); iter++)
    {
        if (iter->second.insertionTime < oldestInsertTime)
        {
            oldest = iter;
            oldestInsertTime = iter->second.insertionTime;
        }
    }
    if (oldest != addresstable.end())
    {
        EV << "Table full, removing oldest entry: " <<
              oldest->first << " --> port" << oldest->second.portno << "\n";
        addresstable.erase(oldest);
    }
}
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().

{
    EV << "Creating and sending PAUSE frame on port " << portno << " with duration=" << pauseUnits << " units\n";

    // create Ethernet frame
    char framename[40];
    sprintf(framename, "pause-%d-%d", getId(), seqNum++);
    EtherPauseFrame *frame = new EtherPauseFrame(framename);
    frame->setPauseTime(pauseUnits);

    frame->setByteLength(ETHER_MAC_FRAME_BYTES+ETHER_PAUSE_COMMAND_BYTES);
    if (frame->getByteLength() < MIN_ETHERNET_FRAME)
        frame->setByteLength(MIN_ETHERNET_FRAME);

    send(frame, "lowerLayerOut", portno);
}
void MACRelayUnitBase::updateTableWithAddress ( MACAddress address,
int  portno 
) [protected, virtual]

Enters address into table.

Referenced by handleAndDispatchFrame().

{
    AddressTable::iterator iter;

    iter = addresstable.find(address);
    if (iter == addresstable.end())
    {
        // Observe finite table size
        if (addressTableSize!=0 && addresstable.size() == (unsigned int)addressTableSize)
        {
            // lazy removal of aged entries: only if table gets full (this step is not strictly needed)
            EV << "Making room in Address Table by throwing out aged entries.\n";
            removeAgedEntriesFromTable();

            if (addresstable.size() == (unsigned int)addressTableSize)
                removeOldestTableEntry();
        }

        // Add entry to table
        EV << "Adding entry to Address Table: "<< address << " --> port" << portno << "\n";
        AddressEntry entry;
        entry.portno = portno;
        entry.insertionTime = simTime();
        addresstable[address] = entry;
    }
    else
    {
        // Update existing entry
        EV << "Updating entry in Address Table: "<< address << " --> port" << portno << "\n";
        AddressEntry& entry = iter->second;
        entry.insertionTime = simTime();
        entry.portno = portno;
    }
}

Member Data Documentation

int MACRelayUnitBase::seqNum [protected]

Referenced by initialize(), and sendPauseFrame().


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