IPv4UnderlayConfigurator Class Reference

#include <IPv4UnderlayConfigurator.h>

Inheritance diagram for IPv4UnderlayConfigurator:

UnderlayConfigurator List of all members.

Detailed Description

Configurator module for the IPv4Underlay.

Author:
Markus Mauch
Todo:
possibility to disable tier1-3 in overlay(access)routers


Public Member Functions

TransportAddresscreateNode (NodeType type, bool initialize=false)
 Creates an overlay node.
void preKillNode (NodeType type, TransportAddress *addr=NULL)
 Notifies and schedules overlay nodes for removal.
void migrateNode (NodeType type, TransportAddress *addr=NULL)
 Migrates overlay nodes from one access net to another.

Protected Member Functions

void initializeUnderlay (int stage)
 Sets up backbone, assigns ip addresses, calculates routing tables, sets some parameters and adds the initial number of nodes to the network.
void handleTimerEvent (cMessage *msg)
 process timer messages
void finishUnderlay ()
 Saves statistics, prints simulation time.
void setDisplayString ()
 Updates the statistics display string.

Protected Attributes

std::vector< cModule * > accessNode
 stores accessRouter
std::deque< IPvXAddress > killList
 stores nodes scheduled to be killed
std::set< int > scheduledID
 stores nodeIds to prevent migration of prekilled nodes
int numCreated
 number of overall created overlay terminals
int numKilled
 number of overall killed overlay terminals

Private Attributes

int accessRouterNum
 number of access router
int overlayAccessRouterNum
 number of overlayAccessRouter
int overlayTerminalNum
 number of terminal in the overlay


Member Function Documentation

TransportAddress * IPv4UnderlayConfigurator::createNode ( NodeType  type,
bool  initialize = false 
) [virtual]

Creates an overlay node.

Parameters:
type the NodeType of the node to create
initialize creation during init phase?

Implements UnderlayConfigurator.

00243 {
00244     Enter_Method_Silent();
00245     // derive overlay node from ned
00246     cModuleType* moduleType = findModuleType("OverlayHost"); //parentModule()->par("overlayTerminalType"));
00247     cModule* node = moduleType->create("overlayTerminal", parentModule());
00248 
00249     node->par("overlayType").setStringValue(type.overlayType.c_str());
00250     node->par("tier1Type").setStringValue(type.tier1Type.c_str());
00251     node->par("tier2Type").setStringValue(type.tier2Type.c_str());
00252     node->par("tier3Type").setStringValue(type.tier3Type.c_str());
00253 
00254     node->setGateSize("in", 1);
00255     node->setGateSize("out", 1);
00256     node->setDisplayString("i=device/wifilaptop_l;i2=block/circle_s");
00257     node->buildInside();
00258     node->scheduleStart(simulation.simTime());
00259 
00260     // create meta information
00261     IPv4Info* info = new IPv4Info(type.typeID, node->id());
00262     AccessNet* accessNet= check_and_cast<AccessNet*>
00263         (accessNode[intuniform(0, accessNode.size() - 1)]
00264          ->submodule("accessNet"));
00265     info->setAccessNetModule(accessNet);
00266     // add node to a randomly chosen access net
00267     info->setNodeID(accessNet->addOverlayNode(node));
00268 
00269     // append index to module name
00270     char buf[80];
00271     sprintf(buf, "overlayTerminal[%i]", numCreated);
00272     node->setName(buf);
00273 
00274     //add node to bootstrap oracle
00275     bootstrapOracle->addPeer(IPAddressResolver().addressOf(node), info);
00276 
00277     // if the node was not created during startup we have to
00278     // finish the initialization process manually
00279     if ( !initialize) {
00280         for (int i = MAX_STAGE_UNDERLAY + 1; i < NUM_STAGES_ALL; i++) {
00281             node->callInitialize(i);
00282         }
00283     }
00284 
00285     overlayTerminalCount++;
00286     numCreated++;
00287 
00288     churnGenerator[type.typeID - 1]->terminalCount++;
00289 
00290     TransportAddress *address = new TransportAddress(IPAddressResolver().addressOf(node));
00291 
00292     // update display
00293     setDisplayString();
00294 
00295     return address;
00296 }

void IPv4UnderlayConfigurator::preKillNode ( NodeType  type,
TransportAddress addr = NULL 
) [virtual]

Notifies and schedules overlay nodes for removal.

Parameters:
type NodeType of the node to remove
addr NULL for random node

Implements UnderlayConfigurator.

00300 {
00301     Enter_Method_Silent();
00302 
00303     AccessNet* accessNetModule;
00304     int nodeID;
00305     IPv4Info* info;
00306 
00307     // If no address given, get random node
00308     if(addr == NULL) {
00309         info = dynamic_cast<IPv4Info*>(bootstrapOracle->getRandomPeerInfo(type.typeID));
00310     } else {
00311         // get node information
00312         info = dynamic_cast<IPv4Info*>(bootstrapOracle->getPeerInfo(*addr));
00313     }
00314     if(info != NULL) {
00315         accessNetModule = info->getAccessNetModule();
00316         nodeID = info->getNodeID();
00317     } else {
00318         opp_error("IPv4UnderlayConfigurator: Trying to pre kill node with nonexistant TransportAddress!");
00319     }
00320     uint32_t effectiveType = info->getTypeID();
00321 
00322     //TODO: keepFirstNode in while-loop?
00323     if(keepFirstNode && (firstNodeId == nodeID))
00324         return;
00325 
00326     // do not kill node that is already scheduled
00327     if(scheduledID.count(nodeID))
00328         return;
00329 
00330     cModule* node = accessNetModule->getOverlayNode(nodeID);
00331     bootstrapOracle->removePeer(IPAddressResolver().addressOf(node));
00332 
00333     //put node into the kill list and schedule a message for final removal of the node
00334     killList.push_front(IPAddressResolver().addressOf(node));
00335     scheduledID.insert(nodeID);
00336 
00337     overlayTerminalCount--;
00338     numKilled++;
00339 
00340     churnGenerator[effectiveType - 1]->terminalCount--;
00341 
00342     // update display
00343     setDisplayString();
00344 
00345     // inform the notification board about the removal
00346     NotificationBoard* nb = check_and_cast<NotificationBoard*>(
00347         node->submodule("notificationBoard"));
00348     nb->fireChangeNotification(NF_OVERLAY_NODE_LEAVE);
00349 
00350     double random = uniform(0, 1);
00351     if (random < gracefulLeavePropability) {
00352         nb->fireChangeNotification(NF_OVERLAY_NODE_GRACEFUL_LEAVE);
00353     }
00354 
00355     cMessage* msg = new cMessage();
00356     scheduleAt(simulation.simTime() + gracefulLeaveDelay, msg);
00357 
00358 }

void IPv4UnderlayConfigurator::migrateNode ( NodeType  type,
TransportAddress addr = NULL 
) [virtual]

Migrates overlay nodes from one access net to another.

Parameters:
type the NodeType of the node to migrate
addr NULL for random node

Implements UnderlayConfigurator.

00361 {
00362     Enter_Method_Silent();
00363 
00364     AccessNet* accessNetModule;
00365     int nodeID;
00366     IPv4Info* info;
00367 
00368     // If no address given, get random node
00369     if(addr == NULL) {
00370         info = dynamic_cast<IPv4Info*>(bootstrapOracle->getRandomPeerInfo(type.typeID));
00371     } else {
00372         // get node information
00373         info = dynamic_cast<IPv4Info*>(bootstrapOracle->getPeerInfo(*addr));
00374     }
00375     if(info != NULL) {
00376         accessNetModule = info->getAccessNetModule();
00377         nodeID = info->getNodeID();
00378     } else {
00379         opp_error("IPv4UnderlayConfigurator: Trying to pre kill node with nonexistant TransportAddress!");
00380     }
00381 
00382     if(keepFirstNode && (firstNodeId == nodeID))
00383       return;
00384 
00385     // do not migrate node that is already scheduled
00386     if(scheduledID.count(nodeID))
00387         return;
00388 
00389     cModule* node = accessNetModule->removeOverlayNode(nodeID);//intuniform(0, accessNetModule->size() - 1));
00390     if(node == NULL)
00391         opp_error("IPv4UnderlayConfigurator: Trying to remove node which is nonexistant in AccessNet!");
00392     //remove node from bootstrap oracle
00393     bootstrapOracle->killPeer(IPAddressResolver().addressOf(node));
00394 
00395     node->bubble("I am migrating!");
00396 
00397     // connect the node to another access net
00398     AccessNet* newAccessNetModule;
00399     do {
00400         newAccessNetModule = check_and_cast<AccessNet*>(accessNode[intuniform(0, accessNode.size() - 1)]->submodule("accessNet"));
00401     } while((newAccessNetModule == accessNetModule) && (accessNode.size() != 1));
00402 
00403     // create meta information
00404     IPv4Info* newinfo = new IPv4Info(type.typeID, node->id());
00405     // add node to a randomly chosen access net
00406     newinfo->setAccessNetModule(newAccessNetModule);
00407     newinfo->setNodeID(newAccessNetModule->addOverlayNode(node, true));
00408 
00409     //add node to bootstrap oracle
00410     bootstrapOracle->addPeer(IPAddressResolver().addressOf(node), newinfo);
00411 
00412     // inform the notofication board about the migration
00413     NotificationBoard* nb = check_and_cast<NotificationBoard*>(node->submodule("notificationBoard"));
00414     nb->fireChangeNotification(NF_OVERLAY_TRANSPORTADDRESS_CHANGED);
00415 }

void IPv4UnderlayConfigurator::initializeUnderlay ( int  stage  )  [protected, virtual]

Sets up backbone, assigns ip addresses, calculates routing tables, sets some parameters and adds the initial number of nodes to the network.

Parameters:
stage the phase of the initialisation

Implements UnderlayConfigurator.

00033 {
00034     //backbone configuration
00035     if(stage == MIN_STAGE_UNDERLAY) {
00036         // Find all router module types.
00037         cTopology topo("topo");
00038         const char* typeNames[6];
00039         typeNames[0] = "Router";
00040         typeNames[1] = "OverlayRouter";
00041         typeNames[2] = "AccessRouter";
00042         typeNames[3] = "OverlayAccessRouter";
00043         typeNames[4] = "TunOutRouter";
00044         typeNames[5] = NULL;
00045         topo.extractByModuleType(typeNames);
00046 
00047         // Assign IP addresses to all router modules.
00048         std::vector<uint32> nodeAddresses;
00049         nodeAddresses.resize(topo.nodes());
00050 
00051         // IP addresses for backbone
00052         // Take start IP from config file
00053         // FIXME: Make Netmask for Routers configurable!
00054         uint32 lowIPBoundary = IPAddress(par("startIP").stringValue()).getInt();
00055 
00056         // uint32 lowIPBoundary = uint32((1 << 24) + 1);
00057         int numIPNodes = 0;
00058         for (int i = 0; i < topo.nodes(); i++) {
00059             ++numIPNodes;
00060 
00061             uint32 addr = lowIPBoundary + uint32(numIPNodes << 16);
00062             nodeAddresses[i] = addr;
00063 
00064             // update ip display string
00065             if (ev.isGUI()) {
00066                 const char* ip_disp = const_cast<char*>(IPAddress(addr).str().c_str());
00067                 topo.node(i)->module()->displayString().insertTag("t", 0);
00068                 topo.node(i)->module()->displayString().setTagArg("t", 0, ip_disp);
00069                 topo.node(i)->module()->displayString().setTagArg("t", 1, "l");
00070                 topo.node(i)->module()->displayString().setTagArg("t", 2, "red");
00071             }
00072 
00073             // find interface table and assign address to all (non-loopback) interfaces
00074             InterfaceTable* ift = IPAddressResolver().interfaceTableOf(topo.node(i)->module());
00075 
00076             for ( int k = 0; k < ift->numInterfaces(); k++ ) {
00077                 InterfaceEntry* ie = ift->interfaceAt(k);
00078                 if (!ie->isLoopback()) {
00079                     ie->ipv4()->setInetAddress(IPAddress(addr));
00080                     // full address must match for local delivery
00081                     ie->ipv4()->setNetmask(IPAddress::ALLONES_ADDRESS);
00082                 }
00083             }
00084         }
00085 
00086         // Fill in routing tables.
00087         for ( int i = 0; i < topo.nodes(); i++ ) {
00088             cTopology::Node* destNode = topo.node(i);
00089             uint32 destAddr = nodeAddresses[i];
00090 
00091             // calculate shortest paths from everywhere towards destNode
00092             topo.unweightedSingleShortestPathsTo(destNode);
00093 
00094             // add overlayAccessRouters and overlayBackboneRouters
00095             // to the BootstrapOracle
00096             if ((strcmp(destNode->module()->name(), "overlayBackboneRouter") == 0 ) ||
00097                 (strcmp(destNode->module()->name(), "overlayAccessRouter") == 0)) {
00098                 //add node to bootstrap oracle
00099                 PeerInfo* info = new PeerInfo(0, destNode->module()->id());
00100                 bootstrapOracle->addPeer(IPvXAddress(nodeAddresses[i]), info);
00101             }
00102 
00103 
00104             // If destNode is the outRouter, add a default route
00105             // to outside network via the TunOutDevice and a route to the
00106             // Gateway
00107             if ( strcmp(destNode->module()->name(), "outRouter" ) == 0 ) {
00108                 RoutingEntry* defRoute = new RoutingEntry();
00109                 defRoute->host = IPAddress::UNSPECIFIED_ADDRESS;
00110                 defRoute->netmask = IPAddress::UNSPECIFIED_ADDRESS;
00111                 defRoute->gateway = IPAddress(par("gatewayIP").stringValue());
00112                 defRoute->interfaceName = "tunDev";
00113                 defRoute->interfacePtr = IPAddressResolver().interfaceTableOf(destNode->module())->interfaceByName("tunDev");
00114                 defRoute->type = RoutingEntry::REMOTE;
00115                 defRoute->source = RoutingEntry::MANUAL;
00116                 IPAddressResolver().routingTableOf(destNode->module())->addRoutingEntry(defRoute);
00117 
00118                 RoutingEntry* gwRoute = new RoutingEntry();
00119                 gwRoute->host = IPAddress(par("gatewayIP").stringValue());
00120                 gwRoute->netmask = IPAddress(255, 255, 255, 255);
00121                 gwRoute->interfaceName = "tunDev";
00122                 gwRoute->interfacePtr = IPAddressResolver().interfaceTableOf(destNode->module())->interfaceByName("tunDev");
00123                 gwRoute->type = RoutingEntry::DIRECT;
00124                 gwRoute->source = RoutingEntry::MANUAL;
00125                 IPAddressResolver().routingTableOf(destNode->module())->addRoutingEntry(gwRoute);
00126             }
00127 
00128             // add route (with host=destNode) to every routing table in the network
00129             for ( int j = 0; j < topo.nodes(); j++ ) {
00130             // continue if same node
00131                 if ( i == j )
00132                     continue;
00133 
00134                 // cancel simulation if node is not conencted with destination
00135                 cTopology::Node* atNode = topo.node(j);
00136                 if(atNode->paths() == 0)
00137                     error((std::string(atNode->module()->name()) + ": Network is not entirely connected."
00138                                 "Please increase your value for the "
00139                                 "connectivity parameter").c_str());
00140 
00141                 //
00142                 // Add routes at the atNode.
00143                 //
00144 
00145                 // find atNode's interface and routing table
00146                 InterfaceTable* ift = IPAddressResolver().interfaceTableOf(atNode->module());
00147                 RoutingTable* rt = IPAddressResolver().routingTableOf(atNode->module());
00148 
00149                 // find atNode's interface entry for the next hop node
00150                 int outputGateId = atNode->path(0)->localGate()->id();
00151                 InterfaceEntry *ie = ift->interfaceByNodeOutputGateId(outputGateId);
00152 
00153                 // find the next hop node on the path towards destNode
00154                 cModule* next_hop = atNode->path(0)->remoteNode()->module();
00155                 IPAddress next_hop_ip = IPAddressResolver().addressOf(next_hop).get4();
00156 
00157 
00158                 // Requirement 1: Each router has exactly one routing entry
00159                 // (netmask 255.255.0.0) to each other router
00160                 RoutingEntry* re = new RoutingEntry();
00161 
00162                 re->host = IPAddress(destAddr);
00163                 re->interfaceName = ie->name();
00164                 re->interfacePtr = ie;
00165                 re->source = RoutingEntry::MANUAL;
00166                 re->netmask = IPAddress(255, 255, 0, 0);
00167                 re->gateway = IPAddress(next_hop_ip);
00168                 re->type = RoutingEntry::REMOTE;
00169 
00170                 rt->addRoutingEntry(re);
00171 
00172                 // Requirement 2: Each router has a point-to-point routing
00173                 // entry (netmask 255.255.255.255) for each immediate neighbour
00174                 if ( atNode->distanceToTarget() == 1 ) {
00175                     RoutingEntry* re2 = new RoutingEntry();
00176 
00177                     re2->host = IPAddress(destAddr);
00178                     re2->interfaceName = ie->name();
00179                     re2->interfacePtr = ie;
00180                     re2->source = RoutingEntry::MANUAL;
00181                     re2->netmask = IPAddress(255, 255, 255, 255);
00182                     re2->type = RoutingEntry::DIRECT;
00183 
00184                     rt->addRoutingEntry(re2);
00185                 }
00186 
00187                 // If destNode is the outRouter, add a default route
00188                 // to the next hop in the direction of the outRouter
00189                 if ( strcmp(destNode->module()->name(), "outRouter" ) == 0 ) {
00190                     RoutingEntry* defRoute = new RoutingEntry();
00191                     defRoute->host = IPAddress::UNSPECIFIED_ADDRESS;
00192                     defRoute->netmask = IPAddress::UNSPECIFIED_ADDRESS;
00193                     defRoute->gateway = IPAddress(next_hop_ip);
00194                     defRoute->interfaceName = ie->name();
00195                     defRoute->interfacePtr = ie;
00196                     defRoute->type = RoutingEntry::REMOTE;
00197                     defRoute->source = RoutingEntry::MANUAL;
00198 
00199                     rt->addRoutingEntry(defRoute);
00200                 }
00201             }
00202         }
00203     }
00204     //accessnet configuration
00205     else if(stage == MAX_STAGE_UNDERLAY) {
00206         // fetch some parameters
00207         accessRouterNum = parentModule()->par("accessRouterNum");
00208         overlayAccessRouterNum = parentModule()->par("overlayAccessRouterNum");
00209 
00210         // count the overlay clients
00211         overlayTerminalCount = 0;
00212 
00213         numCreated = 0;
00214         numKilled = 0;
00215 
00216         // add access node modules to access node vector
00217         // and assing the channel tpye to be used by the access node
00218         cModule* node;
00219         AccessNet* nodeAccess;
00220         for ( int i = 0; i < accessRouterNum; i++ ) {
00221             node = parentModule()->submodule("accessRouter", i);
00222             accessNode.push_back( node );
00223             nodeAccess = check_and_cast<AccessNet*>( node->submodule("accessNet") );
00224             nodeAccess->selectChannel( channelTypes[intuniform(0, channelTypes.size()-1)] );
00225         }
00226 
00227         for ( int i = 0; i < overlayAccessRouterNum; i++ ) {
00228             node = parentModule()->submodule("overlayAccessRouter", i);
00229             accessNode.push_back( node );
00230             nodeAccess = check_and_cast<AccessNet*>( node->submodule("accessNet") );
00231             nodeAccess->selectChannel( channelTypes[intuniform(0, channelTypes.size()-1)] );
00232         }
00233 
00234         // debug stuff
00235         WATCH_PTRVECTOR(accessNode);
00236 
00237 // Now done in base class         churnGenerator->setOverlayTerminalCount(overlayTerminalCount);
00238 // Now done in base class         churnGenerator->initializeChurn();
00239     }
00240 }

void IPv4UnderlayConfigurator::handleTimerEvent ( cMessage *  msg  )  [protected, virtual]

process timer messages

Parameters:
msg the received message

Reimplemented from UnderlayConfigurator.

00418 {
00419     Enter_Method_Silent();
00420 
00421     // get next scheduled node from the kill list
00422     IPvXAddress addr = killList.back();
00423     killList.pop_back();
00424 
00425     AccessNet* accessNetModule;
00426     int nodeID;
00427 
00428     IPv4Info* info = dynamic_cast<IPv4Info*>(bootstrapOracle->getPeerInfo(addr));
00429     if(info != NULL) {
00430         accessNetModule = info->getAccessNetModule();
00431         nodeID = info->getNodeID();
00432     }
00433     else
00434         opp_error("IPv4UnderlayConfigurator: Trying to kill node with nonexistant TransportAddress!");
00435 
00436     scheduledID.erase(nodeID);
00437     bootstrapOracle->killPeer(addr);
00438 
00439     cModule* node = accessNetModule->removeOverlayNode(nodeID);
00440     if(node == NULL)
00441         opp_error("IPv4UnderlayConfigurator: Trying to remove node which is nonexistant in AccessNet!");
00442 
00443     node->callFinish();
00444     node->deleteModule();
00445 
00446     delete msg;
00447 }

void IPv4UnderlayConfigurator::finishUnderlay (  )  [protected, virtual]

Saves statistics, prints simulation time.

Reimplemented from UnderlayConfigurator.

00457 {
00458     // statistics
00459     recordScalar("Terminals added", numCreated);
00460     recordScalar("Terminals removed", numKilled);
00461 
00462     struct timeval now, diff;
00463     gettimeofday(&now, NULL);
00464     timersub(&now, &initFinishedTime, &diff);
00465     printf("Simulation time: %li.%06li\n", diff.tv_sec, diff.tv_usec);
00466 }

void IPv4UnderlayConfigurator::setDisplayString (  )  [protected, virtual]

Updates the statistics display string.

Implements UnderlayConfigurator.

00450 {
00451     char buf[80];
00452     sprintf(buf, "%i overlay clients\n%i access router\n%i overlay access router", overlayTerminalCount, accessRouterNum, overlayAccessRouterNum);
00453     displayString().setTagArg("t", 0, buf);
00454 }


Member Data Documentation

int IPv4UnderlayConfigurator::accessRouterNum [private]

number of access router

int IPv4UnderlayConfigurator::overlayAccessRouterNum [private]

number of overlayAccessRouter

int IPv4UnderlayConfigurator::overlayTerminalNum [private]

number of terminal in the overlay

std::vector<cModule*> IPv4UnderlayConfigurator::accessNode [protected]

stores accessRouter

std::deque<IPvXAddress> IPv4UnderlayConfigurator::killList [protected]

stores nodes scheduled to be killed

std::set<int> IPv4UnderlayConfigurator::scheduledID [protected]

stores nodeIds to prevent migration of prekilled nodes

int IPv4UnderlayConfigurator::numCreated [protected]

number of overall created overlay terminals

int IPv4UnderlayConfigurator::numKilled [protected]

number of overall killed overlay terminals


The documentation for this class was generated from the following files:
Generated on Wed Sep 26 12:13:01 2007 for ITM OverSim by  doxygen 1.5.1