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