#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.
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.
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.
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.
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
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 }
int IPv4UnderlayConfigurator::accessRouterNum [private] |
int IPv4UnderlayConfigurator::overlayAccessRouterNum [private] |
int IPv4UnderlayConfigurator::overlayTerminalNum [private] |
number of terminal in the overlay
std::vector<cModule*> IPv4UnderlayConfigurator::accessNode [protected] |
std::deque<IPvXAddress> IPv4UnderlayConfigurator::killList [protected] |
std::set<int> IPv4UnderlayConfigurator::scheduledID [protected] |
stores nodeIds to prevent migration of prekilled nodes
Referenced by handleTimerEvent(), migrateNode(), and preKillNode().
int IPv4UnderlayConfigurator::numCreated [protected] |
number of overall created overlay terminals
Referenced by createNode(), finishUnderlay(), and initializeUnderlay().
int IPv4UnderlayConfigurator::numKilled [protected] |
number of overall killed overlay terminals
Referenced by finishUnderlay(), initializeUnderlay(), and preKillNode().