|
INET Framework for OMNeT++/OMNEST
|
00001 // 00002 // Copyright (C) 2005 Andras Varga 00003 // 00004 // This program is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 // 00009 // This program is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU Lesser General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this program; if not, see <http://www.gnu.org/licenses/>. 00016 // 00017 00018 00019 #include <stdio.h> 00020 #include <stdlib.h> 00021 #include <string.h> 00022 #include <ctype.h> 00023 #include <algorithm> 00024 #include <sstream> 00025 00026 #include "InterfaceTable.h" 00027 #include "NotifierConsts.h" 00028 00029 00030 Define_Module( InterfaceTable ); 00031 00032 #define INTERFACEIDS_START 100 00033 00034 std::ostream& operator<<(std::ostream& os, const InterfaceEntry& e) 00035 { 00036 os << e.info(); 00037 return os; 00038 }; 00039 00040 00041 InterfaceTable::InterfaceTable() 00042 { 00043 tmpNumInterfaces = -1; 00044 tmpInterfaceList = NULL; 00045 } 00046 00047 InterfaceTable::~InterfaceTable() 00048 { 00049 for (int i=0; i < (int)idToInterface.size(); i++) 00050 delete idToInterface[i]; 00051 delete [] tmpInterfaceList; 00052 } 00053 00054 void InterfaceTable::initialize(int stage) 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 } 00074 00075 void InterfaceTable::updateDisplayString() 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 } 00084 00085 void InterfaceTable::handleMessage(cMessage *msg) 00086 { 00087 opp_error("This module doesn't process messages"); 00088 } 00089 00090 void InterfaceTable::receiveChangeNotification(int category, const cPolymorphic *details) 00091 { 00092 // nothing needed here at the moment 00093 Enter_Method_Silent(); 00094 printNotificationBanner(category, details); 00095 } 00096 00097 //--- 00098 00099 int InterfaceTable::getNumInterfaces() 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 } 00114 00115 InterfaceEntry *InterfaceTable::getInterface(int pos) 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 } 00134 00135 InterfaceEntry *InterfaceTable::getInterfaceById(int id) 00136 { 00137 id -= INTERFACEIDS_START; 00138 return (id<0 || id>=(int)idToInterface.size()) ? NULL : idToInterface[id]; 00139 } 00140 00141 void InterfaceTable::addInterface(InterfaceEntry *entry, cModule *ifmod) 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 } 00159 00160 void InterfaceTable::discoverConnectingGates(InterfaceEntry *entry, cModule *ifmod) 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 } 00196 00197 void InterfaceTable::deleteInterface(InterfaceEntry *entry) 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 } 00209 00210 void InterfaceTable::invalidateTmpInterfaceList() 00211 { 00212 tmpNumInterfaces = -1; 00213 delete[] tmpInterfaceList; 00214 tmpInterfaceList = NULL; 00215 } 00216 00217 void InterfaceTable::interfaceChanged(InterfaceEntry *entry, int category) 00218 { 00219 nb->fireChangeNotification(category, entry); 00220 } 00221 00222 InterfaceEntry *InterfaceTable::getInterfaceByNodeOutputGateId(int id) 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 } 00232 00233 InterfaceEntry *InterfaceTable::getInterfaceByNodeInputGateId(int id) 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 } 00243 00244 InterfaceEntry *InterfaceTable::getInterfaceByNetworkLayerGateIndex(int index) 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 } 00254 00255 InterfaceEntry *InterfaceTable::getInterfaceByName(const char *name) 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 } 00266 00267 InterfaceEntry *InterfaceTable::getFirstLoopbackInterface() 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 } 00276