PingApp Class Reference

#include <PingApp.h>

List of all members.


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.


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


Member Function Documentation

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

00181 {
00182     EV << "Ping reply #" << seqNo << " arrived, rtt=" << rtt << "\n";
00183 
00184     delayStat.collect(rtt);
00185     delayVector.record(rtt);
00186 
00187     if (seqNo == expectedReplySeqNo)
00188     {
00189         // expected ping reply arrived; expect next sequence number
00190         expectedReplySeqNo++;
00191     }
00192     else if (seqNo > expectedReplySeqNo)
00193     {
00194         EV << "Jump in seq numbers, assuming pings since #" << expectedReplySeqNo << " got lost\n";
00195 
00196         // jump in the sequence: count pings in gap as lost
00197         long jump = seqNo - expectedReplySeqNo;
00198         dropCount += jump;
00199         dropVector.record(dropCount);
00200 
00201         // expect sequence numbers to continue from here
00202         expectedReplySeqNo = seqNo+1;
00203     }
00204     else // seqNo < expectedReplySeqNo
00205     {
00206         // ping arrived too late: count as out of order arrival
00207         EV << "Arrived out of order (too late)\n";
00208         outOfOrderArrivalCount++;
00209     }
00210 }

void PingApp::finish (  )  [protected, virtual]

00213 {
00214     if (sendSeqNo==0)
00215     {
00216         EV << fullPath() << ": No pings sent, skipping recording statistics and printing results.\n";
00217         recordScalar("Pings sent", sendSeqNo);
00218         return;
00219     }
00220 
00221     // record statistics
00222     recordScalar("Pings sent", sendSeqNo);
00223     recordScalar("Pings dropped", dropCount);
00224     recordScalar("Out-of-order ping arrivals", outOfOrderArrivalCount);
00225     recordScalar("Pings outstanding at end", sendSeqNo-expectedReplySeqNo);
00226 
00227     recordScalar("Ping drop rate (%)", 100 * dropCount / (double)sendSeqNo);
00228     recordScalar("Ping out-of-order rate (%)", 100 * outOfOrderArrivalCount / (double)sendSeqNo);
00229 
00230     delayStat.recordScalar("Ping roundtrip delays");
00231 
00232     // print it to stdout as well
00233     cout << "--------------------------------------------------------" << endl;
00234     cout << "\t" << fullPath() << endl;
00235     cout << "--------------------------------------------------------" << endl;
00236 
00237     cout << "sent: " << sendSeqNo
00238          << "   drop rate (%): " << (100 * dropCount / (double)sendSeqNo) << endl;
00239     cout << "round-trip min/avg/max (ms): "
00240          << (delayStat.min()*1000.0) << "/"
00241          << (delayStat.mean()*1000.0) << "/"
00242          << (delayStat.max()*1000.0) << endl;
00243     cout << "stddev (ms): "<< (delayStat.stddev()*1000.0)
00244          << "   variance:" << delayStat.variance() << endl;
00245     cout <<"--------------------------------------------------------" << endl;
00246 }

void PingApp::handleMessage ( cMessage *  msg  )  [protected, virtual]

00070 {
00071     if (msg->isSelfMessage())
00072     {
00073         // on first call we need to initialize
00074         if (destAddr.isUnspecified())
00075         {
00076             destAddr = IPAddressResolver().resolve(par("destAddr"));
00077             ASSERT(!destAddr.isUnspecified());
00078             srcAddr = IPAddressResolver().resolve(par("srcAddr"));
00079             EV << "Starting up: dest=" << destAddr << "  src=" << srcAddr << "\n";
00080         }
00081 
00082         // send a ping
00083         sendPing();
00084 
00085         // then schedule next one if needed
00086         scheduleNextPing(msg);
00087     }
00088     else
00089     {
00090         // process ping response
00091         processPingResponse(check_and_cast<PingPayload *>(msg));
00092     }
00093 }

void PingApp::initialize (  )  [protected, virtual]

00035 {
00036     // read params
00037     // (defer reading srcAddr/destAddr to when ping starts, maybe
00038     // addresses will be assigned later by some protocol)
00039     packetSize = par("packetSize");
00040     intervalp = & par("interval");
00041     hopLimit = par("hopLimit");
00042     count = par("count");
00043     startTime = par("startTime");
00044     stopTime = par("stopTime");
00045     printPing = (bool)par("printPing");
00046 
00047     // state
00048     sendSeqNo = expectedReplySeqNo = 0;
00049     WATCH(sendSeqNo);
00050     WATCH(expectedReplySeqNo);
00051 
00052     // statistics
00053     delayStat.setName("pingRTT");
00054     delayVector.setName("pingRTT");
00055     dropVector.setName("pingDrop");
00056 
00057     dropCount = outOfOrderArrivalCount = 0;
00058     WATCH(dropCount);
00059     WATCH(outOfOrderArrivalCount);
00060 
00061     // schedule first ping (use empty destAddr or stopTime<=startTime to disable)
00062     if (par("destAddr").stringValue()[0] && (stopTime==0 || stopTime>=startTime))
00063     {
00064         cMessage *msg = new cMessage("sendPing");
00065         scheduleAt(startTime, msg);
00066     }
00067 }

void PingApp::processPingResponse ( PingPayload msg  )  [protected, virtual]

00145 {
00146     // get src, hopCount etc from packet, and print them
00147     IPvXAddress src, dest;
00148     int msgHopCount = -1;
00149     if (dynamic_cast<IPControlInfo *>(msg->controlInfo())!=NULL)
00150     {
00151         IPControlInfo *ctrl = (IPControlInfo *)msg->controlInfo();
00152         src = ctrl->srcAddr();
00153         dest = ctrl->destAddr();
00154         msgHopCount = ctrl->timeToLive();
00155     }
00156     else if (dynamic_cast<IPv6ControlInfo *>(msg->controlInfo())!=NULL)
00157     {
00158         IPv6ControlInfo *ctrl = (IPv6ControlInfo *)msg->controlInfo();
00159         src = ctrl->srcAddr();
00160         dest = ctrl->destAddr();
00161         msgHopCount = ctrl->hopLimit();
00162     }
00163 
00164     simtime_t rtt = simTime() - msg->creationTime();
00165 
00166     if (printPing)
00167     {
00168         cout << fullPath() << ": reply of " << std::dec << msg->byteLength()
00169              << " bytes from " << src
00170              << " icmp_seq=" << msg->seqNo() << " ttl=" << msgHopCount
00171              << " time=" << (rtt * 1000) << " msec"
00172              << " (" << msg->name() << ")" << endl;
00173     }
00174 
00175     // update statistics
00176     countPingResponse(msg->byteLength(), msg->seqNo(), rtt);
00177     delete msg;
00178 }

void PingApp::scheduleNextPing ( cMessage *  timer  )  [protected, virtual]

00111 {
00112     simtime_t nextPing = simTime() + intervalp->doubleValue();
00113     sendSeqNo++;
00114     if ((count==0 || sendSeqNo<count) && (stopTime==0 || nextPing<stopTime))
00115         scheduleAt(nextPing, timer);
00116     else
00117         delete timer;
00118 }

void PingApp::sendPing (  )  [protected, virtual]

00096 {
00097     EV << "Sending ping #" << sendSeqNo << "\n";
00098 
00099     char name[32];
00100     sprintf(name,"ping%ld", sendSeqNo);
00101 
00102     PingPayload *msg = new PingPayload(name);
00103     msg->setOriginatorId(id());
00104     msg->setSeqNo(sendSeqNo);
00105     msg->setByteLength(packetSize);
00106 
00107     sendToICMP(msg, destAddr, srcAddr, hopLimit);
00108 }

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

00121 {
00122     if (!destAddr.isIPv6())
00123     {
00124         // send to IPv4
00125         IPControlInfo *ctrl = new IPControlInfo();
00126         ctrl->setSrcAddr(srcAddr.get4());
00127         ctrl->setDestAddr(destAddr.get4());
00128         ctrl->setTimeToLive(hopLimit);
00129         msg->setControlInfo(ctrl);
00130         send(msg, "pingOut");
00131     }
00132     else
00133     {
00134         // send to IPv6
00135         IPv6ControlInfo *ctrl = new IPv6ControlInfo();
00136         ctrl->setSrcAddr(srcAddr.get6());
00137         ctrl->setDestAddr(destAddr.get6());
00138         ctrl->setHopLimit(hopLimit);
00139         msg->setControlInfo(ctrl);
00140         send(msg, "pingv6Out");
00141     }
00142 }


Member Data Documentation

int PingApp::count [protected]

cStdDev PingApp::delayStat [protected]

cOutVector PingApp::delayVector [protected]

IPvXAddress PingApp::destAddr [protected]

long PingApp::dropCount [protected]

cOutVector PingApp::dropVector [protected]

long PingApp::expectedReplySeqNo [protected]

int PingApp::hopLimit [protected]

cPar* PingApp::intervalp [protected]

long PingApp::outOfOrderArrivalCount [protected]

int PingApp::packetSize [protected]

bool PingApp::printPing [protected]

long PingApp::sendSeqNo [protected]

IPvXAddress PingApp::srcAddr [protected]

simtime_t PingApp::startTime [protected]

simtime_t PingApp::stopTime [protected]


The documentation for this class was generated from the following files:
Generated on Wed Apr 4 13:20:22 2007 for INET Framework for OMNeT++/OMNEST by  doxygen 1.4.7