RUNetworkConfigurator.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2010 Institut fuer Telematik, Karlsruher Institut fuer Technologie (KIT)
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // 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 General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // 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 
00025 #include "RUNetworkConfigurator.h"
00026 #include <sstream>
00027 
00028 
00029 Define_Module( RUNetworkConfigurator);
00030 
00031 using namespace std;
00032 using namespace RUNetConf;
00033 
00034 RUNetworkConfigurator::RUNetworkConfigurator()
00035 {
00036 }
00037 
00038 RUNetworkConfigurator::~RUNetworkConfigurator()
00039 {
00040 }
00041 
00042 void RUNetworkConfigurator::initialize(int stage)
00043 {
00044     if (stage != 2)
00045         return;
00046 
00047 
00048     //TODO: read number of AS
00049     cTopology tempTopology("tempTopo");
00050     tempTopology.extractByProperty("AS");
00051 
00052     noAS = tempTopology.getNumNodes();
00053     cout << noAS <<endl;
00054     nextPow = 1;
00055     while ((1 << nextPow) < noAS + 1) {
00056         nextPow++;
00057     }
00058     IP_NET_SHIFT = 32 - nextPow;
00059     NET_MASK = 0xffffffff << IP_NET_SHIFT;
00060 
00061     // extract topology nodes and assign IP addresses
00062     extractTopology();
00063 
00064     // assign an IPAddress to all nodes in the network
00065     //FIXME: does asNodeVec.size() work as intended? may need to use noAS instead
00066     for (unsigned int i = 0; i < asNodeVec.size(); i++) {
00067         if ((unsigned int) rlTopology[i]->getNumNodes() > (0xffffffff - NET_MASK))
00068             opp_error("to many nodes in current topology");
00069         cerr << asNodeVec[i].module->getFullPath() << endl;
00070         //
00071         //  insert each router-level node into a node map
00072         //
00073         for (int j = 0; j < rlTopology[i]->getNumNodes(); j++) {
00074             nodeInfoRL curRLNode(rlTopology[i]->getNode(j));
00075             asNodeVec[i].nodeMap.insert(NODE_MAP_PAIR(curRLNode.moduleId, curRLNode));
00076         }
00077 
00078         // assign IP address and add default route
00079         assignAddressAndSetDefaultRoutes(asNodeVec[i]);
00080     }
00081 
00082     // add all further routes in router-level topology
00083     // (unequal to default route)
00084     for (unsigned int i = 0; i < asNodeVec.size(); i++)
00085         setIntraASRoutes(*rlTopology[i], asNodeVec[i]);
00086 
00087     // Having configured all router topologies, add Inter-AS routing paths
00088     if (noAS > 0)
00089         createInterASPaths();
00090 
00091     // free Memory
00092     for (int i = 0; i < noAS; i++) {
00093         rlTopology[i]->clear();
00094         delete rlTopology[i];
00095         asNodeVec[i].nodeMap.clear();
00096     }
00097     asTopology.clear();
00098     asNodeVec.clear();
00099     tempTopology.clear();
00100 }
00101 
00102 void RUNetworkConfigurator::createInterASPaths()
00103 {
00104     IPAddress netmask(NET_MASK);
00105     int asIdHistory = 0;
00106     unsigned int tmpAddr = 0;
00107     for (int i = 0; i < asTopology.getNumNodes(); i++) {
00108         // calculate prefix of current core node
00109         nodeInfoRL destCore(asTopology.getNode(i));
00110         tmpAddr = destCore.addr.getInt() >> IP_NET_SHIFT;
00111         tmpAddr = tmpAddr << IP_NET_SHIFT;
00112         destCore.addr = IPAddress(tmpAddr);
00113         asIdHistory = -1;
00114         for (int j = 0; j < asTopology.getNumNodes(); j++) {
00115             if (i == j)
00116                 continue;
00117             nodeInfoRL srcCore(asTopology.getNode(j));
00118             tmpAddr = srcCore.addr.getInt() >> IP_NET_SHIFT;
00119             tmpAddr = tmpAddr << IP_NET_SHIFT;
00120             srcCore.addr = IPAddress(tmpAddr);
00121 
00122             // do not calculate paths between nodes of the same AS
00123             if (destCore.asId == srcCore.asId)
00124                 continue;
00125 
00126             // cross only transit AS in order to reach destination core node
00127             // therefore, temporarily disable all stub links
00128             if (asIdHistory != srcCore.asId) {
00129                 disableStubLinks(destCore, srcCore);
00130                 asTopology.calculateUnweightedSingleShortestPathsTo(destCore.node);
00131             }
00132             // add routing entry from srcCore to destCore into routing table of srcCore
00133             InterfaceEntry *ie = srcCore.ift->getInterfaceByNodeOutputGateId(srcCore.node->getPath(0)->getLocalGate()->getId());
00134             IPRoute *e = new IPRoute();
00135             e->setHost(destCore.addr);
00136             e->setNetmask(netmask);
00137             e->setInterface(ie);
00138             e->setType(IPRoute::DIRECT);
00139             e->setSource(IPRoute::MANUAL);
00140             srcCore.rt->addRoute(e);
00141 
00142             // re-enable all stub links
00143             if (asIdHistory != srcCore.asId) {
00144                 enableStubLinks();
00145             }
00146             asIdHistory = srcCore.asId;
00147         }
00148     }
00149 }
00150 
00151 void RUNetworkConfigurator::disableStubLinks(nodeInfoRL &dst, nodeInfoRL &src)
00152 {
00153     for (unsigned int i = 0; i < asNodeVec.size(); i++) {
00154         if ((asNodeVec[i].id == dst.asId) || (asNodeVec[i].id == src.asId))
00155             continue;
00156         if (asNodeVec[i].asType == TRANSIT_AS)
00157             continue;
00158 
00159         for (unsigned int j = 0; j < asNodeVec[i].coreNode.size(); j++) {
00160             for (int k = 0; k < asNodeVec[i].coreNode[j].node->getNumInLinks(); k++)
00161                 asNodeVec[i].coreNode[j].node->getLinkIn(k)->disable();
00162         }
00163     }
00164 }
00165 
00166 void RUNetworkConfigurator::enableStubLinks()
00167 {
00168     for (unsigned int i = 0; i < asNodeVec.size(); i++) {
00169         if (asNodeVec[i].asType == TRANSIT_AS)
00170             continue;
00171         for (unsigned int j = 0; j < asNodeVec[i].coreNode.size(); j++) {
00172             for (int k = 0; k < asNodeVec[i].coreNode[j].node->getNumInLinks(); k++)
00173                 asNodeVec[i].coreNode[j].node->getLinkIn(k)->enable();
00174         }
00175     }
00176 }
00177 
00178 void RUNetworkConfigurator::extractTopology()
00179 {
00180     cTopology currentAS;
00181 
00182     // get the AS-level topology
00183     if (noAS > 0) {
00184         currentAS.extractByProperty("AS"); //TODO: check if this is acceptable
00185         if (currentAS.getNumNodes() != noAS)
00186             opp_error("Error: AS-Topology contains %u elements - expected %u\n", currentAS.getNumNodes(), noAS);
00187     }
00188     else if (noAS == 0) {
00189         // Network is router-level only
00190         currentAS.extractByProperty("Internet"); //TODO: check if this is acceptable
00191         if (currentAS.getNumNodes() != 1)
00192             opp_error("Error: tried to extract router-level only topology, but found more than 1 Inet module\n");
00193     }
00194 
00195     // get each router-level topology
00196     unsigned int netIP = 1 << IP_NET_SHIFT;
00197     for (int i = 0; i < currentAS.getNumNodes(); i++) {
00198         cTopology *tmpTopo = new cTopology();
00199         // extract router-level nodes from NED file
00200         tmpTopo->extractFromNetwork(getRouterLevelNodes, (void *) currentAS.getNode(i)->getModule()->getName());
00201         rlTopology.push_back(tmpTopo);
00202         // assign unique /16 IP address prefix to each AS
00203         asNodeVec.push_back(nodeInfoAS(currentAS.getNode(i), IPAddress(netIP), IPAddress(NET_MASK)));
00204         netIP += 1 << IP_NET_SHIFT;
00205     }
00206 
00207     asTopology.extractFromNetwork(getCoreNodes); //TODO: the extra function may be superfuous. extraction could be probably be done via asTopology.extractByProperty("CoreRouter"); -Claus
00208 
00209     //free memory
00210     currentAS.clear();
00211 }
00212 
00213 bool RUNetConf::getRouterLevelNodes(cModule *curMod, void *name)
00214 {
00215     char *curName = (char*) name;
00216     if (curName == NULL)
00217         opp_error("Error while casting void* name to char*\n");
00218 
00219     string sCurName = curName;
00220     sCurName += ".";
00221     string curModPath = curMod->getFullPath();
00222     if (curModPath.find(sCurName) == string::npos)
00223         return 0;
00224     //TODO: took some code from ctopology.cc to implement this, check if functionality is correct -Claus
00225     const char* property = "RL";
00226     cProperty *prop = curMod->getProperties()->get(property);
00227     if (!prop)
00228         return 0;
00229     const char *value = prop->getValue(cProperty::DEFAULTKEY, 0);
00230     return opp_strcmp(value, "false")!=0;
00231 }
00232 
00233 bool RUNetConf::getCoreNodes(cModule *curMod, void *nullPointer)
00234 {
00235     //TODO: took some code from ctopology.cc to implement this, check if functionality is correct -Claus
00236     const char* property = "CoreRouter";
00237     cProperty *prop = curMod->getProperties()->get(property);
00238     if (!prop)
00239         return 0;
00240     const char *value = prop->getValue(cProperty::DEFAULTKEY, 0);
00241     return opp_strcmp(value, "false")!=0;
00242 }
00243 
00244 void RUNetworkConfigurator::assignAddressAndSetDefaultRoutes(nodeInfoAS &asInfo)
00245 {
00246     unsigned int currentIP = asInfo.addr.getInt() + 1;
00247     int countEdgeRouter = 2; // avoids IP address 127.0.0.1
00248     int countRouter = 1;
00249     int edgeShift = 0;
00250 
00251     NODE_MAP::iterator mapIt = asInfo.nodeMap.begin();
00252     while (mapIt != asInfo.nodeMap.end()) {
00253         if (mapIt->second.routerType == EDGE) {
00254             countEdgeRouter++;
00255         }
00256         mapIt++;
00257     }
00258 
00259     nextPow = 0;
00260     while ((1 << nextPow) < countEdgeRouter) {
00261         nextPow++;
00262     }
00263 
00264     edgeShift = IP_NET_SHIFT - nextPow;
00265     asInfo.subnetmask = IPAddress(0xffffffff << edgeShift);
00266     countEdgeRouter = 1;
00267 
00268     mapIt = asInfo.nodeMap.begin();
00269     while (mapIt != asInfo.nodeMap.end()) {
00270         if (mapIt->second.routerType == ENDSYS) {
00271             mapIt++;
00272             continue;
00273         }
00274 
00275         if (mapIt->second.routerType == EDGE) {
00276             currentIP = asInfo.addr.getInt() + 1 + (countEdgeRouter++ << edgeShift);
00277             edgeRouter temp;
00278             temp.edgeIP = currentIP;
00279             temp.usedIPs = 1;
00280             temp.module = mapIt->second.module;
00281             asInfo.edgeRouter.push_back(temp);
00282         }
00283         else {
00284             currentIP = asInfo.addr.getInt() + countRouter++;
00285         }
00286 
00287         for (int j = 0; j < mapIt->second.ift->getNumInterfaces(); j++) {
00288             //
00289             // all interfaces except loopback get the same IP address
00290             //
00291             InterfaceEntry *ie = mapIt->second.ift->getInterface(j);
00292             if (!ie->isLoopback()) {
00293                 ie->ipv4Data()->setIPAddress(IPAddress(currentIP));
00294                 ie->ipv4Data()->setNetmask(IPAddress::ALLONES_ADDRESS);
00295             }
00296         }
00297         if (mapIt->second.rt->getRouterId().isUnspecified())
00298             mapIt->second.rt->setRouterId(IPAddress(currentIP));
00299         mapIt->second.addr.set(currentIP);
00300 
00301         // remember core nodes of each AS in additional list for assignment
00302         // of Inter-AS routing paths
00303         if (mapIt->second.routerType == CORE)
00304             asInfo.coreNode.push_back(mapIt->second);
00305         else {
00306             //
00307             // add default route in case of gw, edge, or host
00308             //
00309             IPRoute *e = new IPRoute();
00310             e->setHost(IPAddress());
00311             e->setNetmask(IPAddress());
00312             e->setInterface(mapIt->second.defaultRouteIE);
00313             e->setType(IPRoute::REMOTE);
00314             e->setSource(IPRoute::MANUAL);
00315             //e->setMetric(1);
00316             mapIt->second.rt->addRoute(e);
00317         }
00318 
00319         currentIP++;
00320         mapIt++;
00321     }
00322 }
00323 
00324 void RUNetworkConfigurator::setIntraASRoutes(cTopology &topology, nodeInfoAS &asInfo)
00325 {
00326     // calculate static routes from each of the AS's router-level nodes to all
00327     // other nodes of the AS
00328 
00329     for (int i = 0; i < topology.getNumNodes(); i++) {
00330         nodeInfoRL destNode = asInfo.nodeMap[topology.getNode(i)->getModule()->getId()];
00331         //
00332         // calculate shortest path form everywhere toward destNode
00333         //
00334         topology.calculateUnweightedSingleShortestPathsTo(destNode.node);
00335         for (int j = 0; j < topology.getNumNodes(); j++) {
00336             if (j == i)
00337                 continue;
00338             nodeInfoRL srcNode = asInfo.nodeMap[topology.getNode(j)->getModule()->getId()];
00339             // no route exists at all
00340             if (srcNode.node->getNumPaths() == 0)
00341                 continue;
00342             // end systems only know a default route to the edge router
00343             else if (srcNode.routerType == ENDSYS)
00344                 continue;
00345             else if (destNode.routerType == ENDSYS) {
00346                 if (srcNode.routerType != EDGE)
00347                         continue;
00348                 InterfaceEntry *ie = srcNode.ift->getInterfaceByNodeOutputGateId(srcNode.node->getPath(0)->getLocalGate()->getId());
00349                 if (ie == srcNode.defaultRouteIE)
00350                     continue;
00351 
00352                 for (uint32 i = 0; i < asInfo.edgeRouter.size(); i++) {
00353 
00354                     if (srcNode.module == asInfo.edgeRouter[i].module) {
00355 
00356                         destNode.addr = IPAddress(asInfo.edgeRouter[i].edgeIP + asInfo.edgeRouter[i].usedIPs);
00357                         asInfo.edgeRouter[i].usedIPs++;
00358                     }
00359                 }
00360 
00361                 for (int j = 0; j < destNode.ift->getNumInterfaces(); j++) {
00362                     //
00363                     // all interfaces except loopback get the same IP address
00364                     //
00365                     InterfaceEntry *ie = destNode.ift->getInterface(j);
00366                     if (!ie->isLoopback()) {
00367                         ie->ipv4Data()->setIPAddress(destNode.addr);
00368                         ie->ipv4Data()->setNetmask(IPAddress::ALLONES_ADDRESS);
00369                     }
00370                 }
00371                 IPRoute *e = new IPRoute();
00372                 e->setHost(IPAddress());
00373                 e->setNetmask(IPAddress());
00374                 e->setInterface(destNode.defaultRouteIE);
00375                 e->setType(IPRoute::REMOTE);
00376                 e->setSource(IPRoute::MANUAL);
00377                 destNode.rt->addRoute(e);
00378 
00379                 ie = srcNode.ift->getInterfaceByNodeOutputGateId(srcNode.node->getPath(0)->getLocalGate()->getId());
00380                 e = new IPRoute();
00381                 e->setHost(destNode.addr);
00382                 e->setNetmask(IPAddress(255, 255, 255, 255));
00383                 e->setInterface(ie);
00384                 e->setType(IPRoute::DIRECT);
00385                 e->setSource(IPRoute::MANUAL);
00386                 srcNode.rt->addRoute(e);
00387             }
00388             else {
00389                 //
00390                 // if destination is reachable through default route, no routing entry is necessary
00391                 //
00392                 InterfaceEntry *ie = srcNode.ift->getInterfaceByNodeOutputGateId(srcNode.node->getPath(0)->getLocalGate()->getId());
00393                 if (ie == srcNode.defaultRouteIE)
00394                     continue;
00395                 else {
00396                     // add specific routing entry into routing table
00397                     IPRoute *e = new IPRoute();
00398                     e->setHost(destNode.addr);
00399                     if (destNode.routerType == EDGE)
00400                         e->setNetmask(asInfo.subnetmask);
00401                     else
00402                         e->setNetmask(IPAddress(255, 255, 255, 255));
00403                     e->setInterface(ie);
00404                     e->setType(IPRoute::DIRECT);
00405                     e->setSource(IPRoute::MANUAL);
00406                     srcNode.rt->addRoute(e);
00407                 }
00408             }
00409         }
00410     }
00411 }
00412 
00413