#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 }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|