|
INET Framework for OMNeT++/OMNEST
|
00001 // 00002 // Copyright (C) 2004 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 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 Lesser General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU Lesser General Public License 00015 // along with this program; if not, see <http://www.gnu.org/licenses/>. 00016 // 00017 00018 #include <algorithm> 00019 #include "IRoutingTable.h" 00020 #include "IInterfaceTable.h" 00021 #include "IPAddressResolver.h" 00022 #include "FlatNetworkConfigurator.h" 00023 #include "InterfaceEntry.h" 00024 #include "IPv4InterfaceData.h" 00025 00026 00027 Define_Module(FlatNetworkConfigurator); 00028 00029 00030 void FlatNetworkConfigurator::initialize(int stage) 00031 { 00032 if (stage==2) 00033 { 00034 cTopology topo("topo"); 00035 NodeInfoVector nodeInfo; // will be of size topo.nodes[] 00036 00037 // extract topology into the cTopology object, then fill in 00038 // isIPNode, rt and ift members of nodeInfo[] 00039 extractTopology(topo, nodeInfo); 00040 00041 // assign addresses to IP nodes, and also store result in nodeInfo[].address 00042 assignAddresses(topo, nodeInfo); 00043 00044 // add default routes to hosts (nodes with a single attachment); 00045 // also remember result in nodeInfo[].usesDefaultRoute 00046 addDefaultRoutes(topo, nodeInfo); 00047 00048 // calculate shortest paths, and add corresponding static routes 00049 fillRoutingTables(topo, nodeInfo); 00050 00051 // update display string 00052 setDisplayString(topo, nodeInfo); 00053 } 00054 } 00055 00056 void FlatNetworkConfigurator::extractTopology(cTopology& topo, NodeInfoVector& nodeInfo) 00057 { 00058 // extract topology 00059 topo.extractByProperty("node"); 00060 EV << "cTopology found " << topo.getNumNodes() << " nodes\n"; 00061 00062 // fill in isIPNode, ift and rt members in nodeInfo[] 00063 nodeInfo.resize(topo.getNumNodes()); 00064 for (int i=0; i<topo.getNumNodes(); i++) 00065 { 00066 cModule *mod = topo.getNode(i)->getModule(); 00067 nodeInfo[i].isIPNode = IPAddressResolver().findInterfaceTableOf(mod)!=NULL; 00068 if (nodeInfo[i].isIPNode) 00069 { 00070 nodeInfo[i].ift = IPAddressResolver().interfaceTableOf(mod); 00071 nodeInfo[i].rt = IPAddressResolver().routingTableOf(mod); 00072 } 00073 } 00074 } 00075 00076 void FlatNetworkConfigurator::assignAddresses(cTopology& topo, NodeInfoVector& nodeInfo) 00077 { 00078 // assign IP addresses 00079 uint32 networkAddress = IPAddress(par("networkAddress").stringValue()).getInt(); 00080 uint32 netmask = IPAddress(par("netmask").stringValue()).getInt(); 00081 int maxNodes = (~netmask)-1; // 0 and ffff have special meaning and cannot be used 00082 if (topo.getNumNodes()>maxNodes) 00083 error("netmask too large, not enough addresses for all %d nodes", topo.getNumNodes()); 00084 00085 int numIPNodes = 0; 00086 for (int i=0; i<topo.getNumNodes(); i++) 00087 { 00088 // skip bus types 00089 if (!nodeInfo[i].isIPNode) 00090 continue; 00091 00092 uint32 addr = networkAddress | uint32(++numIPNodes); 00093 nodeInfo[i].address.set(addr); 00094 00095 // find interface table and assign address to all (non-loopback) interfaces 00096 IInterfaceTable *ift = nodeInfo[i].ift; 00097 for (int k=0; k<ift->getNumInterfaces(); k++) 00098 { 00099 InterfaceEntry *ie = ift->getInterface(k); 00100 if (!ie->isLoopback()) 00101 { 00102 ie->ipv4Data()->setIPAddress(IPAddress(addr)); 00103 ie->ipv4Data()->setNetmask(IPAddress::ALLONES_ADDRESS); // full address must match for local delivery 00104 } 00105 } 00106 } 00107 } 00108 00109 void FlatNetworkConfigurator::addDefaultRoutes(cTopology& topo, NodeInfoVector& nodeInfo) 00110 { 00111 // add default route to nodes with exactly one (non-loopback) interface 00112 for (int i=0; i<topo.getNumNodes(); i++) 00113 { 00114 cTopology::Node *node = topo.getNode(i); 00115 00116 // skip bus types 00117 if (!nodeInfo[i].isIPNode) 00118 continue; 00119 00120 IInterfaceTable *ift = nodeInfo[i].ift; 00121 IRoutingTable *rt = nodeInfo[i].rt; 00122 00123 // count non-loopback interfaces 00124 int numIntf = 0; 00125 InterfaceEntry *ie = NULL; 00126 for (int k=0; k<ift->getNumInterfaces(); k++) 00127 if (!ift->getInterface(k)->isLoopback()) 00128 {ie = ift->getInterface(k); numIntf++;} 00129 00130 nodeInfo[i].usesDefaultRoute = (numIntf==1); 00131 if (numIntf!=1) 00132 continue; // only deal with nodes with one interface plus loopback 00133 00134 EV << " " << node->getModule()->getFullName() << "=" << nodeInfo[i].address 00135 << " has only one (non-loopback) interface, adding default route\n"; 00136 00137 // add route 00138 IPRoute *e = new IPRoute(); 00139 e->setHost(IPAddress()); 00140 e->setNetmask(IPAddress()); 00141 e->setInterface(ie); 00142 e->setType(IPRoute::REMOTE); 00143 e->setSource(IPRoute::MANUAL); 00144 //e->getMetric() = 1; 00145 rt->addRoute(e); 00146 } 00147 } 00148 00149 void FlatNetworkConfigurator::fillRoutingTables(cTopology& topo, NodeInfoVector& nodeInfo) 00150 { 00151 // fill in routing tables with static routes 00152 for (int i=0; i<topo.getNumNodes(); i++) 00153 { 00154 cTopology::Node *destNode = topo.getNode(i); 00155 00156 // skip bus types 00157 if (!nodeInfo[i].isIPNode) 00158 continue; 00159 00160 IPAddress destAddr = nodeInfo[i].address; 00161 std::string destModName = destNode->getModule()->getFullName(); 00162 00163 // calculate shortest paths from everywhere towards destNode 00164 topo.calculateUnweightedSingleShortestPathsTo(destNode); 00165 00166 // add route (with host=destNode) to every routing table in the network 00167 // (excepting nodes with only one interface -- there we'll set up a default route) 00168 for (int j=0; j<topo.getNumNodes(); j++) 00169 { 00170 if (i==j) continue; 00171 if (!nodeInfo[j].isIPNode) 00172 continue; 00173 00174 cTopology::Node *atNode = topo.getNode(j); 00175 if (atNode->getNumPaths()==0) 00176 continue; // not connected 00177 if (nodeInfo[j].usesDefaultRoute) 00178 continue; // already added default route here 00179 00180 IPAddress atAddr = nodeInfo[j].address; 00181 00182 IInterfaceTable *ift = nodeInfo[j].ift; 00183 00184 int outputGateId = atNode->getPath(0)->getLocalGate()->getId(); 00185 InterfaceEntry *ie = ift->getInterfaceByNodeOutputGateId(outputGateId); 00186 if (!ie) 00187 error("%s has no interface for output gate id %d", ift->getFullPath().c_str(), outputGateId); 00188 00189 EV << " from " << atNode->getModule()->getFullName() << "=" << IPAddress(atAddr); 00190 EV << " towards " << destModName << "=" << IPAddress(destAddr) << " interface " << ie->getName() << endl; 00191 00192 // add route 00193 IRoutingTable *rt = nodeInfo[j].rt; 00194 IPRoute *e = new IPRoute(); 00195 e->setHost(destAddr); 00196 e->setNetmask(IPAddress(255,255,255,255)); // full match needed 00197 e->setInterface(ie); 00198 e->setType(IPRoute::DIRECT); 00199 e->setSource(IPRoute::MANUAL); 00200 //e->getMetric() = 1; 00201 rt->addRoute(e); 00202 } 00203 } 00204 } 00205 00206 void FlatNetworkConfigurator::handleMessage(cMessage *msg) 00207 { 00208 error("this module doesn't handle messages, it runs only in initialize()"); 00209 } 00210 00211 void FlatNetworkConfigurator::setDisplayString(cTopology& topo, NodeInfoVector& nodeInfo) 00212 { 00213 int numIPNodes = 0; 00214 for (int i=0; i<topo.getNumNodes(); i++) 00215 if (nodeInfo[i].isIPNode) 00216 numIPNodes++; 00217 00218 // update display string 00219 char buf[80]; 00220 sprintf(buf, "%d IP nodes\n%d non-IP nodes", numIPNodes, topo.getNumNodes()-numIPNodes); 00221 getDisplayString().setTagArg("t",0,buf); 00222 } 00223 00224