00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
00046 if (stage == MIN_STAGE_UNDERLAY) {
00047
00048 cTopology topo("topo");
00049 topo.extractByProperty("node");
00050
00051 if (par("useIPv6Addresses").boolValue()) {
00052 setUpIPv6(topo);
00053
00054 } else {
00055 setUpIPv4(topo);
00056 }
00057 }
00058
00059 else if(stage == MAX_STAGE_UNDERLAY) {
00060
00061 accessRouterNum = getParentModule()->par("accessRouterNum");
00062 overlayAccessRouterNum = getParentModule()->par("overlayAccessRouterNum");
00063
00064
00065 overlayTerminalCount = 0;
00066
00067 numCreated = 0;
00068 numKilled = 0;
00069
00070
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
00083 WATCH_PTRVECTOR(accessNode);
00084 }
00085 }
00086
00087 TransportAddress* InetUnderlayConfigurator::createNode(NodeType type, bool initialize)
00088 {
00089 Enter_Method_Silent();
00090
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
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
00133 globalNodeList->addPeer(accessNet->addOverlayNode(node), info);
00134
00135
00136
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
00152 setDisplayString();
00153
00154 return address;
00155 }
00156
00157
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
00167 if (addr == NULL) {
00168 addr = globalNodeList->getRandomAliveNode(type.typeID);
00169
00170 if (addr == NULL) {
00171
00172 std::cout << "all nodes are already prekilled" << std::endl;
00173 return;
00174 }
00175 }
00176
00177
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
00191 if(scheduledID.count(nodeID))
00192 return;
00193
00194 cModule* node = accessNetModule->getOverlayNode(nodeID);
00195 globalNodeList->removePeer(IPAddressResolver().addressOf(node));
00196
00197
00198 killList.push_front(IPAddressResolver().addressOf(node));
00199 scheduledID.insert(nodeID);
00200
00201 overlayTerminalCount--;
00202 numKilled++;
00203
00204 churnGenerator[effectiveType]->terminalCount--;
00205
00206
00207 setDisplayString();
00208
00209
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
00234 if(addr == NULL) {
00235 info = dynamic_cast<InetInfo*>(globalNodeList->getRandomPeerInfo(type.typeID));
00236 } else {
00237
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
00249 if(scheduledID.count(nodeID))
00250 return;
00251
00252 cModule* node = accessNetModule->removeOverlayNode(nodeID);
00253
00254 if(node == NULL)
00255 opp_error("IPv4UnderlayConfigurator: Trying to remove node which is nonexistant in AccessNet!");
00256
00257
00258 globalNodeList->killPeer(IPAddressResolver().addressOf(node));
00259
00260 node->bubble("I am migrating!");
00261
00262
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
00270 InetInfo* newinfo = new InetInfo(type.typeID, node->getId(), type.context);
00271
00272 newinfo->setAccessNetModule(newAccessNetModule);
00273 newinfo->setNodeID(node->getId());
00274
00275
00276 globalNodeList->addPeer(newAccessNetModule->addOverlayNode(node, true), newinfo);
00277
00278
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
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
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
00341 std::vector<uint32> nodeAddresses;
00342 nodeAddresses.resize(topo.getNumNodes());
00343
00344
00345
00346
00347 uint32 lowIPBoundary = IPAddress(par("startIPv4").stringValue()).getInt();
00348
00349
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
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
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
00375 ie->ipv4Data()->setNetmask(IPAddress::ALLONES_ADDRESS);
00376 }
00377 }
00378 }
00379
00380
00381 for (int i = 0; i < topo.getNumNodes(); i++) {
00382 cTopology::Node* destNode = topo.getNode(i);
00383 uint32 destAddr = nodeAddresses[i];
00384
00385
00386 topo.calculateUnweightedSingleShortestPathsTo(destNode);
00387
00388
00389
00390 if ((strcmp(destNode->getModule()->getName(), "overlayBackboneRouter") == 0) ||
00391 (strcmp(destNode->getModule()->getName(), "overlayAccessRouter") == 0)) {
00392
00393 PeerInfo* info = new PeerInfo(0, destNode->getModule()->getId(), NULL);
00394 globalNodeList->addPeer(IPvXAddress(nodeAddresses[i]), info);
00395 }
00396
00397
00398
00399
00400
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
00421 for (int j = 0; j < topo.getNumNodes(); j++) {
00422
00423 if (i == j)
00424 continue;
00425
00426
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
00437
00438
00439
00440 IInterfaceTable* ift = IPAddressResolver().interfaceTableOf(atNode->getModule());
00441 IRoutingTable* rt = IPAddressResolver().routingTableOf(atNode->getModule());
00442
00443
00444 int outputGateId = atNode->getPath(0)->getLocalGate()->getId();
00445 InterfaceEntry *ie = ift->getInterfaceByNodeOutputGateId(outputGateId);
00446
00447
00448 cModule* next_hop = atNode->getPath(0)->getRemoteNode()->getModule();
00449 IPAddress next_hop_ip = IPAddressResolver().addressOf(next_hop).get4();
00450
00451
00452
00453
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
00466
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
00480
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
00499 std::vector<IPv6Words> nodeAddresses;
00500 nodeAddresses.resize(topo.getNumNodes());
00501
00502
00503
00504
00505 IPv6Words lowIPBoundary(IPv6Address(par("startIPv6").stringValue()));
00506
00507
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
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
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
00533
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
00555 for (int i = 0; i < topo.getNumNodes(); i++) {
00556 cTopology::Node* destNode = topo.getNode(i);
00557 IPv6Words destAddr = nodeAddresses[i];
00558
00559
00560 topo.calculateUnweightedSingleShortestPathsTo(destNode);
00561
00562
00563
00564 if ((strcmp(destNode->getModule()->getName(), "overlayBackboneRouter") == 0) ||
00565 (strcmp(destNode->getModule()->getName(), "overlayAccessRouter") == 0)) {
00566
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
00572 for (int j = 0; j < topo.getNumNodes(); j++) {
00573
00574 if (i == j)
00575 continue;
00576
00577
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
00588
00589
00590
00591 IInterfaceTable* ift = IPAddressResolver().interfaceTableOf(atNode->getModule());
00592 RoutingTable6* rt = IPAddressResolver().routingTable6Of(atNode->getModule());
00593
00594
00595 int outputGateId = atNode->getPath(0)->getLocalGate()->getId();
00596 InterfaceEntry *ie = ift->getInterfaceByNodeOutputGateId(outputGateId);
00597
00598
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
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);