#include <PingApp.h>
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 |
|
||||||||||||||||
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
||||||||||||||||||||
|
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 }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1.4.1