#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.
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.
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.
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.
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
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 }
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