Public Types | Public Member Functions | Static Public Attributes | Protected Member Functions | Protected Attributes

SimpleUDP Class Reference

Implements the UDP protocol: encapsulates/decapsulates user data into/from UDP. More...

#include <SimpleUDP.h>

List of all members.

Public Types

enum  delayFaultTypeNum { delayFaultUndefined, delayFaultLiveAll, delayFaultLivePlanetlab, delayFaultSimulation }

Public Member Functions

void setNodeEntry (SimpleNodeEntry *entry)
 set or change the nodeEntry of this module
 SimpleUDP ()
virtual ~SimpleUDP ()
 destructor

Static Public Attributes

static std::string delayFaultTypeString
static std::map< std::string,
delayFaultTypeNum
delayFaultTypeMap

Protected Member Functions

void updateDisplayString ()
 utility: show current statistics above the icon
virtual void processMsgFromApp (cPacket *appData)
 process packets from application
virtual void processUDPPacket (UDPPacket *udpPacket)
virtual void processUndeliverablePacket (UDPPacket *udpPacket, cPolymorphic *ctrl)
virtual void initialize (int stage)
 initialise the SimpleUDP module
virtual int numInitStages () const
 returns the number of init stages
void finish ()

Protected Attributes

int numQueueLost
 number of lost packets due to queue full
int numPartitionLost
 number of lost packets due to network partitions
int numDestUnavailableLost
 number of lost packets due to unavailable destination
simtime_t delay
 simulated delay between sending and receiving udp module
simtime_t constantDelay
 constant delay between two peers
bool useCoordinateBasedDelay
 delay should be calculated from euklidean distance between two peers
double jitter
 amount of jitter in % of total delay
bool faultyDelay
GlobalNodeListglobalNodeList
 violate the triangle inequality?
GlobalStatisticsglobalStatistics
 pointer to GlobalStatistics
SimpleNodeEntrynodeEntry
 nodeEntry of the overlay node this module belongs to

Detailed Description

Implements the UDP protocol: encapsulates/decapsulates user data into/from UDP.

More info in the NED file.

Definition at line 59 of file SimpleUDP.h.


Member Enumeration Documentation

Enumerator:
delayFaultUndefined 
delayFaultLiveAll 
delayFaultLivePlanetlab 
delayFaultSimulation 

Definition at line 65 of file SimpleUDP.h.

                           {
        delayFaultUndefined,
        delayFaultLiveAll,
        delayFaultLivePlanetlab,
        delayFaultSimulation
    };


Constructor & Destructor Documentation

SimpleUDP::SimpleUDP (  ) 

Definition at line 88 of file SimpleUDP.cc.

{
    globalStatistics = NULL;
}

SimpleUDP::~SimpleUDP (  )  [virtual]

destructor

Definition at line 93 of file SimpleUDP.cc.

{

}


Member Function Documentation

void SimpleUDP::finish (  )  [protected]

Definition at line 149 of file SimpleUDP.cc.

{
    globalStatistics->addStdDev("SimpleUDP: Packets sent",
                                numSent);
    globalStatistics->addStdDev("SimpleUDP: Packets dropped with bad checksum",
                                numDroppedBadChecksum);
    globalStatistics->addStdDev("SimpleUDP: Packets dropped due to queue overflows",
                                numQueueLost);
    globalStatistics->addStdDev("SimpleUDP: Packets dropped due to network partitions",
                                numPartitionLost);
    globalStatistics->addStdDev("SimpleUDP: Packets dropped due to unavailable destination",
                                numDestUnavailableLost);
}

void SimpleUDP::initialize ( int  stage  )  [protected, virtual]

initialise the SimpleUDP module

Parameters:
stage stage of initialisation phase

Definition at line 98 of file SimpleUDP.cc.

{
    if(stage == MIN_STAGE_UNDERLAY) {
        WATCH_PTRMAP(socketsByIdMap);
        WATCH_MAP(socketsByPortMap);

        lastEphemeralPort = EPHEMERAL_PORTRANGE_START;
        icmp = NULL;
        icmpv6 = NULL;

        numSent = 0;
        numPassedUp = 0;
        numDroppedWrongPort = 0;
        numDroppedBadChecksum = 0;
        numQueueLost = 0;
        numPartitionLost = 0;
        numDestUnavailableLost = 0;
        WATCH(numSent);
        WATCH(numPassedUp);
        WATCH(numDroppedWrongPort);
        WATCH(numDroppedBadChecksum);
        WATCH(numQueueLost);
        WATCH(numPartitionLost);
        WATCH(numDestUnavailableLost);

        globalNodeList = GlobalNodeListAccess().get();
        globalStatistics = GlobalStatisticsAccess().get();
        constantDelay = par("constantDelay");
        useCoordinateBasedDelay = par("useCoordinateBasedDelay");

        delayFaultTypeString = par("delayFaultType").stdstringValue();
        delayFaultTypeMap["live_all"] = delayFaultLiveAll;
        delayFaultTypeMap["live_planetlab"] = delayFaultLivePlanetlab;
        delayFaultTypeMap["simulation"] = delayFaultSimulation;

        switch (delayFaultTypeMap[delayFaultTypeString]) {
        case SimpleUDP::delayFaultLiveAll:
        case SimpleUDP::delayFaultLivePlanetlab:
        case SimpleUDP::delayFaultSimulation:
            faultyDelay = true;
            break;
        default:
            faultyDelay = false;
        }

        jitter = par("jitter");
        nodeEntry = NULL;
        WATCH_PTR(nodeEntry);
    }
}

virtual int SimpleUDP::numInitStages ( void   )  const [inline, protected, virtual]

returns the number of init stages

Returns:
the number of init stages

Definition at line 134 of file SimpleUDP.h.

    {
        return MAX_STAGE_UNDERLAY + 1;
    }

void SimpleUDP::processMsgFromApp ( cPacket *  appData  )  [protected, virtual]

process packets from application

Parameters:
appData the data that has to be sent

Definition at line 274 of file SimpleUDP.cc.

{
    cModule *node = getParentModule();
//    IPvXAddress ip = IPAddressResolver().addressOf(node);
//    Speedhack SK

    IPvXAddress srcAddr, destAddr;
    //cGate* destGate;

    UDPControlInfo *udpCtrl = check_and_cast<UDPControlInfo *>(appData->removeControlInfo());

    UDPPacket *udpPacket = createUDPPacket(appData->getName());

    // add header byte length for the skipped IP header
    if (udpCtrl->getDestAddr().isIPv6()) {
        udpPacket->setByteLength(UDP_HEADER_BYTES + IPv6_HEADER_BYTES);
    } else {
        udpPacket->setByteLength(UDP_HEADER_BYTES + IP_HEADER_BYTES);
    }
    udpPacket->encapsulate(appData);

    // set source and destination port
    udpPacket->setSourcePort(udpCtrl->getSrcPort());
    udpPacket->setDestinationPort(udpCtrl->getDestPort());

    /* main modifications for SimpleUDP start here */

    srcAddr = udpCtrl->getSrcAddr();
    destAddr = udpCtrl->getDestAddr();

    SimpleInfo* info = dynamic_cast<SimpleInfo*>(globalNodeList->getPeerInfo(destAddr));
    numSent++;

    if (info == NULL) {
        EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
           << "    No route to host " << destAddr
           << endl;

        delete udpPacket;
        delete udpCtrl;
        numDestUnavailableLost++;
        return;
    }

    SimpleNodeEntry* destEntry = info->getEntry();

    // calculate delay
    simtime_t totalDelay = 0;
    if (srcAddr != destAddr) {
        SimpleNodeEntry::SimpleDelay temp;
        if (faultyDelay) {
            SimpleInfo* thisInfo = static_cast<SimpleInfo*>(globalNodeList->getPeerInfo(srcAddr));
            temp = nodeEntry->calcDelay(udpPacket, *destEntry,
                                        !(thisInfo->getNpsLayer() == 0 ||
                                          info->getNpsLayer() == 0)); //TODO
        } else {
            temp = nodeEntry->calcDelay(udpPacket, *destEntry);
        }
        if (useCoordinateBasedDelay == false) {
            totalDelay = constantDelay;
        } else if (temp.second == false) {
            EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
               << "    Send queue full: packet " << udpPacket << " dropped"
               << endl;
            delete udpCtrl;
            delete udpPacket;
            numQueueLost++;
            return;
        } else {
            totalDelay = temp.first;
        }
    }

    SimpleInfo* thisInfo = dynamic_cast<SimpleInfo*>(globalNodeList->getPeerInfo(srcAddr));

    if (!globalNodeList->areNodeTypesConnected(thisInfo->getTypeID(), info->getTypeID())) {
        EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
                   << "    Partition " << thisInfo->getTypeID() << "->" << info->getTypeID()
                   << " is not connected"
                   << endl;
        delete udpCtrl;
        delete udpPacket;
        numPartitionLost++;
        return;
    }

    if (jitter) {
        // jitter
        //totalDelay += truncnormal(0, SIMTIME_DBL(totalDelay) * jitter);

        //workaround (bug in truncnormal(): sometimes returns inf)
        double temp = truncnormal(0, SIMTIME_DBL(totalDelay) * jitter);
        while (temp == INFINITY || temp != temp) { // reroll if temp is INF or NaN
            std::cerr << "\n******* SimpleUDP: truncnormal() -> inf !!\n"
                      << std::endl;
            temp = truncnormal(0, SIMTIME_DBL(totalDelay) * jitter);
        }

        totalDelay += temp;
    }

    BaseOverlayMessage* temp = NULL;

    if (ev.isGUI() && udpPacket->getEncapsulatedPacket()) {
        if ((temp = dynamic_cast<BaseOverlayMessage*>(udpPacket
                ->getEncapsulatedPacket()))) {
            switch (temp->getStatType()) {
            case APP_DATA_STAT:
                udpPacket->setKind(1);
                break;
            case APP_LOOKUP_STAT:
                udpPacket->setKind(2);
                break;
            case MAINTENANCE_STAT:
            default:
                udpPacket->setKind(3);
            }
        } else {
            udpPacket->setKind(1);
        }
    }

    EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
       << "    Packet " << udpPacket << " sent with delay = " << totalDelay
       << endl;

    //RECORD_STATS(globalStatistics->addStdDev("SimpleUDP: delay", totalDelay));

    /* main modifications for SimpleUDP end here */

    if (!udpCtrl->getDestAddr().isIPv6()) {
        // send to IPv4
        //EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
        //<< "    Sending app packet " << appData->getName() << " over IPv4"
        //<< endl;
        IPControlInfo *ipControlInfo = new IPControlInfo();
        ipControlInfo->setProtocol(IP_PROT_UDP);
        ipControlInfo->setSrcAddr(srcAddr.get4());
        ipControlInfo->setDestAddr(destAddr.get4());
        ipControlInfo->setInterfaceId(udpCtrl->getInterfaceId());
        udpPacket->setControlInfo(ipControlInfo);
        delete udpCtrl;

        // send directly to IPv4 gate of the destination node
        sendDirect(udpPacket, totalDelay, 0, destEntry->getUdpIPv4Gate());

    } else {
        // send to IPv6
        //EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n"
        //<< "    Sending app packet " << appData->getName() << " over IPv6"
        //<< endl;
        IPv6ControlInfo *ipControlInfo = new IPv6ControlInfo();
        ipControlInfo->setProtocol(IP_PROT_UDP);
        ipControlInfo->setSrcAddr(srcAddr.get6());
        ipControlInfo->setDestAddr(destAddr.get6());
        ipControlInfo->setInterfaceId(udpCtrl->getInterfaceId()); //FIXME extend IPv6 with this!!!
        udpPacket->setControlInfo(ipControlInfo);
        delete udpCtrl;

        // send directly to IPv4 gate of the destination node
        sendDirect(udpPacket, totalDelay, 0, destEntry->getUdpIPv6Gate());
    }

}

void SimpleUDP::processUDPPacket ( UDPPacket *  udpPacket  )  [protected, virtual]

Definition at line 188 of file SimpleUDP.cc.

{
    // simulate checksum: discard packet if it has bit error
    EV << "Packet " << udpPacket->getName() << " received from network, dest port " << udpPacket->getDestinationPort() << "\n";
    if (udpPacket->hasBitError())
    {
        EV << "Packet has bit error, discarding\n";
        delete udpPacket;
        numDroppedBadChecksum++;
        return;
    }

    int destPort = udpPacket->getDestinationPort();
    cPolymorphic *ctrl = udpPacket->removeControlInfo();

    // send back ICMP error if no socket is bound to that port
    SocketsByPortMap::iterator it = socketsByPortMap.find(destPort);
    if (it==socketsByPortMap.end())
    {
        EV << "No socket registered on port " << destPort << "\n";
        processUndeliverablePacket(udpPacket, ctrl);
        return;
    }
    SockDescList& list = it->second;

    int matches = 0;

    // deliver a copy of the packet to each matching socket
    cPacket *payload = udpPacket->decapsulate();
    if (dynamic_cast<IPControlInfo *>(ctrl)!=NULL)
    {
        IPControlInfo *ctrl4 = (IPControlInfo *)ctrl;
        for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it)
        {
            SockDesc *sd = *it;
            if (sd->onlyLocalPortIsSet || matchesSocket(sd, udpPacket, ctrl4))
            {
                //EV << "Socket sockId=" << sd->sockId << " matches, sending up a copy.\n";
                //sendUp((cPacket*)payload->dup(), udpPacket, ctrl4, sd);
                // ib: speed hack
                if (matches == 0) {
                    sendUp((cPacket*)payload, udpPacket, ctrl4, sd);
                } else {
                    opp_error("Edit SimpleUDP.cc to support multibinding.");
                }
                matches++;
            }
        }
    }
    else if (dynamic_cast<IPv6ControlInfo *>(ctrl)!=NULL)
    {
        IPv6ControlInfo *ctrl6 = (IPv6ControlInfo *)ctrl;
        for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it)
        {
            SockDesc *sd = *it;
            if (sd->onlyLocalPortIsSet || matchesSocket(sd, udpPacket, ctrl6))
            {
                //EV << "Socket sockId=" << sd->sockId << " matches, sending up a copy.\n";
                //sendUp((cPacket*)payload->dup(), udpPacket, ctrl6, sd);
                // ib: speed hack
                if (matches == 0) {
                    sendUp((cPacket*)payload, udpPacket, ctrl6, sd);
                } else {
                    opp_error("Edit SimpleUDP.cc to support multibinding.");
                }
                matches++;
            }
        }
    }
    else
    {
        error("(%s)%s arrived from lower layer without control info", udpPacket->getClassName(), udpPacket->getName());
    }

    // send back ICMP error if there is no matching socket
    if (matches==0)
    {
        EV << "None of the sockets on port " << destPort << " matches the packet\n";
        processUndeliverablePacket(udpPacket, ctrl);
        return;
    }

    delete udpPacket;
    delete ctrl;
}

void SimpleUDP::processUndeliverablePacket ( UDPPacket *  udpPacket,
cPolymorphic *  ctrl 
) [protected, virtual]

Definition at line 178 of file SimpleUDP.cc.

Referenced by processUDPPacket().

{
    numDroppedWrongPort++;
    EV << "[SimpleUDP::processUndeliverablePacket()]\n"
       << "    Dropped packet bound to unreserved port, ignoring ICMP error"
       << endl;

    delete udpPacket;
}

void SimpleUDP::setNodeEntry ( SimpleNodeEntry entry  ) 

set or change the nodeEntry of this module

Parameters:
entry the new nodeEntry

Definition at line 440 of file SimpleUDP.cc.

Referenced by SimpleUnderlayConfigurator::createNode(), and SimpleUnderlayConfigurator::migrateNode().

{
    nodeEntry = entry;
}

void SimpleUDP::updateDisplayString (  )  [protected]

utility: show current statistics above the icon

Definition at line 163 of file SimpleUDP.cc.

{
    char buf[80];
    sprintf(buf, "passed up: %d pks\nsent: %d pks", numPassedUp, numSent);
    if (numDroppedWrongPort>0) {
        sprintf(buf+strlen(buf), "\ndropped (no app): %d pks", numDroppedWrongPort);
        getDisplayString().setTagArg("i",1,"red");
    }
    if (numQueueLost>0) {
        sprintf(buf+strlen(buf), "\nlost (queue overflow): %d pks", numQueueLost);
        getDisplayString().setTagArg("i",1,"red");
    }
    getDisplayString().setTagArg("t",0,buf);
}


Member Data Documentation

simtime_t SimpleUDP::constantDelay [protected]

constant delay between two peers

Definition at line 81 of file SimpleUDP.h.

Referenced by initialize(), and processMsgFromApp().

simtime_t SimpleUDP::delay [protected]

simulated delay between sending and receiving udp module

Definition at line 79 of file SimpleUDP.h.

Definition at line 71 of file SimpleUDP.h.

Referenced by SimpleNodeEntry::getFaultyDelay(), and initialize().

std::string SimpleUDP::delayFaultTypeString [static]

Definition at line 64 of file SimpleUDP.h.

Referenced by SimpleNodeEntry::getFaultyDelay(), and initialize().

bool SimpleUDP::faultyDelay [protected]

Definition at line 84 of file SimpleUDP.h.

Referenced by initialize(), and processMsgFromApp().

violate the triangle inequality?

pointer to GlobalNodeList

Definition at line 85 of file SimpleUDP.h.

Referenced by initialize(), and processMsgFromApp().

pointer to GlobalStatistics

Definition at line 86 of file SimpleUDP.h.

Referenced by finish(), initialize(), and SimpleUDP().

double SimpleUDP::jitter [protected]

amount of jitter in % of total delay

Definition at line 83 of file SimpleUDP.h.

Referenced by initialize(), and processMsgFromApp().

nodeEntry of the overlay node this module belongs to

Definition at line 87 of file SimpleUDP.h.

Referenced by initialize(), processMsgFromApp(), and setNodeEntry().

number of lost packets due to unavailable destination

Definition at line 78 of file SimpleUDP.h.

Referenced by finish(), initialize(), and processMsgFromApp().

int SimpleUDP::numPartitionLost [protected]

number of lost packets due to network partitions

Definition at line 77 of file SimpleUDP.h.

Referenced by finish(), initialize(), and processMsgFromApp().

int SimpleUDP::numQueueLost [protected]

number of lost packets due to queue full

Definition at line 76 of file SimpleUDP.h.

Referenced by finish(), initialize(), processMsgFromApp(), and updateDisplayString().

delay should be calculated from euklidean distance between two peers

Definition at line 82 of file SimpleUDP.h.

Referenced by initialize(), and processMsgFromApp().


The documentation for this class was generated from the following files: