Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <limits.h>
00020 #include <stdlib.h>
00021 #include <iostream>
00022
00023 #include "IPAddressResolver.h"
00024 #include "PingApp.h"
00025 #include "PingPayload_m.h"
00026 #include "IPControlInfo.h"
00027 #include "IPv6ControlInfo.h"
00028
00029 using std::cout;
00030
00031 Define_Module(PingApp);
00032
00033 void PingApp::initialize()
00034 {
00035
00036
00037
00038 packetSize = par("packetSize");
00039 intervalp = & par("interval");
00040 hopLimit = par("hopLimit");
00041 count = par("count");
00042 startTime = par("startTime");
00043 stopTime = par("stopTime");
00044 printPing = (bool)par("printPing");
00045
00046
00047 sendSeqNo = expectedReplySeqNo = 0;
00048 WATCH(sendSeqNo);
00049 WATCH(expectedReplySeqNo);
00050
00051
00052 delayStat.setName("pingRTT");
00053 delayVector.setName("pingRTT");
00054 dropVector.setName("pingDrop");
00055
00056 dropCount = outOfOrderArrivalCount = 0;
00057 WATCH(dropCount);
00058 WATCH(outOfOrderArrivalCount);
00059
00060
00061 if (par("destAddr").stringValue()[0] && (stopTime==0 || stopTime>=startTime))
00062 {
00063 cMessage *msg = new cMessage("sendPing");
00064 scheduleAt(startTime, msg);
00065 }
00066 }
00067
00068 void PingApp::handleMessage(cMessage *msg)
00069 {
00070 if (msg->isSelfMessage())
00071 {
00072
00073 if (destAddr.isUnspecified())
00074 {
00075 destAddr = IPAddressResolver().resolve(par("destAddr"));
00076 ASSERT(!destAddr.isUnspecified());
00077 srcAddr = IPAddressResolver().resolve(par("srcAddr"));
00078 EV << "Starting up: dest=" << destAddr << " src=" << srcAddr << "\n";
00079 }
00080
00081
00082 sendPing();
00083
00084
00085 scheduleNextPing(msg);
00086 }
00087 else
00088 {
00089
00090 processPingResponse(check_and_cast<PingPayload *>(msg));
00091 }
00092 }
00093
00094 void PingApp::sendPing()
00095 {
00096 EV << "Sending ping #" << sendSeqNo << "\n";
00097
00098 char name[32];
00099 sprintf(name,"ping%ld", sendSeqNo);
00100
00101 PingPayload *msg = new PingPayload(name);
00102 msg->setOriginatorId(getId());
00103 msg->setSeqNo(sendSeqNo);
00104 msg->setByteLength(packetSize);
00105
00106 sendToICMP(msg, destAddr, srcAddr, hopLimit);
00107 }
00108
00109 void PingApp::scheduleNextPing(cMessage *timer)
00110 {
00111 simtime_t nextPing = simTime() + intervalp->doubleValue();
00112 sendSeqNo++;
00113 if ((count==0 || sendSeqNo<count) && (stopTime==0 || nextPing<stopTime))
00114 scheduleAt(nextPing, timer);
00115 else
00116 delete timer;
00117 }
00118
00119 void PingApp::sendToICMP(cMessage *msg, const IPvXAddress& destAddr, const IPvXAddress& srcAddr, int hopLimit)
00120 {
00121 if (!destAddr.isIPv6())
00122 {
00123
00124 IPControlInfo *ctrl = new IPControlInfo();
00125 ctrl->setSrcAddr(srcAddr.get4());
00126 ctrl->setDestAddr(destAddr.get4());
00127 ctrl->setTimeToLive(hopLimit);
00128 msg->setControlInfo(ctrl);
00129 send(msg, "pingOut");
00130 }
00131 else
00132 {
00133
00134 IPv6ControlInfo *ctrl = new IPv6ControlInfo();
00135 ctrl->setSrcAddr(srcAddr.get6());
00136 ctrl->setDestAddr(destAddr.get6());
00137 ctrl->setHopLimit(hopLimit);
00138 msg->setControlInfo(ctrl);
00139 send(msg, "pingv6Out");
00140 }
00141 }
00142
00143 void PingApp::processPingResponse(PingPayload *msg)
00144 {
00145
00146 IPvXAddress src, dest;
00147 int msgHopCount = -1;
00148 if (dynamic_cast<IPControlInfo *>(msg->getControlInfo())!=NULL)
00149 {
00150 IPControlInfo *ctrl = (IPControlInfo *)msg->getControlInfo();
00151 src = ctrl->getSrcAddr();
00152 dest = ctrl->getDestAddr();
00153 msgHopCount = ctrl->getTimeToLive();
00154 }
00155 else if (dynamic_cast<IPv6ControlInfo *>(msg->getControlInfo())!=NULL)
00156 {
00157 IPv6ControlInfo *ctrl = (IPv6ControlInfo *)msg->getControlInfo();
00158 src = ctrl->getSrcAddr();
00159 dest = ctrl->getDestAddr();
00160 msgHopCount = ctrl->getHopLimit();
00161 }
00162
00163 simtime_t rtt = simTime() - msg->getCreationTime();
00164
00165 if (printPing)
00166 {
00167 cout << getFullPath() << ": reply of " << std::dec << msg->getByteLength()
00168 << " bytes from " << src
00169 << " icmp_seq=" << msg->getSeqNo() << " ttl=" << msgHopCount
00170 << " time=" << (rtt * 1000) << " msec"
00171 << " (" << msg->getName() << ")" << endl;
00172 }
00173
00174
00175 countPingResponse(msg->getByteLength(), msg->getSeqNo(), rtt);
00176 delete msg;
00177 }
00178
00179 void PingApp::countPingResponse(int bytes, long seqNo, simtime_t rtt)
00180 {
00181 EV << "Ping reply #" << seqNo << " arrived, rtt=" << rtt << "\n";
00182
00183 delayStat.collect(rtt);
00184 delayVector.record(rtt);
00185
00186 if (seqNo == expectedReplySeqNo)
00187 {
00188
00189 expectedReplySeqNo++;
00190 }
00191 else if (seqNo > expectedReplySeqNo)
00192 {
00193 EV << "Jump in seq numbers, assuming pings since #" << expectedReplySeqNo << " got lost\n";
00194
00195
00196 long jump = seqNo - expectedReplySeqNo;
00197 dropCount += jump;
00198 dropVector.record(dropCount);
00199
00200
00201 expectedReplySeqNo = seqNo+1;
00202 }
00203 else
00204 {
00205
00206 EV << "Arrived out of order (too late)\n";
00207 outOfOrderArrivalCount++;
00208 }
00209 }
00210
00211 void PingApp::finish()
00212 {
00213 if (sendSeqNo==0)
00214 {
00215 EV << getFullPath() << ": No pings sent, skipping recording statistics and printing results.\n";
00216 recordScalar("Pings sent", sendSeqNo);
00217 return;
00218 }
00219
00220
00221 recordScalar("Pings sent", sendSeqNo);
00222 recordScalar("Pings dropped", dropCount);
00223 recordScalar("Out-of-order ping arrivals", outOfOrderArrivalCount);
00224 recordScalar("Pings outstanding at end", sendSeqNo-expectedReplySeqNo);
00225
00226 recordScalar("Ping drop rate (%)", 100 * dropCount / (double)sendSeqNo);
00227 recordScalar("Ping out-of-order rate (%)", 100 * outOfOrderArrivalCount / (double)sendSeqNo);
00228
00229 delayStat.recordAs("Ping roundtrip delays");
00230
00231
00232 cout << "--------------------------------------------------------" << endl;
00233 cout << "\t" << getFullPath() << endl;
00234 cout << "--------------------------------------------------------" << endl;
00235
00236 cout << "sent: " << sendSeqNo
00237 << " drop rate (%): " << (100 * dropCount / (double)sendSeqNo) << endl;
00238 cout << "round-trip min/avg/max (ms): "
00239 << (delayStat.getMin()*1000.0) << "/"
00240 << (delayStat.getMean()*1000.0) << "/"
00241 << (delayStat.getMax()*1000.0) << endl;
00242 cout << "stddev (ms): "<< (delayStat.getStddev()*1000.0)
00243 << " variance:" << delayStat.getVariance() << endl;
00244 cout <<"--------------------------------------------------------" << endl;
00245 }
00246
00247