InetUnderlayConfigurator.cc

Go to the documentation of this file.
00001 //
00002 // This program is free software; you can redistribute it and/or
00003 // modify it under the terms of the GNU General Public License
00004 // as published by the Free Software Foundation; either version 2
00005 // of the License, or (at your option) any later version.
00006 //
00007 // This program is distributed in the hope that it will be useful,
00008 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00009 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010 // GNU General Public License for more details.
00011 //
00012 // You should have received a copy of the GNU General Public License
00013 // along with this program; if not, write to the Free Software
00014 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00015 //
00016 
00022 #include "InetUnderlayConfigurator.h"
00023 
00024 #include <GlobalNodeList.h>
00025 #include <TransportAddress.h>
00026 
00027 #include <StringConvert.h>
00028 
00029 #include <AccessNet.h>
00030 #include <IRoutingTable.h>
00031 #include <RoutingTable6.h>
00032 #include <IInterfaceTable.h>
00033 #include <IPAddressResolver.h>
00034 #include <IPv4InterfaceData.h>
00035 #include <IPv6InterfaceData.h>
00036 #include <NotificationBoard.h>
00037 
00038 
00039 #include <InetInfo.h>
00040 
00041 Define_Module(InetUnderlayConfigurator);
00042 
00043 void InetUnderlayConfigurator::initializeUnderlay(int stage)
00044 {
00045     //backbone configuration
00046     if (stage == MIN_STAGE_UNDERLAY) {
00047         // Find all router modules.
00048         cTopology topo("topo");
00049         topo.extractByProperty("node");
00050 
00051         if (par("useIPv6Addresses").boolValue()) {
00052             setUpIPv6(topo);
00053             //opp_error("IPv6 is not supported in this release but is coming soon.");
00054         } else {
00055             setUpIPv4(topo);
00056         }
00057     }
00058     //access net configuration
00059     else if(stage == MAX_STAGE_UNDERLAY) {
00060         // fetch some parameters
00061         accessRouterNum = getParentModule()->par("accessRouterNum");
00062         overlayAccessRouterNum = getParentModule()->par("overlayAccessRouterNum");
00063 
00064         // count the overlay clients
00065         overlayTerminalCount = 0;
00066 
00067         numCreated = 0;
00068         numKilled = 0;
00069 
00070         // add access node modules to access node vector
00071         cModule* node;
00072         for (int i = 0; i < accessRouterNum; i++) {
00073             node = getParentModule()->getSubmodule("accessRouter", i);
00074             accessNode.push_back( node );
00075         }
00076 
00077         for (int i = 0; i < overlayAccessRouterNum; i++) {
00078             node = getParentModule()->getSubmodule("overlayAccessRouter", i);
00079             accessNode.push_back( node );
00080         }
00081 
00082         // debug stuff
00083         WATCH_PTRVECTOR(accessNode);
00084     }
00085 }
00086 
00087 TransportAddress* InetUnderlayConfigurator::createNode(NodeType type, bool initialize)
00088 {
00089     Enter_Method_Silent();
00090     // derive overlay node from ned
00091     std::string nameStr = "overlayTerminal";
00092     if( churnGenerator.size() > 1 ){
00093         nameStr += "-" + convertToString<uint32_t>(type.typeID);
00094     }
00095     cModuleType* moduleType = cModuleType::get(type.terminalType.c_str());
00096     cModule* node = moduleType->create(nameStr.c_str(), getParentModule(),
00097                                        numCreated + 1, numCreated);
00098 
00099     if (type.channelTypesTx.size() > 0) {
00100         throw cRuntimeError("InetUnderlayConfigurator::createNode(): Setting "
00101                     "channel types via the churn generator is not allowed "
00102                     "with the InetUnderlay. Use **.accessNet.channelTypes instead!");
00103     }
00104 
00105     node->setGateSize("pppg", 1);
00106 
00107     std::string displayString;
00108 
00109     if ((type.typeID > 0) && (type.typeID <= NUM_COLORS)) {
00110         ((displayString += "i=device/wifilaptop_l,")
00111                         += colorNames[type.typeID - 1])
00112                         += ",40;i2=block/circle_s";
00113     } else {
00114         displayString = "i=device/wifilaptop_l;i2=block/circle_s";
00115     }
00116 
00117     node->finalizeParameters();
00118     node->setDisplayString(displayString.c_str());
00119 
00120     node->buildInside();
00121     node->scheduleStart(simTime());
00122 
00123     // create meta information
00124     InetInfo* info = new InetInfo(type.typeID, node->getId(), type.context);
00125     AccessNet* accessNet= check_and_cast<AccessNet*>
00126         (accessNode[intuniform(0, accessNode.size() - 1)]
00127                 ->getSubmodule("accessNet"));
00128 
00129     info->setAccessNetModule(accessNet);
00130     info->setNodeID(node->getId());
00131 
00132     // add node to a randomly chosen access net and bootstrap oracle
00133     globalNodeList->addPeer(accessNet->addOverlayNode(node), info);
00134 
00135     // if the node was not created during startup we have to
00136     // finish the initialization process manually
00137     if (!initialize) {
00138         for (int i = MAX_STAGE_UNDERLAY + 1; i < NUM_STAGES_ALL; i++) {
00139             node->callInitialize(i);
00140         }
00141     }
00142 
00143     overlayTerminalCount++;
00144     numCreated++;
00145 
00146     churnGenerator[type.typeID]->terminalCount++;
00147 
00148     TransportAddress *address = new TransportAddress(
00149                                        IPAddressResolver().addressOf(node));
00150 
00151     // update display
00152     setDisplayString();
00153 
00154     return address;
00155 }
00156 
00157 //TODO: getRandomNode()
00158 void InetUnderlayConfigurator::preKillNode(NodeType type, TransportAddress* addr)
00159 {
00160     Enter_Method_Silent();
00161 
00162     AccessNet* accessNetModule = NULL;
00163     int nodeID;
00164     InetInfo* info;
00165 
00166     // If no address given, get random node
00167     if (addr == NULL) {
00168         addr = globalNodeList->getRandomAliveNode(type.typeID);
00169 
00170         if (addr == NULL) {
00171             // all nodes are already prekilled
00172             std::cout << "all nodes are already prekilled" << std::endl;
00173             return;
00174         }
00175     }
00176 
00177     // get node information
00178     info = dynamic_cast<InetInfo*>(globalNodeList->getPeerInfo(*addr));
00179 
00180     if (info != NULL) {
00181         accessNetModule = info->getAccessNetModule();
00182         nodeID = info->getNodeID();
00183     } else {
00184         opp_error("IPv4UnderlayConfigurator: Trying to pre kill node "
00185                   "with nonexistant TransportAddress!");
00186     }
00187 
00188     uint32_t effectiveType = info->getTypeID();
00189 
00190     // do not kill node that is already scheduled
00191     if(scheduledID.count(nodeID))
00192         return;
00193 
00194     cModule* node = accessNetModule->getOverlayNode(nodeID);
00195     globalNodeList->removePeer(IPAddressResolver().addressOf(node));
00196 
00197     //put node into the kill list and schedule a message for final removal of the node
00198     killList.push_front(IPAddressResolver().addressOf(node));
00199     scheduledID.insert(nodeID);
00200 
00201     overlayTerminalCount--;
00202     numKilled++;
00203 
00204     churnGenerator[effectiveType]->terminalCount--;
00205 
00206     // update display
00207     setDisplayString();
00208 
00209     // inform the notification board about the removal
00210     NotificationBoard* nb = check_and_cast<NotificationBoard*>(
00211             node->getSubmodule("notificationBoard"));
00212     nb->fireChangeNotification(NF_OVERLAY_NODE_LEAVE);
00213 
00214     double random = uniform(0, 1);
00215 
00216     if (random < gracefulLeaveProbability) {
00217         nb->fireChangeNotification(NF_OVERLAY_NODE_GRACEFUL_LEAVE);
00218     }
00219 
00220     cMessage* msg = new cMessage();
00221     scheduleAt(simTime() + gracefulLeaveDelay, msg);
00222 
00223 }
00224 
00225 void InetUnderlayConfigurator::migrateNode(NodeType type, TransportAddress* addr)
00226 {
00227     Enter_Method_Silent();
00228 
00229     AccessNet* accessNetModule = NULL;
00230     int nodeID = -1;
00231     InetInfo* info;
00232 
00233     // If no address given, get random node
00234     if(addr == NULL) {
00235         info = dynamic_cast<InetInfo*>(globalNodeList->getRandomPeerInfo(type.typeID));
00236     } else {
00237         // get node information
00238         info = dynamic_cast<InetInfo*>(globalNodeList->getPeerInfo(*addr));
00239     }
00240 
00241     if(info != NULL) {
00242         accessNetModule = info->getAccessNetModule();
00243         nodeID = info->getNodeID();
00244     } else {
00245         opp_error("IPv4UnderlayConfigurator: Trying to pre kill node with nonexistant TransportAddress!");
00246     }
00247 
00248     // do not migrate node that is already scheduled
00249     if(scheduledID.count(nodeID))
00250         return;
00251 
00252     cModule* node = accessNetModule->removeOverlayNode(nodeID);//intuniform(0, accessNetModule->size() - 1));
00253 
00254     if(node == NULL)
00255         opp_error("IPv4UnderlayConfigurator: Trying to remove node which is nonexistant in AccessNet!");
00256 
00257     //remove node from bootstrap oracle
00258     globalNodeList->killPeer(IPAddressResolver().addressOf(node));
00259 
00260     node->bubble("I am migrating!");
00261 
00262     // connect the node to another access net
00263     AccessNet* newAccessNetModule;
00264 
00265     do {
00266         newAccessNetModule = check_and_cast<AccessNet*>(accessNode[intuniform(0, accessNode.size() - 1)]->getSubmodule("accessNet"));
00267     } while((newAccessNetModule == accessNetModule) && (accessNode.size() != 1));
00268 
00269     // create meta information
00270     InetInfo* newinfo = new InetInfo(type.typeID, node->getId(), type.context);
00271 
00272     newinfo->setAccessNetModule(newAccessNetModule);
00273     newinfo->setNodeID(node->getId());
00274 
00275     //add node to a randomly chosen access net bootstrap oracle
00276     globalNodeList->addPeer(newAccessNetModule->addOverlayNode(node, true), newinfo);
00277 
00278     // inform the notification board about the migration
00279     NotificationBoard* nb = check_and_cast<NotificationBoard*>(node->getSubmodule("notificationBoard"));
00280     nb->fireChangeNotification(NF_OVERLAY_TRANSPORTADDRESS_CHANGED);
00281 }
00282 
00283 void InetUnderlayConfigurator::handleTimerEvent(cMessage* msg)
00284 {
00285     Enter_Method_Silent();
00286 
00287     // get next scheduled node from the kill list
00288     IPvXAddress addr = killList.back();
00289     killList.pop_back();
00290 
00291     AccessNet* accessNetModule = NULL;
00292     int nodeID = -1;
00293 
00294     InetInfo* info = dynamic_cast<InetInfo*>(globalNodeList->getPeerInfo(addr));
00295     if(info != NULL) {
00296         accessNetModule = info->getAccessNetModule();
00297         nodeID = info->getNodeID();
00298     } else {
00299         opp_error("IPv4UnderlayConfigurator: Trying to kill node with nonexistant TransportAddress!");
00300     }
00301 
00302     scheduledID.erase(nodeID);
00303     globalNodeList->killPeer(addr);
00304 
00305     cModule* node = accessNetModule->removeOverlayNode(nodeID);
00306 
00307     if(node == NULL)
00308         opp_error("IPv4UnderlayConfigurator: Trying to remove node which is nonexistant in AccessNet!");
00309 
00310     node->callFinish();
00311     node->deleteModule();
00312 
00313     delete msg;
00314 }
00315 
00316 void InetUnderlayConfigurator::setDisplayString()
00317 {
00318     char buf[80];
00319     sprintf(buf, "%i overlay terminals\n%i access router\n%i overlay access router",
00320             overlayTerminalCount, accessRouterNum, overlayAccessRouterNum);
00321     getDisplayString().setTagArg("t", 0, buf);
00322 }
00323 
00324 void InetUnderlayConfigurator::finishUnderlay()
00325 {
00326     // statistics
00327     recordScalar("Terminals added", numCreated);
00328     recordScalar("Terminals removed", numKilled);
00329 
00330     if (!isInInitPhase()) {
00331         struct timeval now, diff;
00332         gettimeofday(&now, NULL);
00333         timersub(&now, &initFinishedTime, &diff);
00334         printf("Simulation time: %li.%06li\n", diff.tv_sec, diff.tv_usec);
00335     }
00336 }
00337 
00338 void InetUnderlayConfigurator::setUpIPv4(cTopology &topo)
00339 {
00340     // Assign IP addresses to all router modules.
00341     std::vector<uint32> nodeAddresses;
00342     nodeAddresses.resize(topo.getNumNodes());
00343 
00344     // IP addresses for backbone
00345     // Take start IP from config file
00346     // FIXME: Make Netmask for Routers configurable!
00347     uint32 lowIPBoundary = IPAddress(par("startIPv4").stringValue()).getInt();
00348 
00349     // uint32 lowIPBoundary = uint32((1 << 24) + 1);
00350     int numIPNodes = 0;
00351 
00352     for (int i = 0; i < topo.getNumNodes(); i++) {
00353         ++numIPNodes;
00354 
00355         uint32 addr = lowIPBoundary + uint32(numIPNodes << 16);
00356         nodeAddresses[i] = addr;
00357 
00358         // update ip display string
00359         if (ev.isGUI()) {
00360             topo.getNode(i)->getModule()->getDisplayString().insertTag("t", 0);
00361             topo.getNode(i)->getModule()->getDisplayString().setTagArg("t", 0,
00362                                     const_cast<char*>(IPAddress(addr).str().c_str()));
00363             topo.getNode(i)->getModule()->getDisplayString().setTagArg("t", 1, "l");
00364             topo.getNode(i)->getModule()->getDisplayString().setTagArg("t", 2, "red");
00365         }
00366 
00367         // find interface table and assign address to all (non-loopback) interfaces
00368         IInterfaceTable* ift = IPAddressResolver().interfaceTableOf(topo.getNode(i)->getModule());
00369 
00370         for ( int k = 0; k < ift->getNumInterfaces(); k++ ) {
00371             InterfaceEntry* ie = ift->getInterface(k);
00372             if (!ie->isLoopback()) {
00373                 ie->ipv4Data()->setIPAddress(IPAddress(addr));
00374                 // full address must match for local delivery
00375                 ie->ipv4Data()->setNetmask(IPAddress::ALLONES_ADDRESS);
00376             }
00377         }
00378     }
00379 
00380     // Fill in routing tables.
00381     for (int i = 0; i < topo.getNumNodes(); i++) {
00382         cTopology::Node* destNode = topo.getNode(i);
00383         uint32 destAddr = nodeAddresses[i];
00384 
00385         // calculate shortest paths from everywhere towards destNode
00386         topo.calculateUnweightedSingleShortestPathsTo(destNode);
00387 
00388         // add overlayAccessRouters and overlayBackboneRouters
00389         // to the GlobalNodeList
00390         if ((strcmp(destNode->getModule()->getName(), "overlayBackboneRouter") == 0) ||
00391                 (strcmp(destNode->getModule()->getName(), "overlayAccessRouter") == 0)) {
00392             //add node to bootstrap oracle
00393             PeerInfo* info = new PeerInfo(0, destNode->getModule()->getId(), NULL);
00394             globalNodeList->addPeer(IPvXAddress(nodeAddresses[i]), info);
00395         }
00396 
00397 
00398         // If destNode is the outRouter, add a default route
00399         // to outside network via the TunOutDevice and a route to the
00400         // Gateway
00401         if ( strcmp(destNode->getModule()->getName(), "outRouter" ) == 0 ) {
00402             IPRoute* defRoute = new IPRoute();
00403             defRoute->setHost(IPAddress::UNSPECIFIED_ADDRESS);
00404             defRoute->setNetmask(IPAddress::UNSPECIFIED_ADDRESS);
00405             defRoute->setGateway(IPAddress(par("gatewayIP").stringValue()));
00406             defRoute->setInterface(IPAddressResolver().interfaceTableOf(destNode->getModule())->getInterfaceByName("tunDev"));
00407             defRoute->setType(IPRoute::REMOTE);
00408             defRoute->setSource(IPRoute::MANUAL);
00409             IPAddressResolver().routingTableOf(destNode->getModule())->addRoute(defRoute);
00410 
00411             IPRoute* gwRoute = new IPRoute();
00412             gwRoute->setHost(IPAddress(par("gatewayIP").stringValue()));
00413             gwRoute->setNetmask(IPAddress(255, 255, 255, 255));
00414             gwRoute->setInterface(IPAddressResolver().interfaceTableOf(destNode->getModule())->getInterfaceByName("tunDev"));
00415             gwRoute->setType(IPRoute::DIRECT);
00416             gwRoute->setSource(IPRoute::MANUAL);
00417             IPAddressResolver().routingTableOf(destNode->getModule())->addRoute(gwRoute);
00418         }
00419 
00420         // add route (with host=destNode) to every routing table in the network
00421         for (int j = 0; j < topo.getNumNodes(); j++) {
00422             // continue if same node
00423             if (i == j)
00424                 continue;
00425 
00426             // cancel simulation if node is not connected with destination
00427             cTopology::Node* atNode = topo.getNode(j);
00428 
00429             if (atNode->getNumPaths() == 0) {
00430                 error((std::string(atNode->getModule()->getName()) + ": Network is not entirely connected."
00431                         "Please increase your value for the "
00432                         "connectivity parameter").c_str());
00433             }
00434 
00435             //
00436             // Add routes at the atNode.
00437             //
00438 
00439             // find atNode's interface and routing table
00440             IInterfaceTable* ift = IPAddressResolver().interfaceTableOf(atNode->getModule());
00441             IRoutingTable* rt = IPAddressResolver().routingTableOf(atNode->getModule());
00442 
00443             // find atNode's interface entry for the next hop node
00444             int outputGateId = atNode->getPath(0)->getLocalGate()->getId();
00445             InterfaceEntry *ie = ift->getInterfaceByNodeOutputGateId(outputGateId);
00446 
00447             // find the next hop node on the path towards destNode
00448             cModule* next_hop = atNode->getPath(0)->getRemoteNode()->getModule();
00449             IPAddress next_hop_ip = IPAddressResolver().addressOf(next_hop).get4();
00450 
00451 
00452             // Requirement 1: Each router has exactly one routing entry
00453             // (netmask 255.255.0.0) to each other router
00454             IPRoute* re = new IPRoute();
00455 
00456             re->setHost(IPAddress(destAddr));
00457             re->setInterface(ie);
00458             re->setSource(IPRoute::MANUAL);
00459             re->setNetmask(IPAddress(255, 255, 0, 0));
00460             re->setGateway(IPAddress(next_hop_ip));
00461             re->setType(IPRoute::REMOTE);
00462 
00463             rt->addRoute(re);
00464 
00465             // Requirement 2: Each router has a point-to-point routing
00466             // entry (netmask 255.255.255.255) for each immediate neighbour
00467             if (atNode->getDistanceToTarget() == 1) {
00468                 IPRoute* re2 = new IPRoute();
00469 
00470                 re2->setHost(IPAddress(destAddr));
00471                 re2->setInterface(ie);
00472                 re2->setSource(IPRoute::MANUAL);
00473                 re2->setNetmask(IPAddress(255, 255, 255, 255));
00474                 re2->setType(IPRoute::DIRECT);
00475 
00476                 rt->addRoute(re2);
00477             }
00478 
00479             // If destNode is the outRouter, add a default route
00480             // to the next hop in the direction of the outRouter
00481             if (strcmp(destNode->getModule()->getName(), "outRouter" ) == 0) {
00482                 IPRoute* defRoute = new IPRoute();
00483                 defRoute->setHost(IPAddress::UNSPECIFIED_ADDRESS);
00484                 defRoute->setNetmask(IPAddress::UNSPECIFIED_ADDRESS);
00485                 defRoute->setGateway(IPAddress(next_hop_ip));
00486                 defRoute->setInterface(ie);
00487                 defRoute->setType(IPRoute::REMOTE);
00488                 defRoute->setSource(IPRoute::MANUAL);
00489 
00490                 rt->addRoute(defRoute);
00491             }
00492         }
00493     }
00494 }
00495 
00496 void InetUnderlayConfigurator::setUpIPv6(cTopology &topo)
00497 {
00498     // Assign IP addresses to all router modules.
00499     std::vector<IPv6Words> nodeAddresses;
00500     nodeAddresses.resize(topo.getNumNodes());
00501 
00502     // IP addresses for backbone
00503     // Take start IP from config file
00504     // FIXME: Make Netmask for Routers configurable!
00505     IPv6Words lowIPBoundary(IPv6Address(par("startIPv6").stringValue()));
00506 
00507     // uint32 lowIPBoundary = uint32((1 << 24) + 1);
00508     int numIPNodes = 0;
00509 
00510     for (int i = 0; i < topo.getNumNodes(); i++) {
00511         ++numIPNodes;
00512 
00513         IPv6Words addr = lowIPBoundary;
00514         addr.d0 += numIPNodes;
00515         nodeAddresses[i] = addr;
00516 
00517         // update ip display string
00518         if (ev.isGUI()) {
00519             topo.getNode(i)->getModule()->getDisplayString().insertTag("t", 0);
00520             topo.getNode(i)->getModule()->getDisplayString().setTagArg("t", 0,
00521                                     const_cast<char*>(IPv6Address(addr.d0, addr.d1, addr.d2, addr.d3).str().c_str()));
00522             topo.getNode(i)->getModule()->getDisplayString().setTagArg("t", 1, "l");
00523             topo.getNode(i)->getModule()->getDisplayString().setTagArg("t", 2, "red");
00524         }
00525 
00526         // find interface table and assign address to all (non-loopback) interfaces
00527         IInterfaceTable* ift = IPAddressResolver().interfaceTableOf(topo.getNode(i)->getModule());
00528 
00529         for ( int k = 0; k < ift->getNumInterfaces(); k++ ) {
00530             InterfaceEntry* ie = ift->getInterface(k);
00531             if (!ie->isLoopback() && ie->ipv6Data()) {
00532                 //ie->ipv6Data()->assignAddress(IPv6Address(addr.d0, addr.d1, addr.d2, addr.d3), false, 0, 0);
00533                 // full address must match for local delivery
00534                 IPv6Address prefix(addr.d0, addr.d1, addr.d2, addr.d3);
00535                 IPv6InterfaceData::AdvPrefix p;
00536                 p.prefix = prefix;
00537                 p.prefixLength = 32;
00538                 p.advAutonomousFlag = true;
00539                 p.advPreferredLifetime = 0;
00540                 p.advValidLifetime = 0;
00541                 p.advOnLinkFlag = true;
00542                 ie->ipv6Data()->addAdvPrefix(p);
00543                 ie->setMACAddress(MACAddress::generateAutoAddress());
00544 
00545                 ie->ipv6Data()->assignAddress(prefix,false, 0, 0);
00546 
00547                 if (ie->ipv6Data()->getLinkLocalAddress().isUnspecified()) {
00548                     ie->ipv6Data()->assignAddress(IPv6Address::formLinkLocalAddress(ie->getInterfaceToken()),false, 0, 0);
00549                 }
00550             }
00551         }
00552     }
00553 
00554     // Fill in routing tables.
00555     for (int i = 0; i < topo.getNumNodes(); i++) {
00556         cTopology::Node* destNode = topo.getNode(i);
00557         IPv6Words destAddr = nodeAddresses[i];
00558 
00559         // calculate shortest paths from everywhere towards destNode
00560         topo.calculateUnweightedSingleShortestPathsTo(destNode);
00561 
00562         // add overlayAccessRouters and overlayBackboneRouters
00563         // to the GlobalNodeList
00564         if ((strcmp(destNode->getModule()->getName(), "overlayBackboneRouter") == 0) ||
00565                 (strcmp(destNode->getModule()->getName(), "overlayAccessRouter") == 0)) {
00566             //add node to bootstrap oracle
00567             PeerInfo* info = new PeerInfo(0, destNode->getModule()->getId(), NULL);
00568             globalNodeList->addPeer(IPvXAddress(IPv6Address(nodeAddresses[i].d0, nodeAddresses[i].d1, nodeAddresses[i].d2, nodeAddresses[i].d3)), info);
00569         }
00570 
00571         // add route (with host=destNode) to every routing table in the network
00572         for (int j = 0; j < topo.getNumNodes(); j++) {
00573             // continue if same node
00574             if (i == j)
00575                 continue;
00576 
00577             // cancel simulation if node is not connected with destination
00578             cTopology::Node* atNode = topo.getNode(j);
00579 
00580             if (atNode->getNumPaths() == 0) {
00581                 error((std::string(atNode->getModule()->getName()) + ": Network is not entirely connected."
00582                         "Please increase your value for the "
00583                         "connectivity parameter").c_str());
00584             }
00585 
00586             //
00587             // Add routes at the atNode.
00588             //
00589 
00590             // find atNode's interface and routing table
00591             IInterfaceTable* ift = IPAddressResolver().interfaceTableOf(atNode->getModule());
00592             RoutingTable6* rt = IPAddressResolver().routingTable6Of(atNode->getModule());
00593 
00594             // find atNode's interface entry for the next hop node
00595             int outputGateId = atNode->getPath(0)->getLocalGate()->getId();
00596             InterfaceEntry *ie = ift->getInterfaceByNodeOutputGateId(outputGateId);
00597 
00598             // find the next hop node on the path towards destNode
00599             cModule* next_hop = atNode->getPath(0)->getRemoteNode()->getModule();
00600             int destGateId = destNode->getLinkIn(0)->getLocalGateId();
00601             IInterfaceTable* destIft = IPAddressResolver().interfaceTableOf(destNode->getModule());
00602             int remoteGateId = atNode->getPath(0)->getRemoteGateId();
00603             IInterfaceTable* remoteIft = IPAddressResolver().interfaceTableOf(next_hop);
00604             IPv6Address next_hop_ip = remoteIft->getInterfaceByNodeInputGateId(remoteGateId)->ipv6Data()->getLinkLocalAddress();
00605             IPv6InterfaceData::AdvPrefix destPrefix = destIft->getInterfaceByNodeInputGateId(destGateId)->ipv6Data()->getAdvPrefix(0);
00606 
00607             // create routing entry for next hop
00608             rt->addStaticRoute(destPrefix.prefix, destPrefix.prefixLength, ie->getInterfaceId(), next_hop_ip);
00609 
00610         }
00611     }
00612 }
00613 
00614 
00624 double uniform2(double start, double end, double index, double new_calc)
00625 {
00626     static std::vector<double> value;
00627     if ( (unsigned int)index >= value.size() )
00628         value.resize((int)index + 1);
00629     if ( new_calc == 1 )
00630         value[(int)index] = uniform(start, end);
00631     return value[(int)index];
00632 };
00633 
00643 double intuniform2(double start, double end, double index, double new_calc)
00644 {
00645     static std::vector<double> value;
00646     if ( (unsigned int)index >= value.size() )
00647         value.resize((int)index + 1);
00648     if ( new_calc == 1 )
00649         value[(int)index] = (double)intuniform((int)start, (int)end);
00650     return value[(int)index];
00651 };
00652 
00653 Define_Function(uniform2, 4);
00654 Define_Function(intuniform2, 4);