#include <IPv4UnderlayConfigurator.h>
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.
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.
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.
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.
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
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 }
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