|
INET Framework for OMNeT++/OMNEST
|
00001 // 00002 // Copyright (C) 2006 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 "NetworkConfigurator.h" 00023 #include "IPv4InterfaceData.h" 00024 00025 00026 Define_Module(NetworkConfigurator); 00027 00028 00029 void NetworkConfigurator::initialize(int stage) 00030 { 00031 if (stage==2) 00032 { 00033 cTopology topo("topo"); 00034 NodeInfoVector nodeInfo; // will be of size topo.nodes[] 00035 00036 // extract topology into the cTopology object, then fill in 00037 // isIPNode, rt and ift members of nodeInfo[] 00038 extractTopology(topo, nodeInfo); 00039 00040 // assign addresses to IP nodes, and also store result in nodeInfo[].address 00041 assignAddresses(topo, nodeInfo); 00042 00043 // add routes for point-to-point peers 00044 addPointToPointPeerRoutes(topo, nodeInfo); 00045 00046 // add default routes to hosts (nodes with a single attachment); 00047 // also remember result in nodeInfo[].usesDefaultRoute 00048 addDefaultRoutes(topo, nodeInfo); 00049 00050 // help configure RSVP and LinkStateRouting modules by setting their "peers" parameters 00051 setPeersParameter("rsvp", topo, nodeInfo); 00052 setPeersParameter("linkStateRouting", topo, nodeInfo); 00053 00054 // calculate shortest paths, and add corresponding static routes 00055 fillRoutingTables(topo, nodeInfo); 00056 00057 // update display string 00058 setDisplayString(topo, nodeInfo); 00059 } 00060 } 00061 00062 void NetworkConfigurator::extractTopology(cTopology& topo, NodeInfoVector& nodeInfo) 00063 { 00064 // extract topology 00065 topo.extractByProperty("node"); 00066 EV << "cTopology found " << topo.getNumNodes() << " nodes\n"; 00067 00068 // fill in isIPNode, ift and rt members in nodeInfo[] 00069 nodeInfo.resize(topo.getNumNodes()); 00070 for (int i=0; i<topo.getNumNodes(); i++) 00071 { 00072 cModule *mod = topo.getNode(i)->getModule(); 00073 nodeInfo[i].ift = IPAddressResolver().findInterfaceTableOf(mod); 00074 nodeInfo[i].rt = IPAddressResolver().findRoutingTableOf(mod); 00075 nodeInfo[i].isIPNode = nodeInfo[i].rt!=NULL; 00076 } 00077 } 00078 00079 void NetworkConfigurator::assignAddresses(cTopology& topo, NodeInfoVector& nodeInfo) 00080 { 00081 uint32 base = 10 << 24; // 10.x.x.x addresses 00082 int nodeCtr = 1; // middle 16 bits 00083 00084 for (int i=0; i<topo.getNumNodes(); i++) 00085 { 00086 // skip bus types 00087 if (!nodeInfo[i].isIPNode) 00088 continue; 00089 00090 uint32 addr = base + (nodeCtr++ << 8); // --> 10.nn.nn.0 00091 00092 // assign address to all (non-loopback) interfaces 00093 IInterfaceTable *ift = nodeInfo[i].ift; 00094 for (int k=0; k<ift->getNumInterfaces(); k++) 00095 { 00096 InterfaceEntry *ie = ift->getInterface(k); 00097 if (!ie->isLoopback()) 00098 { 00099 ie->ipv4Data()->setIPAddress(IPAddress(addr | (uint32)k)); 00100 ie->ipv4Data()->setNetmask(IPAddress::ALLONES_ADDRESS); // full address must match for local delivery 00101 } 00102 } 00103 00104 // set routerId as well (if not yet configured) 00105 IRoutingTable *rt = nodeInfo[i].rt; 00106 if (rt->getRouterId().isUnspecified()) 00107 { 00108 rt->setRouterId(IPAddress(addr | 1U)); // 10.nn.nn.1 00109 } 00110 } 00111 } 00112 00113 void NetworkConfigurator::addPointToPointPeerRoutes(cTopology& topo, NodeInfoVector& nodeInfo) 00114 { 00115 bool useRouterIdForRoutes = true; // TODO make it parameter 00116 00117 // add routes towards point-to-point routers (in real life these routes are 00118 // created automatically after PPP handshake when neighbour's address is learned) 00119 for (int i=0; i<topo.getNumNodes(); i++) 00120 { 00121 // skip bus types 00122 if (!nodeInfo[i].isIPNode) 00123 continue; 00124 00125 cTopology::Node *node = topo.getNode(i); 00126 //InterfaceTable *ift = nodeInfo[i].ift; 00127 IRoutingTable *rt = nodeInfo[i].rt; 00128 00129 // loop through neighbors 00130 for (int j=0; j<node->getNumOutLinks(); j++) 00131 { 00132 cTopology::Node *neighbor = node->getLinkOut(j)->getRemoteNode(); 00133 00134 // find neighbour's index in cTopology ==> k 00135 int k; 00136 for (k=0; k<topo.getNumNodes(); k++) 00137 if (topo.getNode(k)==neighbor) 00138 break; 00139 ASSERT(k<=topo.getNumNodes()); 00140 00141 // if it's not an IP getNode(e.g. an Ethernet switch), then we're not interested 00142 if (!nodeInfo[k].isIPNode) 00143 continue; 00144 00145 // find out neighbor's routerId 00146 IPAddress neighborRouterId = nodeInfo[k].rt->getRouterId(); 00147 00148 // find out neighbor's interface IP address 00149 int neighborGateId = node->getLinkOut(j)->getRemoteGate()->getId(); 00150 InterfaceEntry *neighborIe = nodeInfo[k].ift->getInterfaceByNodeInputGateId(neighborGateId); 00151 ASSERT(neighborIe); 00152 IPAddress neighborAddr = neighborIe->ipv4Data()->getIPAddress(); 00153 00154 // find our own interface towards neighbor 00155 int gateId = node->getLinkOut(j)->getLocalGate()->getId(); 00156 InterfaceEntry *ie = nodeInfo[i].ift->getInterfaceByNodeOutputGateId(gateId); 00157 ASSERT(ie); 00158 00159 // add route 00160 IPRoute *e = new IPRoute(); 00161 if (useRouterIdForRoutes) 00162 { 00163 e->setHost(neighborRouterId); 00164 e->setGateway(neighborAddr); 00165 } 00166 else 00167 { 00168 e->setHost(neighborAddr); // and no gateway 00169 } 00170 e->setNetmask(IPAddress(255,255,255,255)); // full match needed 00171 e->setInterface(ie); 00172 e->setType(IPRoute::DIRECT); 00173 e->setSource(IPRoute::MANUAL); 00174 //e->getMetric() = 1; 00175 rt->addRoute(e); 00176 } 00177 } 00178 } 00179 00180 void NetworkConfigurator::addDefaultRoutes(cTopology& topo, NodeInfoVector& nodeInfo) 00181 { 00182 // add default route to nodes with exactly one (non-loopback) interface 00183 for (int i=0; i<topo.getNumNodes(); i++) 00184 { 00185 // skip bus types 00186 if (!nodeInfo[i].isIPNode) 00187 continue; 00188 00189 cTopology::Node *node = topo.getNode(i); 00190 IInterfaceTable *ift = nodeInfo[i].ift; 00191 IRoutingTable *rt = nodeInfo[i].rt; 00192 00193 // count non-loopback interfaces 00194 int numIntf = 0; 00195 InterfaceEntry *ie = NULL; 00196 for (int k=0; k<ift->getNumInterfaces(); k++) 00197 if (!ift->getInterface(k)->isLoopback()) 00198 {ie = ift->getInterface(k); numIntf++;} 00199 00200 nodeInfo[i].usesDefaultRoute = (numIntf==1); 00201 if (numIntf!=1) 00202 continue; // only deal with nodes with one interface plus loopback 00203 00204 EV << " " << node->getModule()->getFullName() << " has only one (non-loopback) " 00205 "interface, adding default route\n"; 00206 00207 // add route 00208 IPRoute *e = new IPRoute(); 00209 e->setHost(IPAddress()); 00210 e->setNetmask(IPAddress()); 00211 e->setInterface(ie); 00212 e->setType(IPRoute::REMOTE); 00213 e->setSource(IPRoute::MANUAL); 00214 //e->setMetric(1); 00215 rt->addRoute(e); 00216 } 00217 } 00218 00219 void NetworkConfigurator::setPeersParameter(const char *submodName, cTopology& topo, NodeInfoVector& nodeInfo) 00220 { 00221 // the RSVP module expects a "peers" module parameter to contain the interfaces 00222 // towards directly connected other RSVP routers. Since it's cumbersome to configure 00223 // manually in a large network, do it here (submodName = "rsvp"). 00224 // The LinkStateRouting module is similar, so this function is also called with submodName = "LinkStateRouting". 00225 00226 // for each RSVP router, collect neighbors which are also RSVP routers 00227 for (int i=0; i<topo.getNumNodes(); i++) 00228 { 00229 // if it doesn't have an RSVP submodule, we're not interested 00230 cModule *submod = topo.getNode(i)->getModule()->getSubmodule(submodName); 00231 if (submod==NULL) 00232 continue; 00233 00234 std::string peers; 00235 cTopology::Node *node = topo.getNode(i); 00236 for (int j=0; j<node->getNumOutLinks(); j++) 00237 { 00238 // if neighbor is not an RSVP router, then we're not interested 00239 cModule *neighborSubmod = node->getLinkOut(j)->getRemoteNode()->getModule()->getSubmodule(submodName); 00240 if (neighborSubmod==NULL) 00241 continue; 00242 00243 // find our own interface towards neighbor 00244 int gateId = node->getLinkOut(j)->getLocalGate()->getId(); 00245 InterfaceEntry *ie = nodeInfo[i].ift->getInterfaceByNodeOutputGateId(gateId); 00246 ASSERT(ie); 00247 00248 // interface name to peers list 00249 peers += std::string(" ") + ie->getName(); 00250 } 00251 00252 // set "peers" parameter 00253 submod->par("peers") = peers.c_str(); 00254 } 00255 } 00256 00257 void NetworkConfigurator::fillRoutingTables(cTopology& topo, NodeInfoVector& nodeInfo) 00258 { 00259 /* FIXME TBD 00260 // fill in routing tables with static routes 00261 for (int i=0; i<topo.getNumNodes(); i++) 00262 { 00263 cTopology::Node *destNode = topo.getNode(i); 00264 00265 // skip bus types 00266 if (!nodeInfo[i].isIPNode) 00267 continue; 00268 00269 IPAddress destAddr = nodeInfo[i].address; 00270 std::string destModName = destNode->getModule()->getFullName(); 00271 00272 // calculate shortest paths from everywhere towards destNode 00273 topo.calculateUnweightedSingleShortestPathsTo(destNode); 00274 00275 // add route (with host=destNode) to every routing table in the network 00276 // (excepting nodes with only one interface -- there we'll set up a default route) 00277 for (int j=0; j<topo.getNumNodes(); j++) 00278 { 00279 if (i==j) continue; 00280 if (!nodeInfo[j].isIPNode) 00281 continue; 00282 00283 cTopology::Node *atNode = topo.getNode(j); 00284 if (atNode->getNumPaths()==0) 00285 continue; // not connected 00286 if (nodeInfo[j].usesDefaultRoute) 00287 continue; // already added default route here 00288 00289 IPAddress atAddr = nodeInfo[j].address; 00290 00291 IInterfaceTable *ift = nodeInfo[j].ift; 00292 00293 int outputGateId = atNode->getPath(0)->getLocalGate()->getId(); 00294 InterfaceEntry *ie = ift->getInterfaceByNodeOutputGateId(outputGateId); 00295 if (!ie) 00296 error("%s has no interface for output gate id %d", ift->getFullPath().c_str(), outputGateId); 00297 00298 EV << " from " << atNode->getModule()->getFullName() << "=" << IPAddress(atAddr); 00299 EV << " towards " << destModName << "=" << IPAddress(destAddr) << " interface " << ie->getName() << endl; 00300 00301 // add route 00302 IRoutingTable *rt = nodeInfo[j].rt; 00303 IPRoute *e = new IPRoute(); 00304 e->setHost(destAddr); 00305 e->gateway = ??? 00306 e->setNetmask(IPAddress(255,255,255,255)); // full match needed 00307 e->setInterface(ie); 00308 e->setType(IPRoute::REMOTE); 00309 e->setSource(IPRoute::MANUAL); 00310 //e->getMetric() = 1; 00311 rt->addRoute(e); 00312 } 00313 } 00314 */ 00315 } 00316 00317 void NetworkConfigurator::handleMessage(cMessage *msg) 00318 { 00319 error("this module doesn't handle messages, it runs only in initialize()"); 00320 } 00321 00322 void NetworkConfigurator::setDisplayString(cTopology& topo, NodeInfoVector& nodeInfo) 00323 { 00324 int numIPNodes = 0; 00325 for (int i=0; i<topo.getNumNodes(); i++) 00326 if (nodeInfo[i].isIPNode) 00327 numIPNodes++; 00328 00329 // update display string 00330 char buf[80]; 00331 sprintf(buf, "%d IP nodes\n%d non-IP nodes", numIPNodes, topo.getNumNodes()-numIPNodes); 00332 getDisplayString().setTagArg("t",0,buf); 00333 } 00334 00335