#include <InterfaceTable.h>
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 | ( | ) |
InterfaceTable::~InterfaceTable | ( | ) | [virtual] |
00048 { 00049 for (int i=0; i < (int)idToInterface.size(); i++) 00050 delete idToInterface[i]; 00051 delete [] tmpInterfaceList; 00052 }
void InterfaceTable::updateDisplayString | ( | ) | [protected, virtual] |
Referenced by initialize().
00076 { 00077 if (!ev.isGUI()) 00078 return; 00079 00080 char buf[80]; 00081 sprintf(buf, "%d interfaces", getNumInterfaces()); 00082 getDisplayString().setTagArg("t",0,buf); 00083 }
void InterfaceTable::discoverConnectingGates | ( | InterfaceEntry * | entry, | |
cModule * | ifmod | |||
) | [protected, virtual] |
Referenced by addInterface().
00161 { 00162 // ifmod is something like "host.eth[1].mac"; climb up to find "host.eth[1]" from it 00163 cModule *host = getParentModule(); 00164 while (ifmod && ifmod->getParentModule()!=host) 00165 ifmod = ifmod->getParentModule(); 00166 if (!ifmod) 00167 opp_error("addInterface(): specified module is not in this host/router"); 00168 00169 // find gates connected to host / network layer 00170 cGate *nwlayerInGate=NULL, *nwlayerOutGate=NULL; 00171 for (GateIterator i(ifmod); !i.end(); i++) 00172 { 00173 cGate *g = i(); 00174 if (!g) continue; 00175 00176 // find the host/router's gates that internally connect to this interface 00177 if (g->getType()==cGate::OUTPUT && g->getNextGate() && g->getNextGate()->getOwnerModule()==host) 00178 entry->setNodeOutputGateId(g->getNextGate()->getId()); 00179 if (g->getType()==cGate::INPUT && g->getPreviousGate() && g->getPreviousGate()->getOwnerModule()==host) 00180 entry->setNodeInputGateId(g->getPreviousGate()->getId()); 00181 00182 // find the gate index of networkLayer/networkLayer6/mpls that connects to this interface 00183 if (g->getType()==cGate::OUTPUT && g->getNextGate() && g->getNextGate()->isName("ifIn")) 00184 nwlayerInGate = g->getNextGate(); 00185 if (g->getType()==cGate::INPUT && g->getPreviousGate() && g->getPreviousGate()->isName("ifOut")) 00186 nwlayerOutGate = g->getPreviousGate(); 00187 } 00188 00189 // consistency checks 00190 // note: we don't check nodeOutputGateId/nodeInputGateId, because wireless interfaces 00191 // are not connected to the host 00192 if (!nwlayerInGate || !nwlayerOutGate || nwlayerInGate->getIndex()!=nwlayerOutGate->getIndex()) 00193 opp_error("addInterface(): interface must be connected to network layer's ifIn[]/ifOut[] gates of the same index"); 00194 entry->setNetworkLayerGateIndex(nwlayerInGate->getIndex()); 00195 }
void InterfaceTable::interfaceChanged | ( | InterfaceEntry * | entry, | |
int | category | |||
) | [protected, virtual] |
void InterfaceTable::invalidateTmpInterfaceList | ( | ) | [protected, virtual] |
Referenced by addInterface(), and deleteInterface().
00211 { 00212 tmpNumInterfaces = -1; 00213 delete[] tmpInterfaceList; 00214 tmpInterfaceList = NULL; 00215 }
virtual std::string InterfaceTable::getFullPath | ( | ) | const [inline, virtual] |
void InterfaceTable::initialize | ( | int | stage | ) | [protected, virtual] |
00055 { 00056 if (stage==0) 00057 { 00058 // get a pointer to the NotificationBoard module 00059 nb = NotificationBoardAccess().get(); 00060 00061 // register a loopback interface 00062 InterfaceEntry *ie = new InterfaceEntry(); 00063 ie->setName("lo0"); 00064 ie->setMtu(3924); 00065 ie->setLoopback(true); 00066 addInterface(ie, NULL); 00067 } 00068 else if (stage==1) 00069 { 00070 WATCH_PTRVECTOR(idToInterface); 00071 updateDisplayString(); 00072 } 00073 }
void InterfaceTable::handleMessage | ( | cMessage * | msg | ) | [protected, virtual] |
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.
00091 { 00092 // nothing needed here at the moment 00093 Enter_Method_Silent(); 00094 printNotificationBanner(category, details); 00095 }
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().
00142 { 00143 // check name is unique 00144 if (getInterfaceByName(entry->getName())!=NULL) 00145 opp_error("addInterface(): interface '%s' already registered", entry->getName()); 00146 00147 // insert 00148 entry->setInterfaceId(INTERFACEIDS_START + idToInterface.size()); 00149 entry->setInterfaceTable(this); 00150 idToInterface.push_back(entry); 00151 invalidateTmpInterfaceList(); 00152 00153 // fill in networkLayerGateIndex, nodeOutputGateId, nodeInputGateId 00154 if (ifmod) 00155 discoverConnectingGates(entry, ifmod); 00156 00157 nb->fireChangeNotification(NF_INTERFACE_CREATED, entry); 00158 }
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.
00198 { 00199 int id = entry->getInterfaceId(); 00200 if (entry != getInterfaceById(id)) 00201 opp_error("deleteInterface(): interface '%s' not found in interface table", entry->getName()); 00202 00203 nb->fireChangeNotification(NF_INTERFACE_DELETED, entry); // actually, only going to be deleted 00204 00205 idToInterface[id - INTERFACEIDS_START] = NULL; 00206 delete entry; 00207 invalidateTmpInterfaceList(); 00208 }
int InterfaceTable::getNumInterfaces | ( | ) | [virtual] |
Returns the number of interfaces.
Implements IInterfaceTable.
Referenced by getInterface(), and updateDisplayString().
00100 { 00101 if (tmpNumInterfaces == -1) 00102 { 00103 // count non-NULL elements 00104 int n = 0; 00105 int maxId = idToInterface.size(); 00106 for (int i=0; i<maxId; i++) 00107 if (idToInterface[i]) 00108 n++; 00109 tmpNumInterfaces = n; 00110 } 00111 00112 return tmpNumInterfaces; 00113 }
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.
00116 { 00117 int n = getNumInterfaces(); // also fills tmpInterfaceList 00118 if (pos<0 || pos>=n) 00119 opp_error("getInterface(): interface index %d out of range 0..%d", pos, n-1); 00120 00121 if (!tmpInterfaceList) 00122 { 00123 // collect non-NULL elements into tmpInterfaceList[] 00124 tmpInterfaceList = new InterfaceEntry *[n]; 00125 int k = 0; 00126 int maxId = idToInterface.size(); 00127 for (int i=0; i<maxId; i++) 00128 if (idToInterface[i]) 00129 tmpInterfaceList[k++] = idToInterface[i]; 00130 } 00131 00132 return tmpInterfaceList[pos]; 00133 }
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().
00136 { 00137 id -= INTERFACEIDS_START; 00138 return (id<0 || id>=(int)idToInterface.size()) ? NULL : idToInterface[id]; 00139 }
InterfaceEntry * InterfaceTable::getInterfaceByNodeOutputGateId | ( | int | id | ) | [virtual] |
Returns an interface given by its getNodeOutputGateId(). Returns NULL if not found.
Implements IInterfaceTable.
00223 { 00224 // linear search is OK because normally we have don't have many interfaces and this func is rarely called 00225 Enter_Method_Silent(); 00226 int n = idToInterface.size(); 00227 for (int i=0; i<n; i++) 00228 if (idToInterface[i] && idToInterface[i]->getNodeOutputGateId()==id) 00229 return idToInterface[i]; 00230 return NULL; 00231 }
InterfaceEntry * InterfaceTable::getInterfaceByNodeInputGateId | ( | int | id | ) | [virtual] |
Returns an interface given by its getNodeInputGateId(). Returns NULL if not found.
Implements IInterfaceTable.
00234 { 00235 // linear search is OK because normally we have don't have many interfaces and this func is rarely called 00236 Enter_Method_Silent(); 00237 int n = idToInterface.size(); 00238 for (int i=0; i<n; i++) 00239 if (idToInterface[i] && idToInterface[i]->getNodeInputGateId()==id) 00240 return idToInterface[i]; 00241 return NULL; 00242 }
InterfaceEntry * InterfaceTable::getInterfaceByNetworkLayerGateIndex | ( | int | index | ) | [virtual] |
Returns an interface given by its getNetworkLayerGateIndex(). Returns NULL if not found.
Implements IInterfaceTable.
00245 { 00246 // linear search is OK because normally we have don't have many interfaces and this func is rarely called 00247 Enter_Method_Silent(); 00248 int n = idToInterface.size(); 00249 for (int i=0; i<n; i++) 00250 if (idToInterface[i] && idToInterface[i]->getNetworkLayerGateIndex()==index) 00251 return idToInterface[i]; 00252 return NULL; 00253 }
InterfaceEntry * InterfaceTable::getInterfaceByName | ( | const char * | name | ) | [virtual] |
Returns an interface given by its name. Returns NULL if not found.
Implements IInterfaceTable.
Referenced by addInterface().
00256 { 00257 Enter_Method_Silent(); 00258 if (!name) 00259 return NULL; 00260 int n = idToInterface.size(); 00261 for (int i=0; i<n; i++) 00262 if (idToInterface[i] && !strcmp(name, idToInterface[i]->getName())) 00263 return idToInterface[i]; 00264 return NULL; 00265 }
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.
00268 { 00269 Enter_Method_Silent(); 00270 int n = idToInterface.size(); 00271 for (int i=0; i<n; i++) 00272 if (idToInterface[i] && idToInterface[i]->isLoopback()) 00273 return idToInterface[i]; 00274 return NULL; 00275 }
NotificationBoard* InterfaceTable::nb [protected] |
Referenced by addInterface(), deleteInterface(), initialize(), and interfaceChanged().
InterfaceVector InterfaceTable::idToInterface [protected] |
int InterfaceTable::tmpNumInterfaces [protected] |
Referenced by getNumInterfaces(), InterfaceTable(), and invalidateTmpInterfaceList().
InterfaceEntry** InterfaceTable::tmpInterfaceList [protected] |
Referenced by getInterface(), InterfaceTable(), invalidateTmpInterfaceList(), and ~InterfaceTable().