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:
initialize creation during init phase?

Implements UnderlayConfigurator.

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

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

Notifies and schedules overlay nodes for removal.

Parameters:
addr NULL for random node

Implements UnderlayConfigurator.

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

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

Migrates overlay nodes from one access net to another.

Parameters:
addr NULL for random node

Implements UnderlayConfigurator.

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

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()->
00100                                 submodule("overlay")->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                 if(atNode->paths() == 0)
00138                     error((std::string(atNode->module()->name()) + ": Network is not entirely connected."
00139                                 "Please increase your value for the "
00140                                 "connectivity parameter").c_str());
00141 
00142                 //
00143                 // Add routes at the atNode.
00144                 //
00145 
00146                 // find atNode's interface and routing table
00147                 InterfaceTable* ift = IPAddressResolver().interfaceTableOf(atNode->module());
00148                 RoutingTable* rt = IPAddressResolver().routingTableOf(atNode->module());
00149 
00150                 // find atNode's interface entry for the next hop node
00151                 int outputGateId = atNode->path(0)->localGate()->id();
00152                 InterfaceEntry *ie = ift->interfaceByNodeOutputGateId(outputGateId);
00153 
00154                 // find the next hop node on the path towards destNode
00155                 cModule* next_hop = atNode->path(0)->remoteNode()->module();
00156                 IPAddress next_hop_ip = IPAddressResolver().addressOf(next_hop).get4();
00157 
00158 
00159                 // Requirement 1: Each router has exactly one routing entry
00160                 // (netmask 255.255.0.0) to each other router
00161                 RoutingEntry* re = new RoutingEntry();
00162 
00163                 re->host = IPAddress(destAddr);
00164                 re->interfaceName = ie->name();
00165                 re->interfacePtr = ie;
00166                 re->source = RoutingEntry::MANUAL;
00167                 re->netmask = IPAddress(255, 255, 0, 0);
00168                 re->gateway = IPAddress(next_hop_ip);
00169                 re->type = RoutingEntry::REMOTE;
00170 
00171                 rt->addRoutingEntry(re);
00172 
00173                 // Requirement 2: Each router has a point-to-point routing
00174                 // entry (netmask 255.255.255.255) for each immediate neighbour
00175                 if ( atNode->distanceToTarget() == 1 ) {
00176                     RoutingEntry* re2 = new RoutingEntry();
00177 
00178                     re2->host = IPAddress(destAddr);
00179                     re2->interfaceName = ie->name();
00180                     re2->interfacePtr = ie;
00181                     re2->source = RoutingEntry::MANUAL;
00182                     re2->netmask = IPAddress(255, 255, 255, 255);
00183                     re2->type = RoutingEntry::DIRECT;
00184 
00185                     rt->addRoutingEntry(re2);
00186                 }
00187 
00188                 // If destNode is the outRouter, add a default route
00189                 // to the next hop in the direction of the outRouter
00190                 if ( strcmp(destNode->module()->name(), "outRouter" ) == 0 ) {
00191                     RoutingEntry* defRoute = new RoutingEntry();
00192                     defRoute->host = IPAddress::UNSPECIFIED_ADDRESS;
00193                     defRoute->netmask = IPAddress::UNSPECIFIED_ADDRESS;
00194                     defRoute->gateway = IPAddress(next_hop_ip);
00195                     defRoute->interfaceName = ie->name();
00196                     defRoute->interfacePtr = ie;
00197                     defRoute->type = RoutingEntry::REMOTE;
00198                     defRoute->source = RoutingEntry::MANUAL;
00199 
00200                     rt->addRoutingEntry(defRoute);
00201                 }
00202             }
00203         }
00204     }
00205     //accessnet configuration
00206     else if(stage == MAX_STAGE_UNDERLAY) {
00207         // fetch some parameters
00208         accessRouterNum = parentModule()->par("accessRouterNum");
00209         overlayAccessRouterNum = parentModule()->par("overlayAccessRouterNum");
00210 
00211         // count the overlay clients
00212         overlayTerminalCount = 0;
00213 
00214         numCreated = 0;
00215         numKilled = 0;
00216 
00217         // add access node modules to access node vector
00218         // and assing the channel tpye to be used by the access node
00219         cModule* node;
00220         AccessNet* nodeAccess;
00221         for ( int i = 0; i < accessRouterNum; i++ ) {
00222             node = parentModule()->submodule("accessRouter", i);
00223             accessNode.push_back( node );
00224             nodeAccess = check_and_cast<AccessNet*>( node->submodule("accessNet") );
00225             nodeAccess->selectChannel( channelTypes[intuniform(0, channelTypes.size()-1)] );
00226         }
00227 
00228         for ( int i = 0; i < overlayAccessRouterNum; i++ ) {
00229             node = parentModule()->submodule("overlayAccessRouter", i);
00230             accessNode.push_back( node );
00231             nodeAccess = check_and_cast<AccessNet*>( node->submodule("accessNet") );
00232             nodeAccess->selectChannel( channelTypes[intuniform(0, channelTypes.size()-1)] );
00233         }
00234 
00235         // debug stuff
00236         WATCH_PTRVECTOR(accessNode);
00237 
00238 // Now done in base class         churnGenerator->setOverlayTerminalCount(overlayTerminalCount);
00239 // Now done in base class         churnGenerator->initializeChurn();
00240     }
00241 }

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

process timer messages

Parameters:
msg the received message

Reimplemented from UnderlayConfigurator.

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

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

Saves statistics, prints simulation time.

Reimplemented from UnderlayConfigurator.

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

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

Updates the statistics display string.

Implements UnderlayConfigurator.

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


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 Tue Jul 24 16:51:18 2007 for ITM OverSim by  doxygen 1.5.1