00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00023 #include <omnetpp.h>
00024 #include <malloc.h>
00025 #include <vector>
00026 #include <map>
00027
00028 #include <fstream>
00029
00030 #include <NodeHandle.h>
00031 #include "IInterfaceTable.h"
00032 #include "InterfaceEntry.h"
00033 #include "IPv4InterfaceData.h"
00034 #include "IPv6InterfaceData.h"
00035 #include "TransportAddress.h"
00036 #include "IPAddressResolver.h"
00037 #include <cenvir.h>
00038 #include <cxmlelement.h>
00039 #include "ChurnGenerator.h"
00040 #include "GlobalNodeList.h"
00041 #include <StringConvert.h>
00042
00043 #include "SimpleUDP.h"
00044 #include "SimpleTCP.h"
00045
00046 #include "SimpleUnderlayConfigurator.h"
00047
00048 Define_Module(SimpleUnderlayConfigurator);
00049
00050 using namespace std;
00051
00052 SimpleUnderlayConfigurator::~SimpleUnderlayConfigurator()
00053 {
00054 for (uint32_t i = 0; i < nodeRecordPool.size(); ++i) {
00055
00056 delete nodeRecordPool[i].first;
00057 }
00058 nodeRecordPool.clear();
00059 }
00060
00061 void SimpleUnderlayConfigurator::initializeUnderlay(int stage)
00062 {
00063 if (stage != MAX_STAGE_UNDERLAY)
00064 return;
00065
00066
00067 fixedNodePositions = par("fixedNodePositions");
00068 useIPv6 = par("useIPv6Addresses");
00069
00070
00071 fieldSize = par("fieldSize");
00072 sendQueueLength = par("sendQueueLength");
00073
00074
00075 nodeCoordinateSource = par("nodeCoordinateSource");
00076
00077 if (std::string(nodeCoordinateSource) != "") {
00078
00079 std::ifstream check_for_xml_file(nodeCoordinateSource);
00080 if (check_for_xml_file) {
00081 useXmlCoords = 1;
00082
00083 EV<< "[SimpleNetConfigurator::initializeUnderlay()]\n"
00084 << " Using '" << nodeCoordinateSource
00085 << "' as coordinate source file" << endl;
00086
00087 maxCoordinate = parseCoordFile(nodeCoordinateSource);
00088 } else {
00089 throw cRuntimeError("Coordinate source file not found!");
00090 }
00091 check_for_xml_file.close();
00092 } else {
00093 useXmlCoords = 0;
00094 dimensions = 2;
00095 NodeRecord::setDim(dimensions);
00096 EV << "[SimpleNetConfigurator::initializeUnderlay()]\n"
00097 << " Using conventional (random) coordinates for placing nodes!\n"
00098 << " (no XML coordinate source file was specified)" << endl;
00099 }
00100
00101
00102 nextFreeAddress = 0x1000001;
00103
00104
00105 overlayTerminalCount = 0;
00106
00107 numCreated = 0;
00108 numKilled = 0;
00109 }
00110
00111 TransportAddress* SimpleUnderlayConfigurator::createNode(NodeType type,
00112 bool initialize)
00113 {
00114 Enter_Method_Silent();
00115
00116 cModuleType* moduleType = cModuleType::get(type.terminalType.c_str());
00117
00118 std::string nameStr = "overlayTerminal";
00119 if (churnGenerator.size() > 1) {
00120 nameStr += "-" + convertToString<int32_t>(type.typeID);
00121 }
00122 cModule* node = moduleType->create(nameStr.c_str(), getParentModule(),
00123 numCreated + 1, numCreated);
00124
00125 std::string displayString;
00126
00127 if ((type.typeID > 0) && (type.typeID <= NUM_COLORS)) {
00128 ((displayString += "i=device/wifilaptop_l,")
00129 += colorNames[type.typeID - 1]) += ",40;i2=block/circle_s";
00130 } else {
00131 displayString = "i=device/wifilaptop_l;i2=block/circle_s";
00132 }
00133
00134 node->finalizeParameters();
00135 node->setDisplayString(displayString.c_str());
00136 node->buildInside();
00137 node->scheduleStart(simTime());
00138
00139 for (int i = 0; i < MAX_STAGE_UNDERLAY + 1; i++) {
00140 node->callInitialize(i);
00141 }
00142
00143 IPvXAddress addr;
00144 if (useIPv6) {
00145 addr = IPv6Address(0, nextFreeAddress++, 0, 0);
00146 } else {
00147 addr = IPAddress(nextFreeAddress++);
00148 }
00149
00150 int chanIndex = intuniform(0, type.channelTypesRx.size() - 1);
00151 cChannelType* rxChan = cChannelType::find(type.channelTypesRx[chanIndex].c_str());
00152 cChannelType* txChan = cChannelType::find(type.channelTypesTx[chanIndex].c_str());
00153
00154 if (!txChan || !rxChan)
00155 opp_error("Could not find Channel Type. Most likely parameter "
00156 "channelTypesRx or channelTypes does not match the channels defined in "
00157 "channels.ned");
00158
00159 SimpleNodeEntry* entry;
00160
00161 if (!useXmlCoords) {
00162 entry = new SimpleNodeEntry(node, rxChan, txChan, sendQueueLength, fieldSize);
00163 } else {
00164
00165 uint32_t volunteer = intuniform(0, nodeRecordPool.size() - 1);
00166 uint32_t temp = volunteer;
00167 while (nodeRecordPool[volunteer].second == false) {
00168 ++volunteer;
00169 if (volunteer >= nodeRecordPool.size())
00170 volunteer = 0;
00171
00172 if (temp == volunteer)
00173 throw cRuntimeError("No unused coordinates left -> "
00174 "cannot create any more nodes. "
00175 "Provide %s-file with more nodes!\n", nodeCoordinateSource);
00176 }
00177
00178 entry = new SimpleNodeEntry(node, rxChan, txChan,
00179 sendQueueLength, nodeRecordPool[volunteer].first, volunteer);
00180
00181
00182
00183 nodeRecordPool[volunteer].second = false;
00184 }
00185
00186 SimpleUDP* simpleUdp = check_and_cast<SimpleUDP*> (node->getSubmodule("udp"));
00187 simpleUdp->setNodeEntry(entry);
00188 SimpleTCP* simpleTcp = dynamic_cast<SimpleTCP*> (node->getSubmodule("tcp", 0));
00189 if (simpleTcp) {
00190 simpleTcp->setNodeEntry(entry);
00191 }
00192
00193
00194 if (useIPv6) {
00195 IPv6InterfaceData* ifdata = new IPv6InterfaceData;
00196 ifdata->assignAddress(addr.get6(),false, 0, 0);
00197 IPv6InterfaceData::AdvPrefix prefix = {addr.get6(), 64};
00198 ifdata->addAdvPrefix(prefix);
00199 InterfaceEntry* e = new InterfaceEntry;
00200 e->setName("dummy interface");
00201 e->setIPv6Data(ifdata);
00202 IPAddressResolver().interfaceTableOf(node)->addInterface(e, NULL);
00203 }
00204 else {
00205 IPv4InterfaceData* ifdata = new IPv4InterfaceData;
00206 ifdata->setIPAddress(addr.get4());
00207 ifdata->setNetmask(IPAddress("255.255.255.255"));
00208 InterfaceEntry* e = new InterfaceEntry;
00209 e->setName("dummy interface");
00210 e->setIPv4Data(ifdata);
00211
00212 IPAddressResolver().interfaceTableOf(node)->addInterface(e, NULL);
00213 }
00214
00215
00216 SimpleInfo* info = new SimpleInfo(type.typeID, node->getId(), type.context);
00217 info->setEntry(entry);
00218
00219
00220 globalNodeList->addPeer(addr, info);
00221
00222
00223
00224 if (!initialize) {
00225 for (int i = MAX_STAGE_UNDERLAY + 1; i < NUM_STAGES_ALL; i++) {
00226 node->callInitialize(i);
00227 }
00228 }
00229
00230
00231
00232 if (fixedNodePositions && ev.isGUI()) {
00233 node->getDisplayString().insertTag("p");
00234 node->getDisplayString().setTagArg("p", 0, (long int)(entry->getX() * 5));
00235 node->getDisplayString().setTagArg("p", 1, (long int)(entry->getY() * 5));
00236 node->getDisplayString().insertTag("t", 0);
00237 node->getDisplayString().setTagArg("t", 0, addr.str().c_str());
00238 node->getDisplayString().setTagArg("t", 1, "l");
00239 }
00240
00241 overlayTerminalCount++;
00242 numCreated++;
00243
00244 churnGenerator[type.typeID]->terminalCount++;
00245
00246 TransportAddress *address = new TransportAddress(addr);
00247
00248
00249 setDisplayString();
00250
00251 return address;
00252 }
00253
00254 uint32_t SimpleUnderlayConfigurator::parseCoordFile(const char* nodeCoordinateSource)
00255 {
00256 cXMLElement* rootElement = ev.getXMLDocument(nodeCoordinateSource);
00257
00258
00259 dimensions = atoi(rootElement->getAttribute("dimensions"));
00260 NodeRecord::setDim(dimensions);
00261 EV << "[SimpleNetConfigurator::parseCoordFile()]\n"
00262 << " using " << dimensions << " dimensions: ";
00263
00264 double max_coord = 0;
00265
00266 for (cXMLElement *tmpElement = rootElement->getFirstChild(); tmpElement;
00267 tmpElement = tmpElement->getNextSibling()) {
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 NodeRecord* tmpNode = new NodeRecord;
00279
00280
00281 int i = 0;
00282 for (cXMLElement *coord = tmpElement->getFirstChild(); coord;
00283 coord = coord->getNextSibling()) {
00284
00285 tmpNode->coords[i] = atof(coord->getNodeValue());
00286
00287 double newMax = fabs(tmpNode->coords[i]);
00288 if (newMax > max_coord) {
00289 max_coord = newMax;
00290 }
00291 i++;
00292 }
00293
00294
00295 nodeRecordPool.push_back(make_pair(tmpNode, true));
00296
00297
00298 }
00299
00300 EV << nodeRecordPool.size()
00301 << " nodes added to vector \"nodeRecordPool\"." << endl;
00302
00303 #if OMNETPP_VERSION>=0x0401
00304
00305 ev.forgetXMLDocument(nodeCoordinateSource);
00306 malloc_trim(0);
00307 #endif
00308
00309 return (uint32_t)ceil(max_coord);
00310 }
00311
00312 void SimpleUnderlayConfigurator::preKillNode(NodeType type, TransportAddress* addr)
00313 {
00314 Enter_Method_Silent();
00315
00316 SimpleNodeEntry* entry = NULL;
00317 SimpleInfo* info;
00318
00319 if (addr == NULL) {
00320 addr = globalNodeList->getRandomAliveNode(type.typeID);
00321
00322 if (addr == NULL) {
00323
00324 std::cout << "all nodes are already prekilled" << std::endl;
00325 return;
00326 }
00327 }
00328
00329 info = dynamic_cast<SimpleInfo*> (globalNodeList->getPeerInfo(*addr));
00330
00331 if (info != NULL) {
00332 entry = info->getEntry();
00333 globalNodeList->setPreKilled(*addr);
00334 } else {
00335 opp_error("SimpleNetConfigurator: Trying to pre kill node "
00336 "with nonexistant TransportAddress!");
00337 }
00338
00339 uint32_t effectiveType = info->getTypeID();
00340 cGate* gate = entry->getUdpIPv4Gate();
00341
00342 cModule* node = gate->getOwnerModule()->getParentModule();
00343
00344 if (scheduledID.count(node->getId())) {
00345 std::cout << "SchedID" << std::endl;
00346 return;
00347 }
00348
00349
00350 globalNodeList->removePeer(IPAddressResolver().addressOf(node));
00351
00352
00353
00354 killList.push_front(IPAddressResolver().addressOf(node));
00355 scheduledID.insert(node->getId());
00356
00357 overlayTerminalCount--;
00358 numKilled++;
00359
00360 churnGenerator[effectiveType]->terminalCount--;
00361
00362
00363 setDisplayString();
00364
00365
00366 NotificationBoard* nb = check_and_cast<NotificationBoard*> (
00367 node-> getSubmodule("notificationBoard"));
00368 nb->fireChangeNotification(NF_OVERLAY_NODE_LEAVE);
00369
00370 double random = uniform(0, 1);
00371 if (random < gracefulLeaveProbability) {
00372 nb->fireChangeNotification(NF_OVERLAY_NODE_GRACEFUL_LEAVE);
00373 }
00374
00375 cMessage* msg = new cMessage();
00376 scheduleAt(simTime() + gracefulLeaveDelay, msg);
00377 }
00378
00379 void SimpleUnderlayConfigurator::migrateNode(NodeType type, TransportAddress* addr)
00380 {
00381 Enter_Method_Silent();
00382
00383 SimpleNodeEntry* entry = NULL;
00384
00385 if (addr != NULL) {
00386 SimpleInfo* info =
00387 dynamic_cast<SimpleInfo*> (globalNodeList->getPeerInfo(*addr));
00388 if (info != NULL) {
00389 entry = info->getEntry();
00390 } else {
00391 opp_error("SimpleNetConfigurator: Trying to migrate node with "
00392 "nonexistant TransportAddress!");
00393 }
00394 } else {
00395 SimpleInfo* info = dynamic_cast<SimpleInfo*> (
00396 globalNodeList-> getRandomPeerInfo(type.typeID));
00397 entry = info->getEntry();
00398 }
00399
00400 cGate* gate = entry->getUdpIPv4Gate();
00401 cModule* node = gate->getOwnerModule()->getParentModule();
00402
00403
00404 if (scheduledID.count(node->getId()))
00405 return;
00406
00407
00408
00409
00410 IPvXAddress address = IPAddress(nextFreeAddress++);
00411
00412 IPvXAddress tmp_ip = IPAddressResolver().addressOf(node);
00413 SimpleNodeEntry* newentry;
00414
00415 int chanIndex = intuniform(0, type.channelTypesRx.size() - 1);
00416 cChannelType* rxChan = cChannelType::find(type.channelTypesRx[chanIndex].c_str());
00417 cChannelType* txChan = cChannelType::find(type.channelTypesTx[chanIndex].c_str());
00418
00419 if (!txChan || !rxChan)
00420 opp_error("Could not find Channel Type. Most likely parameter "
00421 "channelTypesRx or channelTypes does not match the channels defined in "
00422 "channels.ned");
00423
00424 if (useXmlCoords) {
00425 newentry = new SimpleNodeEntry(node,
00426 rxChan,
00427 txChan,
00428 sendQueueLength,
00429 entry->getNodeRecord(), entry->getRecordIndex());
00430
00431 } else {
00432 newentry = new SimpleNodeEntry(node, rxChan, txChan, fieldSize, sendQueueLength);
00433 }
00434
00435 node->bubble("I am migrating!");
00436
00437
00438 globalNodeList->killPeer(tmp_ip);
00439
00440 SimpleUDP* simple = check_and_cast<SimpleUDP*> (gate->getOwnerModule());
00441 simple->setNodeEntry(newentry);
00442
00443 InterfaceEntry* ie = IPAddressResolver().interfaceTableOf(node)->
00444 getInterfaceByName("dummy interface");
00445 delete ie->ipv4Data();
00446
00447
00448 IPv4InterfaceData* ifdata = new IPv4InterfaceData;
00449 ifdata->setIPAddress(address.get4());
00450 ifdata->setNetmask(IPAddress("255.255.255.255"));
00451 ie->setIPv4Data(ifdata);
00452
00453
00454 SimpleInfo* newinfo = new SimpleInfo(type.typeID, node->getId(),
00455 type.context);
00456 newinfo->setEntry(newentry);
00457
00458
00459 globalNodeList->addPeer(address, newinfo);
00460
00461
00462 NotificationBoard* nb = check_and_cast<NotificationBoard*> (
00463 node->getSubmodule("notificationBoard"));
00464 nb->fireChangeNotification(NF_OVERLAY_TRANSPORTADDRESS_CHANGED);
00465 }
00466
00467 void SimpleUnderlayConfigurator::handleTimerEvent(cMessage* msg)
00468 {
00469 Enter_Method_Silent();
00470
00471
00472 IPvXAddress addr = killList.back();
00473 killList.pop_back();
00474
00475 SimpleNodeEntry* entry = NULL;
00476
00477 SimpleInfo* info =
00478 dynamic_cast<SimpleInfo*> (globalNodeList->getPeerInfo(addr));
00479
00480 if (info != NULL) {
00481 entry = info->getEntry();
00482 } else {
00483 throw cRuntimeError("SimpleUnderlayConfigurator: Trying to kill "
00484 "node with unknown TransportAddress!");
00485 }
00486
00487 cGate* gate = entry->getUdpIPv4Gate();
00488 cModule* node = gate->getOwnerModule()->getParentModule();
00489
00490 if (useXmlCoords) {
00491 nodeRecordPool[entry->getRecordIndex()].second = true;
00492 }
00493
00494 scheduledID.erase(node->getId());
00495 globalNodeList->killPeer(addr);
00496
00497 InterfaceEntry* ie = IPAddressResolver().interfaceTableOf(node)->
00498 getInterfaceByName("dummy interface");
00499 delete ie->ipv4Data();
00500
00501 node->callFinish();
00502 node->deleteModule();
00503
00504 delete msg;
00505 }
00506
00507 void SimpleUnderlayConfigurator::setDisplayString()
00508 {
00509
00510 char buf[80];
00511 sprintf(buf, "%i overlay terminals", overlayTerminalCount);
00512 getDisplayString().setTagArg("t", 0, buf);
00513 }
00514
00515 void SimpleUnderlayConfigurator::finishUnderlay()
00516 {
00517
00518 recordScalar("Terminals added", numCreated);
00519 recordScalar("Terminals removed", numKilled);
00520
00521 if (!isInInitPhase()) {
00522 struct timeval now, diff;
00523 gettimeofday(&now, NULL);
00524 timersub(&now, &initFinishedTime, &diff);
00525 printf("Simulation time: %li.%06li\n", diff.tv_sec, diff.tv_usec);
00526 }
00527 }