SimpleUDP.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2000 Institut fuer Telematik, Universitaet Karlsruhe
00003 // Copyright (C) 2004,2005 Andras Varga
00004 //
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018 //
00019 
00025 //
00026 // Author: Jochen Reber
00027 // Rewrite: Andras Varga 2004,2005
00028 // Modifications: Stephan Krause
00029 //
00030 
00031 #include <omnetpp.h>
00032 
00033 #include <CommonMessages_m.h>
00034 #include <GlobalNodeListAccess.h>
00035 #include <GlobalStatisticsAccess.h>
00036 
00037 #include <SimpleInfo.h>
00038 #include "UDPPacket.h"
00039 #include "SimpleUDP.h"
00040 #include "IPControlInfo.h"
00041 #include "IPv6ControlInfo.h"
00042 
00043 #include "IPAddressResolver.h"
00044 
00045 #include "IPDatagram_m.h"
00046 #include "IPv6Datagram_m.h"
00047 
00048 
00049 #define EPHEMERAL_PORTRANGE_START 1024
00050 #define EPHEMERAL_PORTRANGE_END   5000
00051 
00052 
00053 Define_Module( SimpleUDP );
00054 
00055 std::string SimpleUDP::delayFaultTypeString;
00056 std::map<std::string, SimpleUDP::delayFaultTypeNum> SimpleUDP::delayFaultTypeMap;
00057 
00058 static std::ostream & operator<<(std::ostream & os,
00059                                  const SimpleUDP::SockDesc& sd)
00060 {
00061     os << "sockId=" << sd.sockId;
00062     os << " appGateIndex=" << sd.appGateIndex;
00063     os << " userId=" << sd.userId;
00064     os << " localPort=" << sd.localPort;
00065     if (sd.remotePort!=0)
00066         os << " remotePort=" << sd.remotePort;
00067     if (!sd.localAddr.isUnspecified())
00068         os << " localAddr=" << sd.localAddr;
00069     if (!sd.remoteAddr.isUnspecified())
00070         os << " remoteAddr=" << sd.remoteAddr;
00071     if (sd.interfaceId!=-1)
00072         os << " interfaceId=" << sd.interfaceId;
00073 
00074     return os;
00075 }
00076 
00077 static std::ostream & operator<<(std::ostream & os,
00078                                  const SimpleUDP::SockDescList& list)
00079 {
00080     for (SimpleUDP::SockDescList::const_iterator i=list.begin();
00081      i!=list.end(); ++i)
00082         os << "sockId=" << (*i)->sockId << " ";
00083     return os;
00084 }
00085 
00086 //--------
00087 
00088 SimpleUDP::SimpleUDP()
00089 {
00090     globalStatistics = NULL;
00091 }
00092 
00093 SimpleUDP::~SimpleUDP()
00094 {
00095 
00096 }
00097 
00098 void SimpleUDP::initialize(int stage)
00099 {
00100     if(stage == MIN_STAGE_UNDERLAY) {
00101         WATCH_PTRMAP(socketsByIdMap);
00102         WATCH_MAP(socketsByPortMap);
00103 
00104         lastEphemeralPort = EPHEMERAL_PORTRANGE_START;
00105         icmp = NULL;
00106         icmpv6 = NULL;
00107 
00108         numSent = 0;
00109         numPassedUp = 0;
00110         numDroppedWrongPort = 0;
00111         numDroppedBadChecksum = 0;
00112         numQueueLost = 0;
00113         numPartitionLost = 0;
00114         numDestUnavailableLost = 0;
00115         WATCH(numSent);
00116         WATCH(numPassedUp);
00117         WATCH(numDroppedWrongPort);
00118         WATCH(numDroppedBadChecksum);
00119         WATCH(numQueueLost);
00120         WATCH(numPartitionLost);
00121         WATCH(numDestUnavailableLost);
00122 
00123         globalNodeList = GlobalNodeListAccess().get();
00124         globalStatistics = GlobalStatisticsAccess().get();
00125         constantDelay = par("constantDelay");
00126         useCoordinateBasedDelay = par("useCoordinateBasedDelay");
00127 
00128         delayFaultTypeString = par("delayFaultType").stdstringValue();
00129         delayFaultTypeMap["live_all"] = delayFaultLiveAll;
00130         delayFaultTypeMap["live_planetlab"] = delayFaultLivePlanetlab;
00131         delayFaultTypeMap["simulation"] = delayFaultSimulation;
00132 
00133         switch (delayFaultTypeMap[delayFaultTypeString]) {
00134         case SimpleUDP::delayFaultLiveAll:
00135         case SimpleUDP::delayFaultLivePlanetlab:
00136         case SimpleUDP::delayFaultSimulation:
00137             faultyDelay = true;
00138             break;
00139         default:
00140             faultyDelay = false;
00141         }
00142 
00143         jitter = par("jitter");
00144         nodeEntry = NULL;
00145         WATCH_PTR(nodeEntry);
00146     }
00147 }
00148 
00149 void SimpleUDP::finish()
00150 {
00151     globalStatistics->addStdDev("SimpleUDP: Packets sent",
00152                                 numSent);
00153     globalStatistics->addStdDev("SimpleUDP: Packets dropped with bad checksum",
00154                                 numDroppedBadChecksum);
00155     globalStatistics->addStdDev("SimpleUDP: Packets dropped due to queue overflows",
00156                                 numQueueLost);
00157     globalStatistics->addStdDev("SimpleUDP: Packets dropped due to network partitions",
00158                                 numPartitionLost);
00159     globalStatistics->addStdDev("SimpleUDP: Packets dropped due to unavailable destination",
00160                                 numDestUnavailableLost);
00161 }
00162 
00163 void SimpleUDP::updateDisplayString()
00164 {
00165     char buf[80];
00166     sprintf(buf, "passed up: %d pks\nsent: %d pks", numPassedUp, numSent);
00167     if (numDroppedWrongPort>0) {
00168         sprintf(buf+strlen(buf), "\ndropped (no app): %d pks", numDroppedWrongPort);
00169         getDisplayString().setTagArg("i",1,"red");
00170     }
00171     if (numQueueLost>0) {
00172         sprintf(buf+strlen(buf), "\nlost (queue overflow): %d pks", numQueueLost);
00173         getDisplayString().setTagArg("i",1,"red");
00174     }
00175     getDisplayString().setTagArg("t",0,buf);
00176 }
00177 
00178 void SimpleUDP::processUndeliverablePacket(UDPPacket *udpPacket, cPolymorphic *ctrl)
00179 {
00180     numDroppedWrongPort++;
00181     EV << "[SimpleUDP::processUndeliverablePacket()]\n"
00182        << "    Dropped packet bound to unreserved port, ignoring ICMP error"
00183        << endl;
00184 
00185     delete udpPacket;
00186 }
00187 
00188 void SimpleUDP::processUDPPacket(UDPPacket *udpPacket)
00189 {
00190     // simulate checksum: discard packet if it has bit error
00191     EV << "Packet " << udpPacket->getName() << " received from network, dest port " << udpPacket->getDestinationPort() << "\n";
00192     if (udpPacket->hasBitError())
00193     {
00194         EV << "Packet has bit error, discarding\n";
00195         delete udpPacket;
00196         numDroppedBadChecksum++;
00197         return;
00198     }
00199 
00200     int destPort = udpPacket->getDestinationPort();
00201     cPolymorphic *ctrl = udpPacket->removeControlInfo();
00202 
00203     // send back ICMP error if no socket is bound to that port
00204     SocketsByPortMap::iterator it = socketsByPortMap.find(destPort);
00205     if (it==socketsByPortMap.end())
00206     {
00207         EV << "No socket registered on port " << destPort << "\n";
00208         processUndeliverablePacket(udpPacket, ctrl);
00209         return;
00210     }
00211     SockDescList& list = it->second;
00212 
00213     int matches = 0;
00214 
00215     // deliver a copy of the packet to each matching socket
00216     cPacket *payload = udpPacket->decapsulate();
00217     if (dynamic_cast<IPControlInfo *>(ctrl)!=NULL)
00218     {
00219         IPControlInfo *ctrl4 = (IPControlInfo *)ctrl;
00220         for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it)
00221         {
00222             SockDesc *sd = *it;
00223             if (sd->onlyLocalPortIsSet || matchesSocket(sd, udpPacket, ctrl4))
00224             {
00225                 //EV << "Socket sockId=" << sd->sockId << " matches, sending up a copy.\n";
00226                 //sendUp((cPacket*)payload->dup(), udpPacket, ctrl4, sd);
00227                 // ib: speed hack
00228                 if (matches == 0) {
00229                     sendUp((cPacket*)payload, udpPacket, ctrl4, sd);
00230                 } else {
00231                     opp_error("Edit SimpleUDP.cc to support multibinding.");
00232                 }
00233                 matches++;
00234             }
00235         }
00236     }
00237     else if (dynamic_cast<IPv6ControlInfo *>(ctrl)!=NULL)
00238     {
00239         IPv6ControlInfo *ctrl6 = (IPv6ControlInfo *)ctrl;
00240         for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it)
00241         {
00242             SockDesc *sd = *it;
00243             if (sd->onlyLocalPortIsSet || matchesSocket(sd, udpPacket, ctrl6))
00244             {
00245                 //EV << "Socket sockId=" << sd->sockId << " matches, sending up a copy.\n";
00246                 //sendUp((cPacket*)payload->dup(), udpPacket, ctrl6, sd);
00247                 // ib: speed hack
00248                 if (matches == 0) {
00249                     sendUp((cPacket*)payload, udpPacket, ctrl6, sd);
00250                 } else {
00251                     opp_error("Edit SimpleUDP.cc to support multibinding.");
00252                 }
00253                 matches++;
00254             }
00255         }
00256     }
00257     else
00258     {
00259         error("(%s)%s arrived from lower layer without control info", udpPacket->getClassName(), udpPacket->getName());
00260     }
00261 
00262     // send back ICMP error if there is no matching socket
00263     if (matches==0)
00264     {
00265         EV << "None of the sockets on port " << destPort << " matches the packet\n";
00266         processUndeliverablePacket(udpPacket, ctrl);
00267         return;
00268     }
00269 
00270     delete udpPacket;
00271     delete ctrl;
00272 }
00273 
00274 void SimpleUDP::processMsgFromApp(cPacket *appData)
00275 {
00276     cModule *node = getParentModule();
00277 //    IPvXAddress ip = IPAddressResolver().addressOf(node);
00278 //    Speedhack SK
00279 
00280     IPvXAddress srcAddr, destAddr;
00281     //cGate* destGate;
00282 
00283     UDPControlInfo *udpCtrl = check_and_cast<UDPControlInfo *>(appData->removeControlInfo());
00284 
00285     UDPPacket *udpPacket = createUDPPacket(appData->getName());
00286 
00287     // add header byte length for the skipped IP header
00288     if (udpCtrl->getDestAddr().isIPv6()) {
00289         udpPacket->setByteLength(UDP_HEADER_BYTES + IPv6_HEADER_BYTES);
00290     } else {
00291         udpPacket->setByteLength(UDP_HEADER_BYTES + IP_HEADER_BYTES);
00292     }
00293     udpPacket->encapsulate(appData);
00294 
00295     // set source and destination port
00296     udpPacket->setSourcePort(udpCtrl->getSrcPort());
00297     udpPacket->setDestinationPort(udpCtrl->getDestPort());
00298 
00299     /* main modifications for SimpleUDP start here */
00300 
00301     srcAddr = udpCtrl->getSrcAddr();
00302     destAddr = udpCtrl->getDestAddr();
00303 
00304     SimpleInfo* info = dynamic_cast<SimpleInfo*>(globalNodeList->getPeerInfo(destAddr));
00305     numSent++;
00306 
00307     if (info == NULL) {
00308         EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
00309            << "    No route to host " << destAddr
00310            << endl;
00311 
00312         delete udpPacket;
00313         delete udpCtrl;
00314         numDestUnavailableLost++;
00315         return;
00316     }
00317 
00318     SimpleNodeEntry* destEntry = info->getEntry();
00319 
00320     // calculate delay
00321     simtime_t totalDelay = 0;
00322     if (srcAddr != destAddr) {
00323         SimpleNodeEntry::SimpleDelay temp;
00324         if (faultyDelay) {
00325             SimpleInfo* thisInfo = static_cast<SimpleInfo*>(globalNodeList->getPeerInfo(srcAddr));
00326             temp = nodeEntry->calcDelay(udpPacket, *destEntry,
00327                                         !(thisInfo->getNpsLayer() == 0 ||
00328                                           info->getNpsLayer() == 0)); //TODO
00329         } else {
00330             temp = nodeEntry->calcDelay(udpPacket, *destEntry);
00331         }
00332         if (useCoordinateBasedDelay == false) {
00333             totalDelay = constantDelay;
00334         } else if (temp.second == false) {
00335             EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
00336                << "    Send queue full: packet " << udpPacket << " dropped"
00337                << endl;
00338             delete udpCtrl;
00339             delete udpPacket;
00340             numQueueLost++;
00341             return;
00342         } else {
00343             totalDelay = temp.first;
00344         }
00345     }
00346 
00347     SimpleInfo* thisInfo = dynamic_cast<SimpleInfo*>(globalNodeList->getPeerInfo(srcAddr));
00348 
00349     if (!globalNodeList->areNodeTypesConnected(thisInfo->getTypeID(), info->getTypeID())) {
00350         EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
00351                    << "    Partition " << thisInfo->getTypeID() << "->" << info->getTypeID()
00352                    << " is not connected"
00353                    << endl;
00354         delete udpCtrl;
00355         delete udpPacket;
00356         numPartitionLost++;
00357         return;
00358     }
00359 
00360     if (jitter) {
00361         // jitter
00362         //totalDelay += truncnormal(0, SIMTIME_DBL(totalDelay) * jitter);
00363 
00364         //workaround (bug in truncnormal(): sometimes returns inf)
00365         double temp = truncnormal(0, SIMTIME_DBL(totalDelay) * jitter);
00366         while (temp == INFINITY || temp != temp) { // reroll if temp is INF or NaN
00367             std::cerr << "\n******* SimpleUDP: truncnormal() -> inf !!\n"
00368                       << std::endl;
00369             temp = truncnormal(0, SIMTIME_DBL(totalDelay) * jitter);
00370         }
00371 
00372         totalDelay += temp;
00373     }
00374 
00375     BaseOverlayMessage* temp = NULL;
00376 
00377     if (ev.isGUI() && udpPacket->getEncapsulatedPacket()) {
00378         if ((temp = dynamic_cast<BaseOverlayMessage*>(udpPacket
00379                 ->getEncapsulatedPacket()))) {
00380             switch (temp->getStatType()) {
00381             case APP_DATA_STAT:
00382                 udpPacket->setKind(1);
00383                 break;
00384             case APP_LOOKUP_STAT:
00385                 udpPacket->setKind(2);
00386                 break;
00387             case MAINTENANCE_STAT:
00388             default:
00389                 udpPacket->setKind(3);
00390             }
00391         } else {
00392             udpPacket->setKind(1);
00393         }
00394     }
00395 
00396     EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
00397        << "    Packet " << udpPacket << " sent with delay = " << totalDelay
00398        << endl;
00399 
00400     //RECORD_STATS(globalStatistics->addStdDev("SimpleUDP: delay", totalDelay));
00401 
00402     /* main modifications for SimpleUDP end here */
00403 
00404     if (!udpCtrl->getDestAddr().isIPv6()) {
00405         // send to IPv4
00406         //EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
00407         //<< "    Sending app packet " << appData->getName() << " over IPv4"
00408         //<< endl;
00409         IPControlInfo *ipControlInfo = new IPControlInfo();
00410         ipControlInfo->setProtocol(IP_PROT_UDP);
00411         ipControlInfo->setSrcAddr(srcAddr.get4());
00412         ipControlInfo->setDestAddr(destAddr.get4());
00413         ipControlInfo->setInterfaceId(udpCtrl->getInterfaceId());
00414         udpPacket->setControlInfo(ipControlInfo);
00415         delete udpCtrl;
00416 
00417         // send directly to IPv4 gate of the destination node
00418         sendDirect(udpPacket, totalDelay, 0, destEntry->getUdpIPv4Gate());
00419 
00420     } else {
00421         // send to IPv6
00422         //EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
00423         //<< "    Sending app packet " << appData->getName() << " over IPv6"
00424         //<< endl;
00425         IPv6ControlInfo *ipControlInfo = new IPv6ControlInfo();
00426         ipControlInfo->setProtocol(IP_PROT_UDP);
00427         ipControlInfo->setSrcAddr(srcAddr.get6());
00428         ipControlInfo->setDestAddr(destAddr.get6());
00429         ipControlInfo->setInterfaceId(udpCtrl->getInterfaceId()); //FIXME extend IPv6 with this!!!
00430         udpPacket->setControlInfo(ipControlInfo);
00431         delete udpCtrl;
00432 
00433         // send directly to IPv4 gate of the destination node
00434         sendDirect(udpPacket, totalDelay, 0, destEntry->getUdpIPv6Gate());
00435     }
00436 
00437 }
00438 
00439 
00440 void SimpleUDP::setNodeEntry(SimpleNodeEntry* entry)
00441 {
00442     nodeEntry = entry;
00443 }