INET Framework for OMNeT++/OMNEST
PingApp Class Reference

#include <PingApp.h>

List of all members.

Protected Member Functions

virtual void initialize ()
virtual void handleMessage (cMessage *msg)
virtual void finish ()
virtual void sendPing ()
virtual void scheduleNextPing (cMessage *timer)
virtual void sendToICMP (cMessage *payload, const IPvXAddress &destAddr, const IPvXAddress &srcAddr, int hopLimit)
virtual void processPingResponse (PingPayload *msg)
virtual void countPingResponse (int bytes, long seqNo, simtime_t rtt)

Protected Attributes

IPvXAddress destAddr
IPvXAddress srcAddr
int packetSize
cPar * intervalp
int hopLimit
int count
simtime_t startTime
simtime_t stopTime
bool printPing
long sendSeqNo
long expectedReplySeqNo
cStdDev delayStat
cOutVector delayVector
cOutVector dropVector
long dropCount
long outOfOrderArrivalCount
long numPongs

Detailed Description

Generates ping requests and calculates the packet loss and round trip parameters of the replies.

See NED file for detailed description of operation.


Member Function Documentation

void PingApp::countPingResponse ( int  bytes,
long  seqNo,
simtime_t  rtt 
) [protected, virtual]

Referenced by processPingResponse().

{
    EV << "Ping reply #" << seqNo << " arrived, rtt=" << rtt << "\n";

        numPongs++;

    delayStat.collect(rtt);
    delayVector.record(rtt);

    if (seqNo == expectedReplySeqNo)
    {
        // expected ping reply arrived; expect next sequence number
        expectedReplySeqNo++;
    }
    else if (seqNo > expectedReplySeqNo)
    {
        EV << "Jump in seq numbers, assuming pings since #" << expectedReplySeqNo << " got lost\n";

        // jump in the sequence: count pings in gap as lost
        long jump = seqNo - expectedReplySeqNo;
        dropCount += jump;
        dropVector.record(dropCount);

        // expect sequence numbers to continue from here
        expectedReplySeqNo = seqNo+1;
    }
    else // seqNo < expectedReplySeqNo
    {
        // ping arrived too late: count as out of order arrival
        EV << "Arrived out of order (too late)\n";
        outOfOrderArrivalCount++;
    }
}
void PingApp::finish ( ) [protected, virtual]
{
    if (sendSeqNo==0)
    {
        if (printPing)
                EV << getFullPath() << ": No pings sent, skipping recording statistics and printing results.\n";
        recordScalar("Pings sent", sendSeqNo);
        return;
    }

    // record statistics
    recordScalar("Pings sent", sendSeqNo);
    recordScalar("Pings dropped", dropCount);
    recordScalar("Out-of-order ping arrivals", outOfOrderArrivalCount);
    recordScalar("Pings outstanding at end", sendSeqNo-expectedReplySeqNo);

    recordScalar("Ping drop rate (%)", 100 * dropCount / (double)sendSeqNo);
    recordScalar("Ping out-of-order rate (%)", 100 * outOfOrderArrivalCount / (double)sendSeqNo);

    delayStat.recordAs("Ping roundtrip delays");

    // print it to stdout as well
    if (printPing)
    {
        cout << "--------------------------------------------------------" << endl;
        cout << "\t" << getFullPath() << endl;
        cout << "--------------------------------------------------------" << endl;

        cout << "sent: " << sendSeqNo
                        << "   drop rate (%): " << (100 * dropCount / (double)sendSeqNo) << endl;
        cout << "round-trip min/avg/max (ms): "
                        << (delayStat.getMin()*1000.0) << "/"
                        << (delayStat.getMean()*1000.0) << "/"
                        << (delayStat.getMax()*1000.0) << endl;
        cout << "stddev (ms): "<< (delayStat.getStddev()*1000.0)
                         << "   variance:" << delayStat.getVariance() << endl;
        cout <<"--------------------------------------------------------" << endl;
    }
}
void PingApp::handleMessage ( cMessage *  msg) [protected, virtual]
{
    if (msg->isSelfMessage())
    {
        // on first call we need to initialize
        if (destAddr.isUnspecified())
        {
            destAddr = IPAddressResolver().resolve(par("destAddr"));
            ASSERT(!destAddr.isUnspecified());
            srcAddr = IPAddressResolver().resolve(par("srcAddr"));
            EV << "Starting up: dest=" << destAddr << "  src=" << srcAddr << "\n";
        }

        // send a ping
        sendPing();

        // then schedule next one if needed
        scheduleNextPing(msg);
    }
    else
    {
        // process ping response
        processPingResponse(check_and_cast<PingPayload *>(msg));
    }
}
void PingApp::initialize ( ) [protected, virtual]
{
    // read params
    // (defer reading srcAddr/destAddr to when ping starts, maybe
    // addresses will be assigned later by some protocol)
    packetSize = par("packetSize");
    intervalp = & par("interval");
    hopLimit = par("hopLimit");
    count = par("count");
    startTime = par("startTime");
    stopTime = par("stopTime");
    printPing = (bool)par("printPing");

    // state
    sendSeqNo = expectedReplySeqNo = 0;
    WATCH(sendSeqNo);
    WATCH(expectedReplySeqNo);

    // statistics
    delayStat.setName("pingRTT");
    delayVector.setName("pingRTT");
    dropVector.setName("pingDrop");

    dropCount = outOfOrderArrivalCount = numPongs = 0;
    WATCH(dropCount);
    WATCH(outOfOrderArrivalCount);
    WATCH(numPongs);

    // schedule first ping (use empty destAddr or stopTime<=startTime to disable)
    if (par("destAddr").stringValue()[0] && (stopTime==0 || stopTime>=startTime))
    {
        cMessage *msg = new cMessage("sendPing");
        scheduleAt(startTime, msg);
    }
}
void PingApp::processPingResponse ( PingPayload *  msg) [protected, virtual]

Referenced by handleMessage().

{
    // get src, hopCount etc from packet, and print them
    IPvXAddress src, dest;
    int msgHopCount = -1;
    if (dynamic_cast<IPControlInfo *>(msg->getControlInfo())!=NULL)
    {
        IPControlInfo *ctrl = (IPControlInfo *)msg->getControlInfo();
        src = ctrl->getSrcAddr();
        dest = ctrl->getDestAddr();
        msgHopCount = ctrl->getTimeToLive();
    }
    else if (dynamic_cast<IPv6ControlInfo *>(msg->getControlInfo())!=NULL)
    {
        IPv6ControlInfo *ctrl = (IPv6ControlInfo *)msg->getControlInfo();
        src = ctrl->getSrcAddr();
        dest = ctrl->getDestAddr();
        msgHopCount = ctrl->getHopLimit();
    }

    simtime_t rtt = simTime() - msg->getCreationTime();

    if (printPing)
    {
        cout << getFullPath() << ": reply of " << std::dec << msg->getByteLength()
             << " bytes from " << src
             << " icmp_seq=" << msg->getSeqNo() << " ttl=" << msgHopCount
             << " time=" << (rtt * 1000) << " msec"
             << " (" << msg->getName() << ")" << endl;
    }

    // update statistics
    countPingResponse(msg->getByteLength(), msg->getSeqNo(), rtt);
    delete msg;
}
void PingApp::scheduleNextPing ( cMessage *  timer) [protected, virtual]

Referenced by handleMessage().

{
    simtime_t nextPing = simTime() + intervalp->doubleValue();
    sendSeqNo++;
    if ((count==0 || sendSeqNo<count) && (stopTime==0 || nextPing<stopTime))
        scheduleAt(nextPing, timer);
    else
        delete timer;
}
void PingApp::sendPing ( ) [protected, virtual]

Referenced by handleMessage().

{
    EV << "Sending ping #" << sendSeqNo << "\n";

    char name[32];
    sprintf(name,"ping%ld", sendSeqNo);

    PingPayload *msg = new PingPayload(name);
    msg->setOriginatorId(getId());
    msg->setSeqNo(sendSeqNo);
    msg->setByteLength(packetSize);

    sendToICMP(msg, destAddr, srcAddr, hopLimit);
}
void PingApp::sendToICMP ( cMessage *  payload,
const IPvXAddress destAddr,
const IPvXAddress srcAddr,
int  hopLimit 
) [protected, virtual]

Referenced by sendPing().

{
    if (!destAddr.isIPv6())
    {
        // send to IPv4
        IPControlInfo *ctrl = new IPControlInfo();
        ctrl->setSrcAddr(srcAddr.get4());
        ctrl->setDestAddr(destAddr.get4());
        ctrl->setTimeToLive(hopLimit);
        msg->setControlInfo(ctrl);
        send(msg, "pingOut");
    }
    else
    {
        // send to IPv6
        IPv6ControlInfo *ctrl = new IPv6ControlInfo();
        ctrl->setSrcAddr(srcAddr.get6());
        ctrl->setDestAddr(destAddr.get6());
        ctrl->setHopLimit(hopLimit);
        msg->setControlInfo(ctrl);
        send(msg, "pingv6Out");
    }
}

Member Data Documentation

int PingApp::count [protected]

Referenced by initialize(), and scheduleNextPing().

cStdDev PingApp::delayStat [protected]
cOutVector PingApp::delayVector [protected]

Referenced by countPingResponse(), and initialize().

Referenced by handleMessage(), and sendPing().

long PingApp::dropCount [protected]
cOutVector PingApp::dropVector [protected]

Referenced by countPingResponse(), and initialize().

int PingApp::hopLimit [protected]

Referenced by initialize(), and sendPing().

cPar* PingApp::intervalp [protected]

Referenced by initialize(), and scheduleNextPing().

long PingApp::numPongs [protected]

Referenced by countPingResponse(), and initialize().

int PingApp::packetSize [protected]

Referenced by initialize(), and sendPing().

bool PingApp::printPing [protected]
long PingApp::sendSeqNo [protected]

Referenced by handleMessage(), and sendPing().

simtime_t PingApp::startTime [protected]

Referenced by initialize().

simtime_t PingApp::stopTime [protected]

Referenced by initialize(), and scheduleNextPing().


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