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.

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

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.

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

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.

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

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

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

process timer messages

Parameters:
msg the received message

Reimplemented from UnderlayConfigurator.

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

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

Saves statistics, prints simulation time.

Reimplemented from UnderlayConfigurator.

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

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

Updates the statistics display string.

Implements UnderlayConfigurator.

00455 {
00456     char buf[80];
00457     sprintf(buf, "%i overlay clients\n%i access router\n%i overlay access router", overlayTerminalCount, accessRouterNum, overlayAccessRouterNum);
00458     displayString().setTagArg("t", 0, buf);
00459 }


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 Thu Apr 17 13:19:29 2008 for ITM OverSim by  doxygen 1.5.3