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 <IPAddressResolver.h>
00032 #include <IPv4InterfaceData.h>
00033 
00034 #include "AccessNet.h"
00035 
00036 Define_Module(AccessNet);
00037 
00038 std::ostream& operator<<(std::ostream& os, NodeInfo& n)
00039 {
00040     os << IPAddress(n.IPAddress);
00041     return os;
00042 }
00043 
00044 void AccessNet::initialize(int stage)
00045 {
00046     if(stage != MIN_STAGE_UNDERLAY + 1)
00047         return;
00048 
00049     router.module = getParentModule();
00050     router.interfaceTable = IPAddressResolver().interfaceTableOf(getParentModule());
00051     router.routingTable = IPAddressResolver().routingTableOf(getParentModule());
00052     router.IPAddress = IPAddressResolver().addressOf(getParentModule()).get4().getInt();
00053 
00054     channelTypesTx = cStringTokenizer(par("channelTypes"), " ").asVector();
00055     channelTypesRx = cStringTokenizer(par("channelTypesRx"), " ").asVector();
00056     
00057     if (channelTypesRx.size() != channelTypesTx.size()) {
00058         channelTypesRx = channelTypesTx;
00059     }
00060     
00061     int chanIndex = intuniform(0, channelTypesTx.size()-1);
00062 
00063     selectChannel(channelTypesRx[chanIndex], channelTypesTx[chanIndex]);
00064 
00065     // statistics
00066     lifetimeVector.setName("Terminal Lifetime");
00067 
00068     WATCH_VECTOR(overlayTerminal);
00069 
00070     lastIP = 0;
00071 
00072     updateDisplayString();
00073 }
00074 
00075 void AccessNet::handleMessage(cMessage* msg)
00076 {
00077     error("this module doesn't handle messages, it runs only in initialize()");
00078 }
00079 
00080 int AccessNet::addOverlayNode(cModule* node, bool migrate)
00081 {
00082     Enter_Method("addOverlayNode()");
00083 
00084     TerminalInfo terminal;
00085     terminal.module = node;
00086     terminal.interfaceTable = IPAddressResolver().interfaceTableOf(node);
00087     terminal.remoteInterfaceTable = router.interfaceTable;
00088     terminal.routingTable = IPAddressResolver().routingTableOf(node);
00089     terminal.PPPInterface = node->getSubmodule("ppp", 0);
00090     terminal.createdAt = simTime();
00091 
00092     // find unassigned ip address:
00093     //   Start at last given address, check if next address is valid and free.
00094     bool ip_test = false;
00095     for (uint32 ipOffset = lastIP + 1; ipOffset != lastIP; ipOffset++) {
00096         if ( ipOffset == 0x10000) {
00097             // Netmask = 255.255.0.0, so roll over if offset = 2**16
00098             ipOffset = 0;
00099             continue;
00100         }
00101 
00102         uint32_t ip = router.IPAddress + ipOffset;
00103 
00104         // Check if IP is valid:
00105         //   Reject x.y.z.0 or x.y.z.255 or x.y.255.z
00106         if ( ((ip & 0xff) == 0) || ((ip & 0xff) == 0xff)
00107              || ((ip & 0xff00) == 0xff00) ) {
00108             continue;
00109         }
00110 
00111         // Check if IP is free
00112         ip_test = true;
00113         for (uint32_t i = 0; i < overlayTerminal.size(); i++) {
00114             if (overlayTerminal[i].IPAddress == ip) {
00115                 ip_test = false;
00116                 break;
00117             }
00118         }
00119 
00120         // found valid IP
00121         if (ip_test) {
00122             terminal.IPAddress = ip;
00123             lastIP = ipOffset;
00124             break;
00125         }
00126     }
00127     if (!ip_test)
00128         opp_error ("Error creating node: No available IP in access net!");
00129 
00130     // update ip display string
00131     if (ev.isGUI()) {
00132         const char* ip_disp = const_cast<char*>
00133             (IPAddress(terminal.IPAddress).str().c_str());
00134         terminal.module->getDisplayString().insertTag("t", 0);
00135         terminal.module->getDisplayString().setTagArg("t", 0, ip_disp);
00136         terminal.module->getDisplayString().setTagArg("t", 1, "l");
00137     }
00138 
00139 
00140     //
00141     // Create new remote ppp interface module for this terminal
00142     //
00143 
00144     // create ppp interface module
00145 
00146     int k = 1;
00147     while ( router.module->findSubmodule("ppp", k) != -1 )
00148         k++;
00149 
00150     cModuleType* pppInterfaceModuleType = cModuleType::get("inet.linklayer.ppp.PPPInterface");
00151     terminal.remotePPPInterface = pppInterfaceModuleType->
00152         create("ppp", router.module, 0, k);
00153 
00154 
00155     //
00156     // Connect all gates
00157     //
00158 
00159     // connect terminal to access router and vice versa
00160     cGate* routerInGate = firstUnusedGate(router.module, "pppg", cGate::INPUT);
00161     cGate* routerOutGate = firstUnusedGate(router.module, "pppg", cGate::OUTPUT);
00162 
00163     cChannelType* channelTypeRx = cChannelType::find( channelTypeRxStr.c_str() );
00164     cChannelType* channelTypeTx = cChannelType::find( channelTypeTxStr.c_str() );
00165     if (!channelTypeRx || !channelTypeTx) 
00166         opp_error("Could not find Channel or ChannelRx Type. Most likely "
00167                     "parameter channelTypes does not match the channels defined "
00168                     "in channels.ned");
00169 
00170     terminal.module->gate("pppg$o", 0)->connectTo(routerInGate,
00171                                 channelTypeRx->create(channelTypeRxStr.c_str()));
00172     routerOutGate->connectTo(terminal.module->gate("pppg$i", 0),
00173                              channelTypeTx->create(channelTypeTxStr.c_str()));
00174 
00175     // connect ppp interface module to router module and vice versa
00176     routerInGate->connectTo(terminal.remotePPPInterface->gate("phys$i"));
00177     terminal.remotePPPInterface->gate("phys$o")->connectTo(routerOutGate);
00178 
00179     // connect ppp interface module to network layer module and vice versa
00180     cModule* netwModule = router.module->getSubmodule("networkLayer");
00181 
00182     cGate* netwInGate = firstUnusedGate(netwModule, "ifIn");
00183     cGate* netwOutGate = firstUnusedGate(netwModule, "ifOut");
00184 
00185     netwOutGate->connectTo(terminal.remotePPPInterface->gate("netwIn"));
00186     terminal.remotePPPInterface->gate("netwOut")->connectTo(netwInGate);
00187 
00188     // connect network layer module to ip and arp modules
00189     cModule* ipModule = router.module->getSubmodule("networkLayer")->
00190         getSubmodule("ip");
00191 
00192     cGate* ipIn = firstUnusedGate(ipModule, "queueIn");
00193     netwInGate->connectTo(ipIn);
00194 
00195 #ifdef _ORIG_INET
00196     cModule* arpModule = router.module->getSubmodule("networkLayer")->getSubmodule("arp"); //comment out for speed-hack
00197 
00198     cGate* arpOut = firstUnusedGate(arpModule, "nicOut"); //comment out for speed-hack
00199 
00200     //cGate* ipOut = firstUnusedGate(ipModule, "queueOut"); //comment out for speed-hack
00201     cGate* ipOut = ipModule->gate("queueOut");
00202 
00203     arpOut->connectTo(netwOutGate);     //comment out for speed-hack
00204 #endif
00205 
00206     //
00207     // Start ppp interface modules
00208     //
00209     terminal.remotePPPInterface->finalizeParameters();
00210     terminal.remotePPPInterface->setDisplayString("i=block/ifcard");
00211     terminal.remotePPPInterface->buildInside();
00212     terminal.remotePPPInterface->scheduleStart(simTime());
00213     terminal.remotePPPInterface->callInitialize();
00214 
00215     if ( !migrate) {
00216         // we are already in stage 4 and need to call initialize
00217         // for all previous stages manually
00218         for (int i=0; i < MAX_STAGE_UNDERLAY + 1; i++) {
00219             terminal.module->callInitialize(i);
00220         }
00221     }
00222 
00223     terminal.remoteInterfaceEntry = router.interfaceTable->getInterface(
00224         router.interfaceTable->getNumInterfaces() - 1);
00225     terminal.interfaceEntry = terminal.interfaceTable->getInterfaceByName("ppp0");
00226 
00227 
00228     //
00229     // Fill in interface table.
00230     //
00231 
00232     // router
00233     IPv4InterfaceData* interfaceData = new IPv4InterfaceData;
00234     interfaceData->setIPAddress(router.IPAddress);
00235     interfaceData->setNetmask(IPAddress::ALLONES_ADDRESS);
00236     terminal.remoteInterfaceEntry->setIPv4Data(interfaceData);
00237 
00238     // terminal
00239     terminal.interfaceEntry->ipv4Data()->setIPAddress(IPAddress(terminal.IPAddress));
00240     terminal.interfaceEntry->ipv4Data()->setNetmask(IPAddress::ALLONES_ADDRESS);
00241 
00242     //
00243     // Fill in routing table.
00244     //
00245 
00246     // router
00247     IPRoute* re = new IPRoute();
00248     re->setHost(IPAddress(terminal.IPAddress));
00249     re->setNetmask(IPAddress(IPAddress::ALLONES_ADDRESS));
00250     re->setInterface(terminal.remoteInterfaceEntry);
00251     re->setType(IPRoute::DIRECT);
00252     re->setSource(IPRoute::MANUAL);
00253     router.routingTable->addRoute(re);
00254     terminal.remoteRoutingEntry = re;
00255 
00256     // terminal
00257     IPRoute* te = new IPRoute();
00258     te->setHost(IPAddress::UNSPECIFIED_ADDRESS);
00259     te->setNetmask(IPAddress::UNSPECIFIED_ADDRESS);
00260     te->setGateway(router.IPAddress);
00261     te->setInterface(terminal.interfaceEntry);
00262     te->setType(IPRoute::REMOTE);
00263     te->setSource(IPRoute::MANUAL);
00264     terminal.routingTable->addRoute(te);
00265     terminal.routingEntry = te;
00266 
00267 
00268     // append module to overlay terminal vector
00269     overlayTerminal.push_back(terminal);
00270     int ID = terminal.module->getId();
00271 
00272     updateDisplayString();
00273 
00274     return ID;
00275 }
00276 
00277 int AccessNet::getRandomNodeId()
00278 {
00279     Enter_Method("getRandomNodeId()");
00280 
00281     return overlayTerminal[intuniform(0, overlayTerminal.size() - 1)].module->getId();
00282 }
00283 
00284 cModule* AccessNet::removeOverlayNode(int ID)
00285 {
00286     Enter_Method("removeOverlayNode()");
00287 
00288     cModule* node = NULL;
00289     TerminalInfo terminal;
00290     int index;
00291 
00292     for(unsigned int i=0; i<overlayTerminal.size(); i++) {
00293         if(overlayTerminal[i].module->getId() == ID) {
00294             terminal = overlayTerminal[i];
00295             node = terminal.module;
00296             index = i;
00297         }
00298     }
00299 
00300     if(node == NULL) return NULL;
00301 
00302     cModule* ppp = terminal.remotePPPInterface;
00303 
00304     // disconnect terminal
00305     node->gate("pppg$o", 0)->disconnect();
00306     node->gate("pppg$i", 0)->getPreviousGate()->disconnect();
00307 
00308     // disconnect ip and arp modules
00309     ppp->gate("netwIn")->getPathStartGate()->disconnect();
00310     ppp->gate("netwOut")->getNextGate()->disconnect();
00311 
00312     // remove associated ppp interface module
00313     ppp->callFinish();
00314     ppp->deleteModule();
00315 
00316     // remove associated interface table entry
00317     router.interfaceTable->deleteInterface(terminal.remoteInterfaceEntry);
00318 
00319     // remove routing entries
00320     terminal.routingTable->deleteRoute(terminal.routingEntry);
00321     router.routingTable->deleteRoute(terminal.remoteRoutingEntry);
00322 
00323     // statistics
00324     lifetimeVector.record(simTime() - overlayTerminal[index].createdAt);
00325 
00326     // remove terminal from overlay terminal vector
00327     overlayTerminal.erase(overlayTerminal.begin() + index);
00328 
00329     updateDisplayString();
00330 
00331     return node;
00332 }
00333 
00334 cModule* AccessNet::getOverlayNode(int ID)
00335 {
00336     Enter_Method("getOverlayNode()");
00337 
00338     cModule* node = NULL;
00339 
00340     for(unsigned int i=0; i<overlayTerminal.size(); i++) {
00341         if(overlayTerminal[i].module->getId() == ID)
00342             node = overlayTerminal[i].module;
00343     }
00344     return node;
00345 }
00346 
00347 void AccessNet::updateDisplayString()
00348 {
00349     if (ev.isGUI()) {
00350         char buf[80];
00351         if ( overlayTerminal.size() == 1 ) {
00352             sprintf(buf, "1 terminal connected");
00353         } else {
00354             sprintf(buf, "%zi terminals connected", overlayTerminal.size());
00355         }
00356         getDisplayString().setTagArg("t", 0, buf);
00357         getDisplayString().setTagArg("t", 2, "blue");
00358     }
00359 }
00360 
00361 cGate* firstUnusedGate(cModule* owner, const char* name, cGate::Type type)
00362 {
00363     int index;
00364     for (index = 0; index < owner->gateSize(name); index++) {
00365         cGate *gate = type == cGate::NONE ? owner->gate(name, index) : owner->gateHalf(name, type, index);
00366         if (!gate->isConnectedOutside()) {
00367             return gate;
00368         }
00369     }
00370 
00371     owner->setGateSize(name, index + 2);
00372     return type == cGate::NONE ? owner->gate(name, index + 1) : owner->gateHalf(name, type, index + 1);
00373 }
00374 
Generated on Wed May 26 16:21:13 2010 for OverSim by  doxygen 1.6.3