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 <IInterfaceTable.h>
00032 #include <IPAddressResolver.h>
00033 #include <IPv4InterfaceData.h>
00034 #include <NotificationBoard.h>
00035
00036
00037 #include <InetInfo.h>
00038
00039 Define_Module(InetUnderlayConfigurator);
00040
00041 void InetUnderlayConfigurator::initializeUnderlay(int stage)
00042 {
00043
00044 if (stage == MIN_STAGE_UNDERLAY) {
00045
00046 cTopology topo("topo");
00047 topo.extractByProperty("node");
00048
00049
00050 std::vector<uint32> nodeAddresses;
00051 nodeAddresses.resize(topo.getNumNodes());
00052
00053
00054
00055
00056 uint32 lowIPBoundary = IPAddress(par("startIP").stringValue()).getInt();
00057
00058
00059 int numIPNodes = 0;
00060
00061 for (int i = 0; i < topo.getNumNodes(); i++) {
00062 ++numIPNodes;
00063
00064 uint32 addr = lowIPBoundary + uint32(numIPNodes << 16);
00065 nodeAddresses[i] = addr;
00066
00067
00068 if (ev.isGUI()) {
00069 topo.getNode(i)->getModule()->getDisplayString().insertTag("t", 0);
00070 topo.getNode(i)->getModule()->getDisplayString().setTagArg("t", 0,
00071 const_cast<char*>(IPAddress(addr).str().c_str()));
00072 topo.getNode(i)->getModule()->getDisplayString().setTagArg("t", 1, "l");
00073 topo.getNode(i)->getModule()->getDisplayString().setTagArg("t", 2, "red");
00074 }
00075
00076
00077 IInterfaceTable* ift = IPAddressResolver().interfaceTableOf(topo.getNode(i)->getModule());
00078
00079 for ( int k = 0; k < ift->getNumInterfaces(); k++ ) {
00080 InterfaceEntry* ie = ift->getInterface(k);
00081 if (!ie->isLoopback()) {
00082 ie->ipv4Data()->setIPAddress(IPAddress(addr));
00083
00084 ie->ipv4Data()->setNetmask(IPAddress::ALLONES_ADDRESS);
00085 }
00086 }
00087 }
00088
00089
00090 for (int i = 0; i < topo.getNumNodes(); i++) {
00091 cTopology::Node* destNode = topo.getNode(i);
00092 uint32 destAddr = nodeAddresses[i];
00093
00094
00095 topo.calculateUnweightedSingleShortestPathsTo(destNode);
00096
00097
00098
00099 if ((strcmp(destNode->getModule()->getName(), "overlayBackboneRouter") == 0) ||
00100 (strcmp(destNode->getModule()->getName(), "overlayAccessRouter") == 0)) {
00101
00102 PeerInfo* info = new PeerInfo(0, destNode->getModule()->getId(), NULL);
00103 globalNodeList->addPeer(IPvXAddress(nodeAddresses[i]), info);
00104 }
00105
00106
00107
00108
00109
00110 if ( strcmp(destNode->getModule()->getName(), "outRouter" ) == 0 ) {
00111 IPRoute* defRoute = new IPRoute();
00112 defRoute->setHost(IPAddress::UNSPECIFIED_ADDRESS);
00113 defRoute->setNetmask(IPAddress::UNSPECIFIED_ADDRESS);
00114 defRoute->setGateway(IPAddress(par("gatewayIP").stringValue()));
00115 defRoute->setInterface(IPAddressResolver().interfaceTableOf(destNode->getModule())->getInterfaceByName("tunDev"));
00116 defRoute->setType(IPRoute::REMOTE);
00117 defRoute->setSource(IPRoute::MANUAL);
00118 IPAddressResolver().routingTableOf(destNode->getModule())->addRoute(defRoute);
00119
00120 IPRoute* gwRoute = new IPRoute();
00121 gwRoute->setHost(IPAddress(par("gatewayIP").stringValue()));
00122 gwRoute->setNetmask(IPAddress(255, 255, 255, 255));
00123 gwRoute->setInterface(IPAddressResolver().interfaceTableOf(destNode->getModule())->getInterfaceByName("tunDev"));
00124 gwRoute->setType(IPRoute::DIRECT);
00125 gwRoute->setSource(IPRoute::MANUAL);
00126 IPAddressResolver().routingTableOf(destNode->getModule())->addRoute(gwRoute);
00127 }
00128
00129
00130 for (int j = 0; j < topo.getNumNodes(); j++) {
00131
00132 if (i == j)
00133 continue;
00134
00135
00136 cTopology::Node* atNode = topo.getNode(j);
00137
00138 if (atNode->getNumPaths() == 0) {
00139 error((std::string(atNode->getModule()->getName()) + ": Network is not entirely connected."
00140 "Please increase your value for the "
00141 "connectivity parameter").c_str());
00142 }
00143
00144
00145
00146
00147
00148
00149 IInterfaceTable* ift = IPAddressResolver().interfaceTableOf(atNode->getModule());
00150 IRoutingTable* rt = IPAddressResolver().routingTableOf(atNode->getModule());
00151
00152
00153 int outputGateId = atNode->getPath(0)->getLocalGate()->getId();
00154 InterfaceEntry *ie = ift->getInterfaceByNodeOutputGateId(outputGateId);
00155
00156
00157 cModule* next_hop = atNode->getPath(0)->getRemoteNode()->getModule();
00158 IPAddress next_hop_ip = IPAddressResolver().addressOf(next_hop).get4();
00159
00160
00161
00162
00163 IPRoute* re = new IPRoute();
00164
00165 re->setHost(IPAddress(destAddr));
00166 re->setInterface(ie);
00167 re->setSource(IPRoute::MANUAL);
00168 re->setNetmask(IPAddress(255, 255, 0, 0));
00169 re->setGateway(IPAddress(next_hop_ip));
00170 re->setType(IPRoute::REMOTE);
00171
00172 rt->addRoute(re);
00173
00174
00175
00176 if (atNode->getDistanceToTarget() == 1) {
00177 IPRoute* re2 = new IPRoute();
00178
00179 re2->setHost(IPAddress(destAddr));
00180 re2->setInterface(ie);
00181 re2->setSource(IPRoute::MANUAL);
00182 re2->setNetmask(IPAddress(255, 255, 255, 255));
00183 re2->setType(IPRoute::DIRECT);
00184
00185 rt->addRoute(re2);
00186 }
00187
00188
00189
00190 if (strcmp(destNode->getModule()->getName(), "outRouter" ) == 0) {
00191 IPRoute* defRoute = new IPRoute();
00192 defRoute->setHost(IPAddress::UNSPECIFIED_ADDRESS);
00193 defRoute->setNetmask(IPAddress::UNSPECIFIED_ADDRESS);
00194 defRoute->setGateway(IPAddress(next_hop_ip));
00195 defRoute->setInterface(ie);
00196 defRoute->setType(IPRoute::REMOTE);
00197 defRoute->setSource(IPRoute::MANUAL);
00198
00199 rt->addRoute(defRoute);
00200 }
00201 }
00202 }
00203 }
00204
00205 else if(stage == MAX_STAGE_UNDERLAY) {
00206
00207 accessRouterNum = getParentModule()->par("accessRouterNum");
00208 overlayAccessRouterNum = getParentModule()->par("overlayAccessRouterNum");
00209
00210
00211 overlayTerminalCount = 0;
00212
00213 numCreated = 0;
00214 numKilled = 0;
00215
00216
00217 cModule* node;
00218 for (int i = 0; i < accessRouterNum; i++) {
00219 node = getParentModule()->getSubmodule("accessRouter", i);
00220 accessNode.push_back( node );
00221 }
00222
00223 for (int i = 0; i < overlayAccessRouterNum; i++) {
00224 node = getParentModule()->getSubmodule("overlayAccessRouter", i);
00225 accessNode.push_back( node );
00226 }
00227
00228
00229 WATCH_PTRVECTOR(accessNode);
00230 }
00231 }
00232
00233 TransportAddress* InetUnderlayConfigurator::createNode(NodeType type, bool initialize)
00234 {
00235 Enter_Method_Silent();
00236
00237 std::string nameStr = "overlayTerminal";
00238 if( churnGenerator.size() > 1 ){
00239 nameStr += "-" + convertToString<uint32_t>(type.typeID);
00240 }
00241 cModuleType* moduleType = cModuleType::get(type.terminalType.c_str());
00242 cModule* node = moduleType->create(nameStr.c_str(), getParentModule(),
00243 numCreated + 1, numCreated);
00244
00245 if (type.channelTypesTx.size() > 0) {
00246 throw cRuntimeError("InetUnderlayConfigurator::createNode(): Setting "
00247 "channel types via the churn generator is not allowed "
00248 "with the InetUnderlay. Use **.accessNet.channelTypes instead!");
00249 }
00250
00251 node->par("overlayType").setStringValue(type.overlayType.c_str());
00252 node->par("tier1Type").setStringValue(type.tier1Type.c_str());
00253 node->par("tier2Type").setStringValue(type.tier2Type.c_str());
00254 node->par("tier3Type").setStringValue(type.tier3Type.c_str());
00255
00256 node->setGateSize("pppg", 1);
00257
00258 std::string displayString;
00259
00260 if ((type.typeID > 1) && (type.typeID <= (NUM_COLORS + 1))) {
00261 ((displayString += "i=device/wifilaptop_l,")
00262 += colorNames[type.typeID - 2])
00263 += ",40;i2=block/circle_s";
00264 } else {
00265 displayString = "i=device/wifilaptop_l;i2=block/circle_s";
00266 }
00267
00268 node->finalizeParameters();
00269 node->setDisplayString(displayString.c_str());
00270
00271 node->buildInside();
00272 node->scheduleStart(simTime());
00273
00274
00275 InetInfo* info = new InetInfo(type.typeID, node->getId(), type.context);
00276 AccessNet* accessNet= check_and_cast<AccessNet*>
00277 (accessNode[intuniform(0, accessNode.size() - 1)]
00278 ->getSubmodule("accessNet"));
00279 info->setAccessNetModule(accessNet);
00280
00281 info->setNodeID(accessNet->addOverlayNode(node));
00282
00283
00284 globalNodeList->addPeer(IPAddressResolver().addressOf(node), info);
00285
00286
00287
00288 if (!initialize) {
00289 for (int i = MAX_STAGE_UNDERLAY + 1; i < NUM_STAGES_ALL; i++) {
00290 node->callInitialize(i);
00291 }
00292 }
00293
00294 overlayTerminalCount++;
00295 numCreated++;
00296
00297 churnGenerator[type.typeID - 1]->terminalCount++;
00298
00299 TransportAddress *address = new TransportAddress(
00300 IPAddressResolver().addressOf(node));
00301
00302
00303 setDisplayString();
00304
00305 return address;
00306 }
00307
00308
00309 void InetUnderlayConfigurator::preKillNode(NodeType type, TransportAddress* addr)
00310 {
00311 Enter_Method_Silent();
00312
00313 AccessNet* accessNetModule = NULL;
00314 int nodeID;
00315 InetInfo* info;
00316
00317
00318 if (addr == NULL) {
00319 addr = globalNodeList->getRandomAliveNode(type.typeID);
00320
00321 if (addr == NULL) {
00322
00323 std::cout << "all nodes are already prekilled" << std::endl;
00324 return;
00325 }
00326 }
00327
00328
00329 info = dynamic_cast<InetInfo*>(globalNodeList->getPeerInfo(*addr));
00330
00331 if (info != NULL) {
00332 accessNetModule = info->getAccessNetModule();
00333 nodeID = info->getNodeID();
00334 } else {
00335 opp_error("IPv4UnderlayConfigurator: Trying to pre kill node "
00336 "with nonexistant TransportAddress!");
00337 }
00338
00339 uint32_t effectiveType = info->getTypeID();
00340
00341
00342 if(scheduledID.count(nodeID))
00343 return;
00344
00345 cModule* node = accessNetModule->getOverlayNode(nodeID);
00346 globalNodeList->removePeer(IPAddressResolver().addressOf(node));
00347
00348
00349 killList.push_front(IPAddressResolver().addressOf(node));
00350 scheduledID.insert(nodeID);
00351
00352 overlayTerminalCount--;
00353 numKilled++;
00354
00355 churnGenerator[effectiveType - 1]->terminalCount--;
00356
00357
00358 setDisplayString();
00359
00360
00361 NotificationBoard* nb = check_and_cast<NotificationBoard*>(
00362 node->getSubmodule("notificationBoard"));
00363 nb->fireChangeNotification(NF_OVERLAY_NODE_LEAVE);
00364
00365 double random = uniform(0, 1);
00366
00367 if (random < gracefulLeaveProbability) {
00368 nb->fireChangeNotification(NF_OVERLAY_NODE_GRACEFUL_LEAVE);
00369 }
00370
00371 cMessage* msg = new cMessage();
00372 scheduleAt(simTime() + gracefulLeaveDelay, msg);
00373
00374 }
00375
00376 void InetUnderlayConfigurator::migrateNode(NodeType type, TransportAddress* addr)
00377 {
00378 Enter_Method_Silent();
00379
00380 AccessNet* accessNetModule = NULL;
00381 int nodeID = -1;
00382 InetInfo* info;
00383
00384
00385 if(addr == NULL) {
00386 info = dynamic_cast<InetInfo*>(globalNodeList->getRandomPeerInfo(type.typeID));
00387 } else {
00388
00389 info = dynamic_cast<InetInfo*>(globalNodeList->getPeerInfo(*addr));
00390 }
00391
00392 if(info != NULL) {
00393 accessNetModule = info->getAccessNetModule();
00394 nodeID = info->getNodeID();
00395 } else {
00396 opp_error("IPv4UnderlayConfigurator: Trying to pre kill node with nonexistant TransportAddress!");
00397 }
00398
00399
00400 if(scheduledID.count(nodeID))
00401 return;
00402
00403 cModule* node = accessNetModule->removeOverlayNode(nodeID);
00404
00405 if(node == NULL)
00406 opp_error("IPv4UnderlayConfigurator: Trying to remove node which is nonexistant in AccessNet!");
00407
00408
00409 globalNodeList->killPeer(IPAddressResolver().addressOf(node));
00410
00411 node->bubble("I am migrating!");
00412
00413
00414 AccessNet* newAccessNetModule;
00415
00416 do {
00417 newAccessNetModule = check_and_cast<AccessNet*>(accessNode[intuniform(0, accessNode.size() - 1)]->getSubmodule("accessNet"));
00418 } while((newAccessNetModule == accessNetModule) && (accessNode.size() != 1));
00419
00420
00421 InetInfo* newinfo = new InetInfo(type.typeID, node->getId(), type.context);
00422
00423 newinfo->setAccessNetModule(newAccessNetModule);
00424 newinfo->setNodeID(newAccessNetModule->addOverlayNode(node, true));
00425
00426
00427 globalNodeList->addPeer(IPAddressResolver().addressOf(node), newinfo);
00428
00429
00430 NotificationBoard* nb = check_and_cast<NotificationBoard*>(node->getSubmodule("notificationBoard"));
00431 nb->fireChangeNotification(NF_OVERLAY_TRANSPORTADDRESS_CHANGED);
00432 }
00433
00434 void InetUnderlayConfigurator::handleTimerEvent(cMessage* msg)
00435 {
00436 Enter_Method_Silent();
00437
00438
00439 IPvXAddress addr = killList.back();
00440 killList.pop_back();
00441
00442 AccessNet* accessNetModule = NULL;
00443 int nodeID = -1;
00444
00445 InetInfo* info = dynamic_cast<InetInfo*>(globalNodeList->getPeerInfo(addr));
00446 if(info != NULL) {
00447 accessNetModule = info->getAccessNetModule();
00448 nodeID = info->getNodeID();
00449 } else {
00450 opp_error("IPv4UnderlayConfigurator: Trying to kill node with nonexistant TransportAddress!");
00451 }
00452
00453 scheduledID.erase(nodeID);
00454 globalNodeList->killPeer(addr);
00455
00456 cModule* node = accessNetModule->removeOverlayNode(nodeID);
00457
00458 if(node == NULL)
00459 opp_error("IPv4UnderlayConfigurator: Trying to remove node which is nonexistant in AccessNet!");
00460
00461 node->callFinish();
00462 node->deleteModule();
00463
00464 delete msg;
00465 }
00466
00467 void InetUnderlayConfigurator::setDisplayString()
00468 {
00469 char buf[80];
00470 sprintf(buf, "%i overlay terminals\n%i access router\n%i overlay access router",
00471 overlayTerminalCount, accessRouterNum, overlayAccessRouterNum);
00472 getDisplayString().setTagArg("t", 0, buf);
00473 }
00474
00475 void InetUnderlayConfigurator::finishUnderlay()
00476 {
00477
00478 recordScalar("Terminals added", numCreated);
00479 recordScalar("Terminals removed", numKilled);
00480
00481 if (!isInInitPhase()) {
00482 struct timeval now, diff;
00483 gettimeofday(&now, NULL);
00484 timersub(&now, &initFinishedTime, &diff);
00485 printf("Simulation time: %li.%06li\n", diff.tv_sec, diff.tv_usec);
00486 }
00487 }
00488
00489
00499 double uniform2(double start, double end, double index, double new_calc)
00500 {
00501 static std::vector<double> value;
00502 if ( (unsigned int)index >= value.size() )
00503 value.resize((int)index + 1);
00504 if ( new_calc == 1 )
00505 value[(int)index] = uniform(start, end);
00506 return value[(int)index];
00507 };
00508
00518 double intuniform2(double start, double end, double index, double new_calc)
00519 {
00520 static std::vector<double> value;
00521 if ( (unsigned int)index >= value.size() )
00522 value.resize((int)index + 1);
00523 if ( new_calc == 1 )
00524 value[(int)index] = (double)intuniform((int)start, (int)end);
00525 return value[(int)index];
00526 };
00527
00528 Define_Function(uniform2, 4);
00529 Define_Function(intuniform2, 4);