INET Framework for OMNeT++/OMNEST
|
#include <InterfaceTable.h>
Represents the interface table. This object has one instance per host or router. It has methods to manage the interface table, so one can access functionality similar to the "ifconfig" command.
See the NED documentation for general overview.
This is a simple module without gates, it requires function calls to it (message handling does nothing). Methods are provided for reading and updating the interface table.
Interfaces are dynamically registered: at the start of the simulation, every L2 module adds its own InterfaceEntry to the table; after that, IPv4's IRoutingTable and IPv6's RoutingTable6 (an possibly, further L3 protocols) add protocol-specific data on each InterfaceEntry (see IPv4InterfaceData, IPv6InterfaceData, and InterfaceEntry::setIPv4Data(), InterfaceEntry::setIPv6Data())
Interfaces are represented by InterfaceEntry objects.
When interfaces need to be reliably and efficiently identified from other modules, interfaceIds should be used. They are better suited than pointers because when an interface gets removed (see deleteInterface()), it is often impossible/impractical to invalidate all pointers to it, and also because pointers are not necessarily unique (a new InterfaceEntry may get allocated exactly at the address of a previously deleted one). Interface Ids are unique (Ids of removed interfaces are not issued again), stale Ids can be detected, and they are also invariant to insertion/deletion.
Clients can get notified about interface changes by subscribing to the following notifications in NotificationBoard: NF_INTERFACE_CREATED, NF_INTERFACE_DELETED, NF_INTERFACE_STATE_CHANGED, NF_INTERFACE_CONFIG_CHANGED. State change gets fired for up/down events; all other changes fire as config change.
typedef std::vector<InterfaceEntry *> InterfaceTable::InterfaceVector [protected] |
InterfaceTable::InterfaceTable | ( | ) |
{ tmpNumInterfaces = -1; tmpInterfaceList = NULL; }
InterfaceTable::~InterfaceTable | ( | ) | [virtual] |
{ for (int i=0; i < (int)idToInterface.size(); i++) delete idToInterface[i]; delete [] tmpInterfaceList; }
void InterfaceTable::addInterface | ( | InterfaceEntry * | entry, |
cModule * | ifmod | ||
) | [virtual] |
Adds an interface. The second argument should be a module which belongs to the physical interface (e.g. PPP or EtherMac) -- it will be used to discover and fill in getNetworkLayerGateIndex(), getNodeOutputGateId(), and getNodeInputGateId() in InterfaceEntry. It should be NULL if this is a virtual interface (e.g. loopback).
Implements IInterfaceTable.
Referenced by initialize().
{ // check name is unique if (getInterfaceByName(entry->getName())!=NULL) opp_error("addInterface(): interface '%s' already registered", entry->getName()); // insert entry->setInterfaceId(INTERFACEIDS_START + idToInterface.size()); entry->setInterfaceTable(this); idToInterface.push_back(entry); invalidateTmpInterfaceList(); // fill in networkLayerGateIndex, nodeOutputGateId, nodeInputGateId if (ifmod) discoverConnectingGates(entry, ifmod); nb->fireChangeNotification(NF_INTERFACE_CREATED, entry); }
void InterfaceTable::deleteInterface | ( | InterfaceEntry * | entry | ) | [virtual] |
Deletes the given interface from the table. Indices of existing interfaces (see getInterface(int)) may change. It is an error if the given interface is not in the table.
Implements IInterfaceTable.
{ int id = entry->getInterfaceId(); if (entry != getInterfaceById(id)) opp_error("deleteInterface(): interface '%s' not found in interface table", entry->getName()); nb->fireChangeNotification(NF_INTERFACE_DELETED, entry); // actually, only going to be deleted idToInterface[id - INTERFACEIDS_START] = NULL; delete entry; invalidateTmpInterfaceList(); }
void InterfaceTable::discoverConnectingGates | ( | InterfaceEntry * | entry, |
cModule * | ifmod | ||
) | [protected, virtual] |
Referenced by addInterface().
{ // ifmod is something like "host.eth[1].mac"; climb up to find "host.eth[1]" from it cModule *host = getParentModule(); while (ifmod && ifmod->getParentModule()!=host) ifmod = ifmod->getParentModule(); if (!ifmod) opp_error("addInterface(): specified module is not in this host/router"); // find gates connected to host / network layer cGate *nwlayerInGate=NULL, *nwlayerOutGate=NULL; for (GateIterator i(ifmod); !i.end(); i++) { cGate *g = i(); if (!g) continue; // find the host/router's gates that internally connect to this interface if (g->getType()==cGate::OUTPUT && g->getNextGate() && g->getNextGate()->getOwnerModule()==host) entry->setNodeOutputGateId(g->getNextGate()->getId()); if (g->getType()==cGate::INPUT && g->getPreviousGate() && g->getPreviousGate()->getOwnerModule()==host) entry->setNodeInputGateId(g->getPreviousGate()->getId()); // find the gate index of networkLayer/networkLayer6/mpls that connects to this interface if (g->getType()==cGate::OUTPUT && g->getNextGate() && g->getNextGate()->isName("ifIn")) nwlayerInGate = g->getNextGate(); if (g->getType()==cGate::INPUT && g->getPreviousGate() && g->getPreviousGate()->isName("ifOut")) nwlayerOutGate = g->getPreviousGate(); } // consistency checks // note: we don't check nodeOutputGateId/nodeInputGateId, because wireless interfaces // are not connected to the host if (!nwlayerInGate || !nwlayerOutGate || nwlayerInGate->getIndex()!=nwlayerOutGate->getIndex()) opp_error("addInterface(): interface must be connected to network layer's ifIn[]/ifOut[] gates of the same index"); entry->setNetworkLayerGateIndex(nwlayerInGate->getIndex()); }
InterfaceEntry * InterfaceTable::getFirstLoopbackInterface | ( | ) | [virtual] |
Returns the first interface with the isLoopback flag set. (If there's no loopback, it returns NULL -- but this should never happen because InterfaceTable itself registers a loopback interface on startup.)
Implements IInterfaceTable.
{ Enter_Method_Silent(); int n = idToInterface.size(); for (int i=0; i<n; i++) if (idToInterface[i] && idToInterface[i]->isLoopback()) return idToInterface[i]; return NULL; }
virtual std::string InterfaceTable::getFullPath | ( | ) | const [inline, virtual] |
InterfaceEntry * InterfaceTable::getInterface | ( | int | pos | ) | [virtual] |
Returns the InterfaceEntry specified by an index 0..numInterfaces-1. Throws an error if index is out of range.
Note that this index is NOT the same as interfaceId! Indices are not guaranteed to stay the same after interface addition/deletion, so cannot be used to reliably identify the interface. Use interfaceId to refer to interfaces from other modules or from messages/packets.
Implements IInterfaceTable.
{ int n = getNumInterfaces(); // also fills tmpInterfaceList if (pos<0 || pos>=n) opp_error("getInterface(): interface index %d out of range 0..%d", pos, n-1); if (!tmpInterfaceList) { // collect non-NULL elements into tmpInterfaceList[] tmpInterfaceList = new InterfaceEntry *[n]; int k = 0; int maxId = idToInterface.size(); for (int i=0; i<maxId; i++) if (idToInterface[i]) tmpInterfaceList[k++] = idToInterface[i]; } return tmpInterfaceList[pos]; }
InterfaceEntry * InterfaceTable::getInterfaceById | ( | int | id | ) | [virtual] |
Returns an interface by its Id. Ids are guaranteed to be invariant to interface deletions/additions. Returns NULL if there is no such interface (This allows detecting stale IDs without raising an error.)
Implements IInterfaceTable.
Referenced by deleteInterface().
{ id -= INTERFACEIDS_START; return (id<0 || id>=(int)idToInterface.size()) ? NULL : idToInterface[id]; }
InterfaceEntry * InterfaceTable::getInterfaceByName | ( | const char * | name | ) | [virtual] |
Returns an interface given by its name. Returns NULL if not found.
Implements IInterfaceTable.
Referenced by addInterface().
{ Enter_Method_Silent(); if (!name) return NULL; int n = idToInterface.size(); for (int i=0; i<n; i++) if (idToInterface[i] && !strcmp(name, idToInterface[i]->getName())) return idToInterface[i]; return NULL; }
InterfaceEntry * InterfaceTable::getInterfaceByNetworkLayerGateIndex | ( | int | index | ) | [virtual] |
Returns an interface given by its getNetworkLayerGateIndex(). Returns NULL if not found.
Implements IInterfaceTable.
{ // linear search is OK because normally we have don't have many interfaces and this func is rarely called Enter_Method_Silent(); int n = idToInterface.size(); for (int i=0; i<n; i++) if (idToInterface[i] && idToInterface[i]->getNetworkLayerGateIndex()==index) return idToInterface[i]; return NULL; }
InterfaceEntry * InterfaceTable::getInterfaceByNodeInputGateId | ( | int | id | ) | [virtual] |
Returns an interface given by its getNodeInputGateId(). Returns NULL if not found.
Implements IInterfaceTable.
{ // linear search is OK because normally we have don't have many interfaces and this func is rarely called Enter_Method_Silent(); int n = idToInterface.size(); for (int i=0; i<n; i++) if (idToInterface[i] && idToInterface[i]->getNodeInputGateId()==id) return idToInterface[i]; return NULL; }
InterfaceEntry * InterfaceTable::getInterfaceByNodeOutputGateId | ( | int | id | ) | [virtual] |
Returns an interface given by its getNodeOutputGateId(). Returns NULL if not found.
Implements IInterfaceTable.
{ // linear search is OK because normally we have don't have many interfaces and this func is rarely called Enter_Method_Silent(); int n = idToInterface.size(); for (int i=0; i<n; i++) if (idToInterface[i] && idToInterface[i]->getNodeOutputGateId()==id) return idToInterface[i]; return NULL; }
int InterfaceTable::getNumInterfaces | ( | ) | [virtual] |
Returns the number of interfaces.
Implements IInterfaceTable.
Referenced by getInterface(), and updateDisplayString().
{ if (tmpNumInterfaces == -1) { // count non-NULL elements int n = 0; int maxId = idToInterface.size(); for (int i=0; i<maxId; i++) if (idToInterface[i]) n++; tmpNumInterfaces = n; } return tmpNumInterfaces; }
void InterfaceTable::handleMessage | ( | cMessage * | msg | ) | [protected, virtual] |
Raises an error.
{
opp_error("This module doesn't process messages");
}
void InterfaceTable::initialize | ( | int | stage | ) | [protected, virtual] |
{ if (stage==0) { // get a pointer to the NotificationBoard module nb = NotificationBoardAccess().get(); // register a loopback interface InterfaceEntry *ie = new InterfaceEntry(); ie->setName("lo0"); ie->setMtu(3924); ie->setLoopback(true); addInterface(ie, NULL); } else if (stage==1) { WATCH_PTRVECTOR(idToInterface); updateDisplayString(); } }
void InterfaceTable::interfaceChanged | ( | InterfaceEntry * | entry, |
int | category | ||
) | [protected, virtual] |
Implements IInterfaceTable.
{ nb->fireChangeNotification(category, entry); }
void InterfaceTable::invalidateTmpInterfaceList | ( | ) | [protected, virtual] |
Referenced by addInterface(), and deleteInterface().
{ tmpNumInterfaces = -1; delete[] tmpInterfaceList; tmpInterfaceList = NULL; }
virtual int InterfaceTable::numInitStages | ( | ) | const [inline, protected, virtual] |
{return 2;}
void InterfaceTable::receiveChangeNotification | ( | int | category, |
const cPolymorphic * | details | ||
) | [virtual] |
Called by the NotificationBoard whenever a change of a category occurs to which this client has subscribed.
Implements INotifiable.
{ // nothing needed here at the moment Enter_Method_Silent(); printNotificationBanner(category, details); }
void InterfaceTable::updateDisplayString | ( | ) | [protected, virtual] |
Referenced by initialize().
{ if (!ev.isGUI()) return; char buf[80]; sprintf(buf, "%d interfaces", getNumInterfaces()); getDisplayString().setTagArg("t",0,buf); }
InterfaceVector InterfaceTable::idToInterface [protected] |
NotificationBoard* InterfaceTable::nb [protected] |
Referenced by addInterface(), deleteInterface(), initialize(), and interfaceChanged().
InterfaceEntry** InterfaceTable::tmpInterfaceList [protected] |
Referenced by getInterface(), InterfaceTable(), invalidateTmpInterfaceList(), and ~InterfaceTable().
int InterfaceTable::tmpNumInterfaces [protected] |
Referenced by getNumInterfaces(), InterfaceTable(), and invalidateTmpInterfaceList().