#include <IPv4UnderlayConfigurator.h>
Inheritance diagram for IPv4UnderlayConfigurator:
Public Member Functions | |
TransportAddress * | createNode (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 |
TransportAddress * IPv4UnderlayConfigurator::createNode | ( | NodeType | type, | |
bool | initialize = false | |||
) | [virtual] |
Creates an overlay node.
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.
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.
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.
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
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 }
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