AccessNet.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2006 Institut fuer Telematik, Universitaet Karlsruhe (TH)
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 //
00018 
00024 #include <vector>
00025 #include <iostream>
00026 
00027 #include <omnetpp.h>
00028 
00029 #include <IRoutingTable.h>
00030 #include <IInterfaceTable.h>
00031 #include <RoutingTable6.h>
00032 #include <IPAddressResolver.h>
00033 #include <IPv4InterfaceData.h>
00034 #include <IPv6InterfaceData.h>
00035 
00036 #include "AccessNet.h"
00037 
00038 Define_Module(AccessNet);
00039 
00040 std::ostream& operator<<(std::ostream& os, NodeInfo& n)
00041 {
00042     os << n.IPAddress;
00043     return os;
00044 }
00045 
00046 void AccessNet::initialize(int stage)
00047 {
00048     if(stage != MIN_STAGE_UNDERLAY + 1)
00049         return;
00050 
00051     router.module = getParentModule();
00052     router.interfaceTable = IPAddressResolver().interfaceTableOf(getParentModule());
00053     useIPv6 = par("useIPv6Addresses").boolValue();
00054     if (useIPv6){
00055         router.routingTable6 = IPAddressResolver().routingTable6Of(getParentModule());
00056         router.IPAddress = getAssignedPrefix(router.interfaceTable);
00057     } else {
00058         router.routingTable = IPAddressResolver().routingTableOf(getParentModule());
00059         router.IPAddress = IPAddressResolver().addressOf(getParentModule());
00060     }
00061 
00062     channelTypesTx = cStringTokenizer(par("channelTypes"), " ").asVector();
00063     channelTypesRx = cStringTokenizer(par("channelTypesRx"), " ").asVector();
00064     
00065     if (channelTypesRx.size() != channelTypesTx.size()) {
00066         channelTypesRx = channelTypesTx;
00067     }
00068     
00069     int chanIndex = intuniform(0, channelTypesTx.size()-1);
00070 
00071     selectChannel(channelTypesRx[chanIndex], channelTypesTx[chanIndex]);
00072 
00073     // statistics
00074     lifetimeVector.setName("Terminal Lifetime");
00075 
00076     WATCH_VECTOR(overlayTerminal);
00077 
00078     lastIP = 0;
00079 
00080     updateDisplayString();
00081 }
00082 
00083 void AccessNet::handleMessage(cMessage* msg)
00084 {
00085     error("this module doesn't handle messages, it runs only in initialize()");
00086 }
00087 
00088 IPvXAddress AccessNet::addOverlayNode(cModule* node, bool migrate)
00089 {
00090     Enter_Method("addOverlayNode()");
00091 
00092     TerminalInfo terminal;
00093     terminal.module = node;
00094     terminal.interfaceTable = IPAddressResolver().interfaceTableOf(node);
00095     terminal.remoteInterfaceTable = router.interfaceTable;
00096     if (useIPv6) {
00097         terminal.routingTable6 = IPAddressResolver().routingTable6Of(node);
00098     }
00099     else {
00100         terminal.routingTable = IPAddressResolver().routingTableOf(node);
00101     }
00102     terminal.PPPInterface = node->getSubmodule("ppp", 0);
00103     terminal.createdAt = simTime();
00104 
00105     // find unassigned ip address:
00106     // check list of returned IPs
00107     // TODO: check overlays for side effects of reused IP addresses
00108 //    if (returnedIPs.size() != 0) {
00109 //      terminal.IPAddress = returnedIPs.back();
00110 //      returnedIPs.pop_back();
00111 //    }
00112 //    else {
00113     if (useIPv6) {
00114         IPv6Words candidate(router.IPAddress);
00115         // we dont need to check for duplicates because of the giant address space and reuse of old IPs
00116         candidate.d1 += ++lastIP;
00117         terminal.IPAddress = IPvXAddress(IPv6Address(candidate.d0, candidate.d1, candidate.d2, candidate.d3));
00118     } else {
00119         uint32_t routerAddr = router.IPAddress.get4().getInt();
00120 
00121         // Start at last given address, check if next address is valid and free.
00122         bool ip_test = false;
00123         for (uint32 ipOffset = lastIP + 1; ipOffset != lastIP; ipOffset++) {
00124             if ( ipOffset == 0x10000) {
00125                 // Netmask = 255.255.0.0, so roll over if offset = 2**16
00126                 ipOffset = 0;
00127                 continue;
00128             }
00129 
00130             uint32_t ip = routerAddr + ipOffset;
00131 
00132             // Check if IP is valid:
00133             //   Reject x.y.z.0 or x.y.z.255 or x.y.255.z
00134             if ( ((ip & 0xff) == 0) || ((ip & 0xff) == 0xff)
00135                     || ((ip & 0xff00) == 0xff00) ) {
00136                 continue;
00137             }
00138 
00139             // Check if IP is free
00140             ip_test = true;
00141             for (uint32_t i = 0; i < overlayTerminal.size(); i++) {
00142                 if (overlayTerminal[i].IPAddress == ip) {
00143                     ip_test = false;
00144                     break;
00145                 }
00146             }
00147 
00148             // found valid IP
00149             if (ip_test) {
00150                 terminal.IPAddress = IPvXAddress(ip);
00151                 lastIP = ipOffset;
00152                 break;
00153             }
00154         }
00155         if (!ip_test)
00156             opp_error ("Error creating node: No available IP in access net!");
00157     }
00158 //    }
00159 
00160     // update ip display string
00161     if (ev.isGUI()) {
00162         const char* ip_disp = const_cast<char*>
00163         (terminal.IPAddress.str().c_str());
00164         terminal.module->getDisplayString().insertTag("t", 0);
00165         terminal.module->getDisplayString().setTagArg("t", 0, ip_disp);
00166         terminal.module->getDisplayString().setTagArg("t", 1, "l");
00167     }
00168 
00169 
00170     //
00171     // Create new remote ppp interface module for this terminal
00172     //
00173 
00174     // create ppp interface module
00175 
00176     int k = 1;
00177     while ( router.module->findSubmodule("ppp", k) != -1 )
00178         k++;
00179 
00180     cModuleType* pppInterfaceModuleType = cModuleType::get("inet.linklayer.ppp.PPPInterface");
00181     terminal.remotePPPInterface = pppInterfaceModuleType->
00182     create("ppp", router.module, 0, k);
00183 
00184 
00185     //
00186     // Connect all gates
00187     //
00188 
00189     // connect terminal to access router and vice versa
00190     cGate* routerInGate = firstUnusedGate(router.module, "pppg", cGate::INPUT);
00191     cGate* routerOutGate = firstUnusedGate(router.module, "pppg", cGate::OUTPUT);
00192 
00193     cChannelType* channelTypeRx = cChannelType::find( channelTypeRxStr.c_str() );
00194     cChannelType* channelTypeTx = cChannelType::find( channelTypeTxStr.c_str() );
00195     if (!channelTypeRx || !channelTypeTx) 
00196         opp_error("Could not find Channel or ChannelRx Type. Most likely "
00197             "parameter channelTypes does not match the channels defined "
00198             "in channels.ned");
00199 
00200     terminal.module->gate("pppg$o", 0)->connectTo(routerInGate,
00201                 channelTypeRx->create(channelTypeRxStr.c_str()));
00202     routerOutGate->connectTo(terminal.module->gate("pppg$i", 0),
00203                  channelTypeTx->create(channelTypeTxStr.c_str()));
00204 
00205     // connect ppp interface module to router module and vice versa
00206     routerInGate->connectTo(terminal.remotePPPInterface->gate("phys$i"));
00207     terminal.remotePPPInterface->gate("phys$o")->connectTo(routerOutGate);
00208 
00209     // connect ppp interface module to network layer module and vice versa
00210     cModule* netwModule = router.module->getSubmodule("networkLayer");
00211 
00212     cGate* netwInGate = firstUnusedGate(netwModule, "ifIn");
00213     cGate* netwOutGate = firstUnusedGate(netwModule, "ifOut");
00214 
00215     netwOutGate->connectTo(terminal.remotePPPInterface->gate("netwIn"));
00216     terminal.remotePPPInterface->gate("netwOut")->connectTo(netwInGate);
00217 
00218     // connect network layer module to ip and arp modules
00219     cModule* ipModule;
00220     if (useIPv6) {
00221         ipModule = router.module->getSubmodule("networkLayer")->getSubmodule("ipv6");
00222     }
00223     else {
00224         ipModule = router.module->getSubmodule("networkLayer")->getSubmodule("ip");
00225     }
00226 
00227     cGate* ipIn = firstUnusedGate(ipModule, "queueIn");
00228     netwInGate->connectTo(ipIn);
00229 
00230     if(useIPv6) {
00231         cGate* ipOut = firstUnusedGate(ipModule, "queueOut");
00232         ipOut->connectTo(netwOutGate);
00233     }
00234 
00235 #ifdef _ORIG_INET
00236     cModule* arpModule = router.module->getSubmodule("networkLayer")->getSubmodule("arp"); //comment out for speed-hack
00237 
00238     cGate* arpOut = firstUnusedGate(arpModule, "nicOut"); //comment out for speed-hack
00239 
00240     //cGate* ipOut = firstUnusedGate(ipModule, "queueOut"); //comment out for speed-hack
00241     cGate* ipOut = ipModule->gate("queueOut");
00242 
00243     arpOut->connectTo(netwOutGate);    //comment out for speed-hack
00244 #endif
00245 
00246     //
00247     // Start ppp interface modules
00248     //
00249     terminal.remotePPPInterface->finalizeParameters();
00250     terminal.remotePPPInterface->setDisplayString("i=block/ifcard");
00251     terminal.remotePPPInterface->buildInside();
00252     terminal.remotePPPInterface->scheduleStart(simTime());
00253     terminal.remotePPPInterface->callInitialize();
00254 
00255     if ( !migrate) {
00256         // we are already in stage 4 and need to call initialize
00257     // for all previous stages manually
00258         for (int i=0; i < MAX_STAGE_UNDERLAY + 1; i++) {
00259             terminal.module->callInitialize(i);
00260         }
00261     }
00262 
00263     terminal.remoteInterfaceEntry = router.interfaceTable->getInterface(
00264             router.interfaceTable->getNumInterfaces() - 1);
00265     terminal.interfaceEntry = terminal.interfaceTable->getInterfaceByName("ppp0");
00266 
00267 
00268     //
00269     // Fill in interface table and routing table.
00270     //
00271 
00272     if (useIPv6) {
00273         //
00274         // Fill in interface table.
00275 
00276         // router
00277         IPv6InterfaceData* interfaceData = new IPv6InterfaceData;
00278         interfaceData->setAdvSendAdvertisements(true); // router
00279         interfaceData->assignAddress(IPv6Address::formLinkLocalAddress(terminal.remoteInterfaceEntry->getInterfaceToken()), false, 0, 0);
00280         terminal.remoteInterfaceEntry->setIPv6Data(interfaceData);
00281         terminal.remoteInterfaceEntry->setMACAddress(MACAddress::generateAutoAddress());
00282 
00283         // terminal
00284         terminal.interfaceEntry->ipv6Data()->setAdvSendAdvertisements(false); // host
00285         terminal.interfaceEntry->ipv6Data()->assignAddress(terminal.IPAddress.get6(), false, 0, 0);
00286         terminal.interfaceEntry->ipv6Data()->assignAddress(IPv6Address::formLinkLocalAddress(terminal.interfaceEntry->getInterfaceToken()), false, 0, 0);
00287         terminal.interfaceEntry->setMACAddress(MACAddress::generateAutoAddress());
00288 
00289         //
00290         // Fill in routing table.
00291         //
00292 
00293         // router
00294         router.routingTable6->addStaticRoute(terminal.IPAddress.get6(),64, terminal.remoteInterfaceEntry->getInterfaceId(), terminal.interfaceEntry->ipv6Data()->getLinkLocalAddress());
00295 
00296         // terminal
00297         terminal.routingTable6->addDefaultRoute(terminal.remoteInterfaceEntry->ipv6Data()->getLinkLocalAddress(), terminal.interfaceEntry->getInterfaceId(), 0);
00298 
00299     } else {
00300 
00301         //
00302         // Fill in interface table.
00303         //
00304 
00305         // router
00306         IPv4InterfaceData* interfaceData = new IPv4InterfaceData;
00307         interfaceData->setIPAddress(router.IPAddress.get4());
00308         interfaceData->setNetmask(IPAddress::ALLONES_ADDRESS);
00309         terminal.remoteInterfaceEntry->setIPv4Data(interfaceData);
00310 
00311         // terminal
00312         terminal.interfaceEntry->ipv4Data()->setIPAddress(terminal.IPAddress.get4());
00313         terminal.interfaceEntry->ipv4Data()->setNetmask(IPAddress::ALLONES_ADDRESS);
00314 
00315         //
00316         // Fill in routing table.
00317         //
00318 
00319         // router
00320         IPRoute* re = new IPRoute();
00321         re->setHost(terminal.IPAddress.get4());
00322         re->setNetmask(IPAddress(IPAddress::ALLONES_ADDRESS));
00323         re->setInterface(terminal.remoteInterfaceEntry);
00324         re->setType(IPRoute::DIRECT);
00325         re->setSource(IPRoute::MANUAL);
00326         router.routingTable->addRoute(re);
00327         terminal.remoteRoutingEntry = re;
00328 
00329         // terminal
00330         IPRoute* te = new IPRoute();
00331         te->setHost(IPAddress::UNSPECIFIED_ADDRESS);
00332         te->setNetmask(IPAddress::UNSPECIFIED_ADDRESS);
00333         te->setGateway(router.IPAddress.get4());
00334         te->setInterface(terminal.interfaceEntry);
00335         te->setType(IPRoute::REMOTE);
00336         te->setSource(IPRoute::MANUAL);
00337         terminal.routingTable->addRoute(te);
00338         terminal.routingEntry = te;
00339 
00340     }
00341 
00342 
00343     // append module to overlay terminal vector
00344     overlayTerminal.push_back(terminal);
00345     //int ID = terminal.module->getId();
00346 
00347     updateDisplayString();
00348 
00349     return terminal.IPAddress;
00350 }
00351 
00352 int AccessNet::getRandomNodeId()
00353 {
00354     Enter_Method("getRandomNodeId()");
00355 
00356     return overlayTerminal[intuniform(0, overlayTerminal.size() - 1)].module->getId();
00357 }
00358 
00359 cModule* AccessNet::removeOverlayNode(int ID)
00360 {
00361     Enter_Method("removeOverlayNode()");
00362 
00363     cModule* node = NULL;
00364     TerminalInfo terminal;
00365     int index;
00366 
00367     for(unsigned int i=0; i<overlayTerminal.size(); i++) {
00368         if(overlayTerminal[i].module->getId() == ID) {
00369             terminal = overlayTerminal[i];
00370             node = terminal.module;
00371             index = i;
00372         }
00373     }
00374 
00375     if(node == NULL) return NULL;
00376 
00377     cModule* ppp = terminal.remotePPPInterface;
00378 
00379     // disconnect terminal
00380     node->gate("pppg$o", 0)->disconnect();
00381     node->gate("pppg$i", 0)->getPreviousGate()->disconnect();
00382 
00383     // disconnect ip and arp modules
00384     ppp->gate("netwIn")->getPathStartGate()->disconnect();
00385     ppp->gate("netwOut")->getNextGate()->disconnect();
00386 
00387     // remove associated ppp interface module
00388     ppp->callFinish();
00389     ppp->deleteModule();
00390 
00391     // remove associated interface table entry
00392     router.interfaceTable->deleteInterface(terminal.remoteInterfaceEntry);
00393 
00394     // remove routing entries //TODO: IPv6
00395     if (!useIPv6) {
00396         terminal.routingTable->deleteRoute(terminal.routingEntry);
00397         router.routingTable->deleteRoute(terminal.remoteRoutingEntry);
00398     } else {
00399 #if 0
00400         for (int i = 0; i < terminal.routingTable6->getNumRoutes(); i++) {
00401             IPv6Route* route = terminal.routingTable6->getRoute(i);
00402             if (route->getDestPrefix() == terminal.remoteInterfaceEntry->
00403                     ipv6Data()->getLinkLocalAddress()) {
00404                 terminal.routingTable6->purgeDestCacheEntriesToNeighbour(terminal.remoteInterfaceEntry->ipv6Data()->getLinkLocalAddress(), route->getInterfaceId());
00405                 terminal.routingTable6->removeRoute(route);
00406             }
00407         }
00408 #endif
00409 
00410         for (int i = 0; i < router.routingTable6->getNumRoutes(); i++) {
00411             IPv6Route* route = router.routingTable6->getRoute(i);
00412             if (route->getDestPrefix() == terminal.IPAddress.get6()) {
00413                 router.routingTable6->purgeDestCacheEntriesToNeighbour(terminal.interfaceEntry->ipv6Data()->getLinkLocalAddress(), route->getInterfaceId());
00414                 router.routingTable6->removeRoute(route);
00415                 break;
00416             }
00417         }
00418     }
00419 
00420     // statistics
00421     lifetimeVector.record(simTime() - overlayTerminal[index].createdAt);
00422 
00423     // remove terminal from overlay terminal vector
00424     overlayTerminal.erase(overlayTerminal.begin() + index);
00425 
00426     updateDisplayString();
00427 
00428     return node;
00429 }
00430 
00431 cModule* AccessNet::getOverlayNode(int ID)
00432 {
00433     Enter_Method("getOverlayNode()");
00434 
00435     cModule* node = NULL;
00436 
00437     for(unsigned int i=0; i<overlayTerminal.size(); i++) {
00438         if(overlayTerminal[i].module->getId() == ID)
00439             node = overlayTerminal[i].module;
00440     }
00441     return node;
00442 }
00443 
00444 void AccessNet::updateDisplayString()
00445 {
00446     if (ev.isGUI()) {
00447         char buf[80];
00448         if ( overlayTerminal.size() == 1 ) {
00449             sprintf(buf, "1 terminal connected");
00450         } else {
00451             sprintf(buf, "%zi terminals connected", overlayTerminal.size());
00452         }
00453         getDisplayString().setTagArg("t", 0, buf);
00454         getDisplayString().setTagArg("t", 2, "blue");
00455     }
00456 }
00457 
00458 cGate* firstUnusedGate(cModule* owner, const char* name, cGate::Type type)
00459 {
00460     int index;
00461     for (index = 0; index < owner->gateSize(name); index++) {
00462         cGate *gate = type == cGate::NONE ? owner->gate(name, index) : owner->gateHalf(name, type, index);
00463         if (!gate->isConnectedOutside()) {
00464             return gate;
00465         }
00466     }
00467 
00468     owner->setGateSize(name, index + 2);
00469     return type == cGate::NONE ? owner->gate(name, index + 1) : owner->gateHalf(name, type, index + 1);
00470 }
00471 
00472 IPvXAddress AccessNet::getAssignedPrefix(IInterfaceTable* ift)
00473 {
00474     //FIXME: support multiple prefixes
00475     for (int i = 0; i< ift->getNumInterfaces(); i++) {
00476         if (!ift->getInterface(i)->isLoopback()) {
00477             if (ift->getInterface(i)->ipv6Data()->getNumAdvPrefixes() == 1)
00478                 return ift->getInterface(i)->ipv6Data()->getAdvPrefix(0).prefix;
00479             else
00480                 opp_error("Prefix is not unique.");
00481         }
00482     }
00483     return IPvXAddress();
00484 }