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