ReaSEUnderlayConfigurator.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2010 Institut fuer Telematik, Karlsruher Institut fuer Technologie (KIT)
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 //
00018 
00024 #include "ReaSEUnderlayConfigurator.h"
00025 
00026 #include <GlobalNodeList.h>
00027 #include <TransportAddress.h>
00028 
00029 #include <StringConvert.h>
00030 
00031 #include <ConnectReaSE.h>
00032 #include <IRoutingTable.h>
00033 #include <IInterfaceTable.h>
00034 #include <IPAddressResolver.h>
00035 #include <IPv4InterfaceData.h>
00036 #include <NotificationBoard.h>
00037 
00038 
00039 #include <ReaSEInfo.h>
00040 
00041 Define_Module(ReaSEUnderlayConfigurator);
00042 
00043 void ReaSEUnderlayConfigurator::initializeUnderlay(int stage)
00044 {
00045     //backbone configuration
00046     if (stage == MIN_STAGE_UNDERLAY) {
00047 
00048     }
00049     //access net configuration
00050     else if (stage == MAX_STAGE_UNDERLAY) {
00051         // fetch some parameters
00052 
00053 
00054         // count the overlay clients
00055         overlayTerminalCount = 0;
00056 
00057         numCreated = 0;
00058         numKilled = 0;
00059 
00060         // add access node modules to access node vector
00061         TerminalConnector = (ConnectReaSE*)getParentModule()->getSubmodule("TerminalConnector");
00062     }
00063 }
00064 
00065 TransportAddress* ReaSEUnderlayConfigurator::createNode(NodeType type, bool initialize)
00066 {
00067     Enter_Method_Silent();
00068     // derive overlay node from ned
00069     std::string nameStr = "overlayTerminal";
00070     if (churnGenerator.size() > 1) {
00071         nameStr += "-" + convertToString<int32_t>(type.typeID);
00072     }
00073     AccessInfo accessNet= TerminalConnector->getAccessNode();
00074     cModuleType* moduleType = cModuleType::get(type.terminalType.c_str());
00075     cModule* node = moduleType->create(nameStr.c_str(), accessNet.edge->Router->getParentModule(), //TODO: insert node in submodule
00076                                        numCreated + 1, numCreated);
00077 
00078     if (type.channelTypesTx.size() > 0) {
00079         throw cRuntimeError("ReaSEUnderlayConfigurator::createNode(): Setting "
00080                     "channel types via the churn generator is not allowed "
00081                     "with the ReaSEUnderlay. Use **.accessNet.channelTypes instead!");
00082     }
00083 
00084     node->setGateSize("pppg", 1);
00085 
00086     std::string displayString;
00087 
00088     if ((type.typeID > 0) && (type.typeID <= NUM_COLORS)) {
00089         ((displayString += "i=device/wifilaptop_l,")
00090                         += colorNames[type.typeID - 1])
00091                         += ",40;i2=block/circle_s";
00092     } else {
00093         displayString = "i=device/wifilaptop_l;i2=block/circle_s";
00094     }
00095 
00096     node->finalizeParameters();
00097     node->setDisplayString(displayString.c_str());
00098 
00099     node->buildInside();
00100     node->scheduleStart(simTime());
00101 
00102     // create meta information
00103     ReaSEInfo* info = new ReaSEInfo(type.typeID, node->getId(), type.context);
00104 
00105     accessNet.terminal = node;
00106     // add node to a randomly chosen access net
00107     info->setNodeID(TerminalConnector->addOverlayNode(&accessNet));
00108 
00109 
00110     // add node to bootstrap oracle
00111     globalNodeList->addPeer(IPAddressResolver().addressOf(node), info);
00112 
00113     // if the node was not created during startup we have to
00114     // finish the initialization process manually
00115     if (!initialize) {
00116         for (int i = MAX_STAGE_UNDERLAY + 1; i < NUM_STAGES_ALL; i++) {
00117             node->callInitialize(i);
00118         }
00119     }
00120 
00121     overlayTerminalCount++;
00122     numCreated++;
00123 
00124     churnGenerator[type.typeID]->terminalCount++;
00125 
00126     TransportAddress *address = new TransportAddress(
00127                                        IPAddressResolver().addressOf(node));
00128 
00129     // update display
00130     setDisplayString();
00131 
00132     return address;
00133 }
00134 
00135 //TODO: getRandomNode()
00136 void ReaSEUnderlayConfigurator::preKillNode(NodeType type, TransportAddress* addr)
00137 {
00138     Enter_Method_Silent();
00139 
00140     // AccessNet* accessNetModule = NULL;
00141     int nodeID;
00142     ReaSEInfo* info;
00143 
00144     // If no address given, get random node
00145     if (addr == NULL) {
00146         addr = globalNodeList->getRandomAliveNode(type.typeID);
00147 
00148         if (addr == NULL) {
00149             // all nodes are already prekilled
00150             std::cout << "all nodes are already prekilled" << std::endl;
00151             return;
00152         }
00153     }
00154 
00155     // get node information
00156     info = dynamic_cast<ReaSEInfo*>(globalNodeList->getPeerInfo(*addr));
00157 
00158     if (info != NULL) {
00159         //accessNetModule = info->getAccessNetModule();
00160         nodeID = info->getNodeID();
00161     } else {
00162         opp_error("IPv4UnderlayConfigurator: Trying to pre kill node "
00163                   "with nonexistant TransportAddress!");
00164     }
00165 
00166     uint32_t effectiveType = info->getTypeID();
00167 
00168     // do not kill node that is already scheduled
00169     if (scheduledID.count(nodeID))
00170         return;
00171     //TODO: get overlay node
00172     cModule* node = TerminalConnector->getOverlayNode(nodeID);
00173     globalNodeList->removePeer(IPAddressResolver().addressOf(node));
00174 
00175     //put node into the kill list and schedule a message for final removal of the node
00176     killList.push_front(IPAddressResolver().addressOf(node));
00177     scheduledID.insert(nodeID);
00178 
00179     overlayTerminalCount--;
00180     numKilled++;
00181 
00182     churnGenerator[effectiveType]->terminalCount--;
00183 
00184     // update display
00185     setDisplayString();
00186 
00187     // inform the notification board about the removal
00188     NotificationBoard* nb = check_and_cast<NotificationBoard*>(
00189             node->getSubmodule("notificationBoard"));
00190     nb->fireChangeNotification(NF_OVERLAY_NODE_LEAVE);
00191 
00192     double random = uniform(0, 1);
00193 
00194     if (random < gracefulLeaveProbability) {
00195         nb->fireChangeNotification(NF_OVERLAY_NODE_GRACEFUL_LEAVE);
00196     }
00197 
00198     cMessage* msg = new cMessage();
00199     scheduleAt(simTime() + gracefulLeaveDelay, msg);
00200 
00201 }
00202 
00203 void ReaSEUnderlayConfigurator::migrateNode(NodeType type, TransportAddress* addr)
00204 {
00205     Enter_Method_Silent();
00206 
00207     // AccessNet* accessNetModule = NULL;
00208     int nodeID = -1;
00209     ReaSEInfo* info;
00210 
00211     // If no address given, get random node
00212     if (addr == NULL) {
00213         info = dynamic_cast<ReaSEInfo*>(globalNodeList->getRandomPeerInfo(type.typeID));
00214     } else {
00215         // get node information
00216         info = dynamic_cast<ReaSEInfo*>(globalNodeList->getPeerInfo(*addr));
00217     }
00218 
00219     if (info != NULL) {
00220         //accessNetModule = info->getAccessNetModule();
00221         nodeID = info->getNodeID();
00222     } else {
00223         opp_error("ReaSEUnderlayConfigurator: Trying to pre kill node with nonexistant TransportAddress!");
00224     }
00225 
00226     // do not migrate node that is already scheduled
00227     if (scheduledID.count(nodeID))
00228         return;
00229 
00230     cModule* node = TerminalConnector->removeOverlayNode(nodeID);//intuniform(0, accessNetModule->size() - 1));
00231 
00232     if (node == NULL)
00233         opp_error("ReaSEUnderlayConfigurator: Trying to remove node which is not an overlay node in network!");
00234 
00235     //remove node from bootstrap oracle
00236     globalNodeList->killPeer(IPAddressResolver().addressOf(node));
00237 
00238     node->bubble("I am migrating!");
00239     // connect the node to another access net
00240     AccessInfo newAccessModule;
00241 
00242     // create meta information
00243     ReaSEInfo* newinfo = new ReaSEInfo(type.typeID, node->getId(), type.context);
00244         newAccessModule = TerminalConnector->migrateNode(node->getId());
00245         newAccessModule.terminal = node;
00246         // add node to a randomly chosen access net
00247         info->setNodeID(TerminalConnector->addOverlayNode(&newAccessModule));
00248 
00249     //add node to bootstrap oracle
00250     globalNodeList->addPeer(IPAddressResolver().addressOf(node), newinfo);
00251 
00252     // inform the notification board about the migration
00253     NotificationBoard* nb = check_and_cast<NotificationBoard*>(node->getSubmodule("notificationBoard"));
00254     nb->fireChangeNotification(NF_OVERLAY_TRANSPORTADDRESS_CHANGED);
00255 }
00256 
00257 void ReaSEUnderlayConfigurator::handleTimerEvent(cMessage* msg)
00258 {
00259     Enter_Method_Silent();
00260 
00261     // get next scheduled node from the kill list
00262     IPvXAddress addr = killList.back();
00263     killList.pop_back();
00264 
00265     //AccessNet* accessNetModule = NULL;
00266     int nodeID = -1;
00267 
00268     ReaSEInfo* info = dynamic_cast<ReaSEInfo*>(globalNodeList->getPeerInfo(addr));
00269     if (info != NULL) {
00270         //accessNetModule = info->getAccessNetModule();
00271         nodeID = info->getNodeID();
00272     } else {
00273         opp_error("IPv4UnderlayConfigurator: Trying to kill node with nonexistant TransportAddress!");
00274     }
00275 
00276     scheduledID.erase(nodeID);
00277     globalNodeList->killPeer(addr);
00278 
00279     cModule* node = TerminalConnector->removeOverlayNode(nodeID);
00280 
00281     if (node == NULL)
00282         opp_error("IPv4UnderlayConfigurator: Trying to remove node which is nonexistant in AccessNet!");
00283 
00284     node->callFinish();
00285     node->deleteModule();
00286 
00287     delete msg;
00288 }
00289 
00290 void ReaSEUnderlayConfigurator::setDisplayString()
00291 {
00292     char buf[80];
00293     sprintf(buf, "%i overlay terminals",
00294             overlayTerminalCount);
00295     getDisplayString().setTagArg("t", 0, buf);
00296 }
00297 
00298 void ReaSEUnderlayConfigurator::finishUnderlay()
00299 {
00300     // statistics
00301     recordScalar("Terminals added", numCreated);
00302     recordScalar("Terminals removed", numKilled);
00303 
00304     if (!isInInitPhase()) {
00305         struct timeval now, diff;
00306         gettimeofday(&now, NULL);
00307         timersub(&now, &initFinishedTime, &diff);
00308         printf("Simulation time: %li.%06li\n", diff.tv_sec, diff.tv_usec);
00309     }
00310 }
00311 
00312