|
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, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 // 00018 00019 00020 #include <stdio.h> 00021 #include <stdlib.h> 00022 #include <string.h> 00023 #include <ctype.h> 00024 #include <algorithm> 00025 #include <sstream> 00026 00027 #include "AnsaInterfaceTable.h" 00028 #include "NotifierConsts.h" 00029 00030 00031 Define_Module(AnsaInterfaceTable ); 00032 00033 #define INTERFACEIDS_START 100 00034 00035 std::ostream& operator<<(std::ostream& os, const InterfaceEntry& e); 00036 00037 AnsaInterfaceTable::AnsaInterfaceTable() 00038 { 00039 tmpNumInterfaces = -1; 00040 tmpInterfaceList = NULL; 00041 } 00042 00043 AnsaInterfaceTable::~AnsaInterfaceTable() 00044 { 00045 for (int i=0; i < (int)idToInterface.size(); i++) 00046 delete idToInterface[i]; 00047 delete [] tmpInterfaceList; 00048 } 00049 00050 void AnsaInterfaceTable::initialize(int stage) 00051 { 00052 if (stage==0) 00053 { 00054 // get a pointer to the NotificationBoard module 00055 nb = NotificationBoardAccess().get(); 00056 00057 // register a loopback interface 00058 //vypnut 00059 //InterfaceEntry *ie = new InterfaceEntry(); 00060 //ie->setName("lo0"); 00061 //ie->setMtu(3924); 00062 //ie->setLoopback(true); 00063 //addInterface(ie, NULL); 00064 } 00065 else if (stage==1) 00066 { 00067 WATCH_PTRVECTOR(idToInterface); 00068 updateDisplayString(); 00069 } 00070 } 00071 00072 void AnsaInterfaceTable::updateDisplayString() 00073 { 00074 if (!ev.isGUI()) 00075 return; 00076 00077 char buf[80]; 00078 sprintf(buf, "%d interfaces", getNumInterfaces()); 00079 getDisplayString().setTagArg("t",0,buf); 00080 } 00081 00082 void AnsaInterfaceTable::handleMessage(cMessage *msg) 00083 { 00084 opp_error("This module doesn't process messages"); 00085 } 00086 00087 void AnsaInterfaceTable::receiveChangeNotification(int category, const cPolymorphic *details) 00088 { 00089 // nothing needed here at the moment 00090 Enter_Method_Silent(); 00091 printNotificationBanner(category, details); 00092 } 00093 00094 //--- 00095 00096 int AnsaInterfaceTable::getNumInterfaces() 00097 { 00098 if (tmpNumInterfaces == -1) 00099 { 00100 // count non-NULL elements 00101 int n = 0; 00102 int maxId = idToInterface.size(); 00103 for (int i=0; i<maxId; i++) 00104 if (idToInterface[i]) 00105 n++; 00106 tmpNumInterfaces = n; 00107 } 00108 00109 return tmpNumInterfaces; 00110 } 00111 00112 InterfaceEntry *AnsaInterfaceTable::getInterface(int pos) 00113 { 00114 int n = getNumInterfaces(); // also fills tmpInterfaceList 00115 if (pos<0 || pos>=n) 00116 opp_error("getInterface(): interface index %d out of range 0..%d", pos, n-1); 00117 00118 if (!tmpInterfaceList) 00119 { 00120 // collect non-NULL elements into tmpInterfaceList[] 00121 tmpInterfaceList = new InterfaceEntry *[n]; 00122 int k = 0; 00123 int maxId = idToInterface.size(); 00124 for (int i=0; i<maxId; i++) 00125 if (idToInterface[i]) 00126 tmpInterfaceList[k++] = idToInterface[i]; 00127 } 00128 00129 return tmpInterfaceList[pos]; 00130 } 00131 00132 InterfaceEntry *AnsaInterfaceTable::getInterfaceById(int id) 00133 { 00134 id -= INTERFACEIDS_START; 00135 return (id<0 || id>=(int)idToInterface.size()) ? NULL : idToInterface[id]; 00136 } 00137 00138 void AnsaInterfaceTable::addInterface(InterfaceEntry *entry, cModule *ifmod) 00139 { 00140 // check name is unique 00141 if (getInterfaceByName(entry->getName())!=NULL) 00142 opp_error("addInterface(): interface '%s' already registered", entry->getName()); 00143 00144 // insert 00145 entry->setInterfaceId(INTERFACEIDS_START + idToInterface.size()); 00146 entry->setInterfaceTable(this); 00147 idToInterface.push_back(entry); 00148 invalidateTmpInterfaceList(); 00149 00150 // fill in networkLayerGateIndex, nodeOutputGateId, nodeInputGateId 00151 if (ifmod) 00152 discoverConnectingGates(entry, ifmod); 00153 00154 nb->fireChangeNotification(NF_INTERFACE_CREATED, entry); 00155 } 00156 00157 void AnsaInterfaceTable::discoverConnectingGates(InterfaceEntry *entry, cModule *ifmod) 00158 { 00159 // ifmod is something like "host.eth[1].mac"; climb up to find "host.eth[1]" from it 00160 cModule *host = getParentModule(); 00161 while (ifmod && ifmod->getParentModule()!=host) 00162 ifmod = ifmod->getParentModule(); 00163 if (!ifmod) 00164 opp_error("addInterface(): specified module is not in this host/router"); 00165 00166 // find gates connected to host / network layer 00167 cGate *nwlayerInGate=NULL, *nwlayerOutGate=NULL; 00168 for (GateIterator i(ifmod); !i.end(); i++) 00169 { 00170 cGate *g = i(); 00171 if (!g) continue; 00172 00173 // find the host/router's gates that internally connect to this interface 00174 if (g->getType()==cGate::OUTPUT && g->getNextGate() && g->getNextGate()->getOwnerModule()==host) 00175 entry->setNodeOutputGateId(g->getNextGate()->getId()); 00176 if (g->getType()==cGate::INPUT && g->getPreviousGate() && g->getPreviousGate()->getOwnerModule()==host) 00177 entry->setNodeInputGateId(g->getPreviousGate()->getId()); 00178 00179 // find the gate index of networkLayer/networkLayer6/mpls that connects to this interface 00180 if (g->getType()==cGate::OUTPUT && g->getNextGate() && g->getNextGate()->isName("ifIn")) 00181 nwlayerInGate = g->getNextGate(); 00182 if (g->getType()==cGate::INPUT && g->getPreviousGate() && g->getPreviousGate()->isName("ifOut")) 00183 nwlayerOutGate = g->getPreviousGate(); 00184 } 00185 00186 // consistency checks 00187 // note: we don't check nodeOutputGateId/nodeInputGateId, because wireless interfaces 00188 // are not connected to the host 00189 if (!nwlayerInGate || !nwlayerOutGate || nwlayerInGate->getIndex()!=nwlayerOutGate->getIndex()) 00190 opp_error("addInterface(): interface must be connected to network layer's ifIn[]/ifOut[] gates of the same index"); 00191 entry->setNetworkLayerGateIndex(nwlayerInGate->getIndex()); 00192 } 00193 00194 void AnsaInterfaceTable::deleteInterface(InterfaceEntry *entry) 00195 { 00196 int id = entry->getInterfaceId(); 00197 if (entry != getInterfaceById(id)) 00198 opp_error("deleteInterface(): interface '%s' not found in interface table", entry->getName()); 00199 00200 nb->fireChangeNotification(NF_INTERFACE_DELETED, entry); // actually, only going to be deleted 00201 00202 idToInterface[id - INTERFACEIDS_START] = NULL; 00203 delete entry; 00204 invalidateTmpInterfaceList(); 00205 } 00206 00207 void AnsaInterfaceTable::invalidateTmpInterfaceList() 00208 { 00209 tmpNumInterfaces = -1; 00210 delete[] tmpInterfaceList; 00211 tmpInterfaceList = NULL; 00212 } 00213 00214 void AnsaInterfaceTable::interfaceChanged(InterfaceEntry *entry, int category) 00215 { 00216 nb->fireChangeNotification(category, entry); 00217 } 00218 00219 InterfaceEntry *AnsaInterfaceTable::getInterfaceByNodeOutputGateId(int id) 00220 { 00221 // linear search is OK because normally we have don't have many interfaces and this func is rarely called 00222 Enter_Method_Silent(); 00223 int n = idToInterface.size(); 00224 for (int i=0; i<n; i++) 00225 if (idToInterface[i] && idToInterface[i]->getNodeOutputGateId()==id) 00226 return idToInterface[i]; 00227 return NULL; 00228 } 00229 00230 InterfaceEntry *AnsaInterfaceTable::getInterfaceByNodeInputGateId(int id) 00231 { 00232 // linear search is OK because normally we have don't have many interfaces and this func is rarely called 00233 Enter_Method_Silent(); 00234 int n = idToInterface.size(); 00235 for (int i=0; i<n; i++) 00236 if (idToInterface[i] && idToInterface[i]->getNodeInputGateId()==id) 00237 return idToInterface[i]; 00238 return NULL; 00239 } 00240 00241 InterfaceEntry *AnsaInterfaceTable::getInterfaceByNetworkLayerGateIndex(int index) 00242 { 00243 // linear search is OK because normally we have don't have many interfaces and this func is rarely called 00244 Enter_Method_Silent(); 00245 int n = idToInterface.size(); 00246 for (int i=0; i<n; i++) 00247 if (idToInterface[i] && idToInterface[i]->getNetworkLayerGateIndex()==index) 00248 return idToInterface[i]; 00249 return NULL; 00250 } 00251 00252 InterfaceEntry *AnsaInterfaceTable::getInterfaceByName(const char *name) 00253 { 00254 Enter_Method_Silent(); 00255 if (!name) 00256 return NULL; 00257 int n = idToInterface.size(); 00258 for (int i=0; i<n; i++) 00259 if (idToInterface[i] && !strcmp(name, idToInterface[i]->getName())) 00260 return idToInterface[i]; 00261 return NULL; 00262 } 00263 00264 InterfaceEntry *AnsaInterfaceTable::getFirstLoopbackInterface() 00265 { 00266 Enter_Method_Silent(); 00267 int n = idToInterface.size(); 00268 for (int i=0; i<n; i++) 00269 if (idToInterface[i] && idToInterface[i]->isLoopback()) 00270 return idToInterface[i]; 00271 return NULL; 00272 } 00273 00274 InterfaceEntry *AnsaInterfaceTable::getFirstInterface() 00275 { 00276 Enter_Method_Silent(); 00277 int n = idToInterface.size(); 00278 for (int i=0; i<n; i++) 00279 if (idToInterface[i]) 00280 return idToInterface[i]; 00281 return NULL; 00282 } 00283