INET Framework for OMNeT++/OMNEST
AnsaInterfaceTable.cc
Go to the documentation of this file.
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