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.

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

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.

00319 {
00320     Enter_Method_Silent();
00321 
00322     AccessNet* accessNetModule = NULL;
00323     int nodeID;
00324     IPv4Info* info;
00325 
00326     // If no address given, get random node
00327     if (addr == NULL) {
00328         addr = bootstrapOracle->getRandomAliveNode(type.typeID);
00329 
00330         if (addr == NULL) {
00331             // all nodes are already prekilled
00332             std::cout << "all nodes are already prekilled" << std::endl;
00333             return;
00334         }
00335     }
00336 
00337     // get node information
00338     info = dynamic_cast<IPv4Info*>(bootstrapOracle->getPeerInfo(*addr));
00339 
00340     if (info != NULL) {
00341         accessNetModule = info->getAccessNetModule();
00342         nodeID = info->getNodeID();
00343     } else {
00344         opp_error("IPv4UnderlayConfigurator: Trying to pre kill node "
00345                   "with nonexistant TransportAddress!");
00346     }
00347 
00348     uint32_t effectiveType = info->getTypeID();
00349 
00350     // do not kill node that is already scheduled
00351     if(scheduledID.count(nodeID))
00352         return;
00353 
00354     cModule* node = accessNetModule->getOverlayNode(nodeID);
00355     bootstrapOracle->removePeer(IPAddressResolver().addressOf(node));
00356 
00357     //put node into the kill list and schedule a message for final removal of the node
00358     killList.push_front(IPAddressResolver().addressOf(node));
00359     scheduledID.insert(nodeID);
00360 
00361     overlayTerminalCount--;
00362     numKilled++;
00363 
00364     churnGenerator[effectiveType - 1]->terminalCount--;
00365 
00366     // update display
00367     setDisplayString();
00368 
00369     // inform the notification board about the removal
00370     NotificationBoard* nb = check_and_cast<NotificationBoard*>(
00371             node->submodule("notificationBoard"));
00372     nb->fireChangeNotification(NF_OVERLAY_NODE_LEAVE);
00373 
00374     double random = uniform(0, 1);
00375 
00376     if (random < gracefulLeaveProbability) {
00377         nb->fireChangeNotification(NF_OVERLAY_NODE_GRACEFUL_LEAVE);
00378     }
00379 
00380     cMessage* msg = new cMessage();
00381     scheduleAt(simulation.simTime() + gracefulLeaveDelay, msg);
00382 
00383 }

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.

00386 {
00387     Enter_Method_Silent();
00388 
00389     AccessNet* accessNetModule = NULL;
00390     int nodeID = -1;
00391     IPv4Info* info;
00392 
00393     // If no address given, get random node
00394     if(addr == NULL) {
00395         info = dynamic_cast<IPv4Info*>(bootstrapOracle->getRandomPeerInfo(type.typeID));
00396     } else {
00397         // get node information
00398         info = dynamic_cast<IPv4Info*>(bootstrapOracle->getPeerInfo(*addr));
00399     }
00400 
00401     if(info != NULL) {
00402         accessNetModule = info->getAccessNetModule();
00403         nodeID = info->getNodeID();
00404     } else {
00405         opp_error("IPv4UnderlayConfigurator: Trying to pre kill node with nonexistant TransportAddress!");
00406     }
00407 
00408     // do not migrate node that is already scheduled
00409     if(scheduledID.count(nodeID))
00410         return;
00411 
00412     cModule* node = accessNetModule->removeOverlayNode(nodeID);//intuniform(0, accessNetModule->size() - 1));
00413 
00414     if(node == NULL)
00415         opp_error("IPv4UnderlayConfigurator: Trying to remove node which is nonexistant in AccessNet!");
00416 
00417     //remove node from bootstrap oracle
00418     bootstrapOracle->killPeer(IPAddressResolver().addressOf(node));
00419 
00420     node->bubble("I am migrating!");
00421 
00422     // connect the node to another access net
00423     AccessNet* newAccessNetModule;
00424 
00425     do {
00426         newAccessNetModule = check_and_cast<AccessNet*>(accessNode[intuniform(0, accessNode.size() - 1)]->submodule("accessNet"));
00427     } while((newAccessNetModule == accessNetModule) && (accessNode.size() != 1));
00428 
00429     // create meta information
00430     IPv4Info* newinfo = new IPv4Info(type.typeID, node->id());
00431     // add node to a randomly chosen access net
00432     newinfo->setAccessNetModule(newAccessNetModule);
00433     newinfo->setNodeID(newAccessNetModule->addOverlayNode(node, true));
00434 
00435     //add node to bootstrap oracle
00436     bootstrapOracle->addPeer(IPAddressResolver().addressOf(node), newinfo);
00437 
00438     // inform the notofication board about the migration
00439     NotificationBoard* nb = check_and_cast<NotificationBoard*>(node->submodule("notificationBoard"));
00440     nb->fireChangeNotification(NF_OVERLAY_TRANSPORTADDRESS_CHANGED);
00441 }

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.

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

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

process timer messages

Parameters:
msg the received message

Reimplemented from UnderlayConfigurator.

00444 {
00445     Enter_Method_Silent();
00446 
00447     // get next scheduled node from the kill list
00448     IPvXAddress addr = killList.back();
00449     killList.pop_back();
00450 
00451     AccessNet* accessNetModule = NULL;
00452     int nodeID = -1;
00453 
00454     IPv4Info* info = dynamic_cast<IPv4Info*>(bootstrapOracle->getPeerInfo(addr));
00455     if(info != NULL) {
00456         accessNetModule = info->getAccessNetModule();
00457         nodeID = info->getNodeID();
00458     } else {
00459         opp_error("IPv4UnderlayConfigurator: Trying to kill node with nonexistant TransportAddress!");
00460     }
00461 
00462     scheduledID.erase(nodeID);
00463     bootstrapOracle->killPeer(addr);
00464 
00465     cModule* node = accessNetModule->removeOverlayNode(nodeID);
00466 
00467     if(node == NULL)
00468         opp_error("IPv4UnderlayConfigurator: Trying to remove node which is nonexistant in AccessNet!");
00469 
00470     node->callFinish();
00471     node->deleteModule();
00472 
00473     delete msg;
00474 }

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

Saves statistics, prints simulation time.

Reimplemented from UnderlayConfigurator.

00484 {
00485     // statistics
00486     recordScalar("Terminals added", numCreated);
00487     recordScalar("Terminals removed", numKilled);
00488 
00489     if (!isInInitPhase()) {
00490         struct timeval now, diff;
00491         gettimeofday(&now, NULL);
00492         timersub(&now, &initFinishedTime, &diff);
00493         printf("Simulation time: %li.%06li\n", diff.tv_sec, diff.tv_usec);
00494     }
00495 }

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

Updates the statistics display string.

Implements UnderlayConfigurator.

Referenced by createNode(), and preKillNode().

00477 {
00478     char buf[80];
00479     sprintf(buf, "%i overlay terminals\n%i access router\n%i overlay access router", overlayTerminalCount, accessRouterNum, overlayAccessRouterNum);
00480     displayString().setTagArg("t", 0, buf);
00481 }


Member Data Documentation

number of access router

Referenced by initializeUnderlay(), and setDisplayString().

number of overlayAccessRouter

Referenced by initializeUnderlay(), and setDisplayString().

number of terminal in the overlay

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

stores accessRouter

Referenced by createNode(), initializeUnderlay(), and migrateNode().

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

stores nodes scheduled to be killed

Referenced by handleTimerEvent(), and preKillNode().

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

stores nodeIds to prevent migration of prekilled nodes

Referenced by handleTimerEvent(), migrateNode(), and preKillNode().

number of overall created overlay terminals

Referenced by createNode(), finishUnderlay(), and initializeUnderlay().

number of overall killed overlay terminals

Referenced by finishUnderlay(), initializeUnderlay(), and preKillNode().


The documentation for this class was generated from the following files:

Generated on Fri Sep 19 13:05:07 2008 for ITM OverSim by  doxygen 1.5.5