#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 |
void PingApp::initialize | ( | ) | [protected, virtual] |
00034 { 00035 // read params 00036 // (defer reading srcAddr/destAddr to when ping starts, maybe 00037 // addresses will be assigned later by some protocol) 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 // state 00047 sendSeqNo = expectedReplySeqNo = 0; 00048 WATCH(sendSeqNo); 00049 WATCH(expectedReplySeqNo); 00050 00051 // statistics 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 // schedule first ping (use empty destAddr or stopTime<=startTime to disable) 00061 if (par("destAddr").stringValue()[0] && (stopTime==0 || stopTime>=startTime)) 00062 { 00063 cMessage *msg = new cMessage("sendPing"); 00064 scheduleAt(startTime, msg); 00065 } 00066 }
void PingApp::handleMessage | ( | cMessage * | msg | ) | [protected, virtual] |
00069 { 00070 if (msg->isSelfMessage()) 00071 { 00072 // on first call we need to initialize 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 // send a ping 00082 sendPing(); 00083 00084 // then schedule next one if needed 00085 scheduleNextPing(msg); 00086 } 00087 else 00088 { 00089 // process ping response 00090 processPingResponse(check_and_cast<PingPayload *>(msg)); 00091 } 00092 }
void PingApp::finish | ( | ) | [protected, virtual] |
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 // record statistics 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 // print it to stdout as well 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 }
void PingApp::sendPing | ( | ) | [protected, virtual] |
Referenced by handleMessage().
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 }
void PingApp::scheduleNextPing | ( | cMessage * | timer | ) | [protected, virtual] |
void PingApp::sendToICMP | ( | cMessage * | payload, | |
const IPvXAddress & | destAddr, | |||
const IPvXAddress & | srcAddr, | |||
int | hopLimit | |||
) | [protected, virtual] |
Referenced by sendPing().
00120 { 00121 if (!destAddr.isIPv6()) 00122 { 00123 // send to IPv4 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 // send to IPv6 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 }
void PingApp::processPingResponse | ( | PingPayload * | msg | ) | [protected, virtual] |
Referenced by handleMessage().
00144 { 00145 // get src, hopCount etc from packet, and print them 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 // update statistics 00175 countPingResponse(msg->getByteLength(), msg->getSeqNo(), rtt); 00176 delete msg; 00177 }
void PingApp::countPingResponse | ( | int | bytes, | |
long | seqNo, | |||
simtime_t | rtt | |||
) | [protected, virtual] |
Referenced by processPingResponse().
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 // expected ping reply arrived; expect next sequence number 00189 expectedReplySeqNo++; 00190 } 00191 else if (seqNo > expectedReplySeqNo) 00192 { 00193 EV << "Jump in seq numbers, assuming pings since #" << expectedReplySeqNo << " got lost\n"; 00194 00195 // jump in the sequence: count pings in gap as lost 00196 long jump = seqNo - expectedReplySeqNo; 00197 dropCount += jump; 00198 dropVector.record(dropCount); 00199 00200 // expect sequence numbers to continue from here 00201 expectedReplySeqNo = seqNo+1; 00202 } 00203 else // seqNo < expectedReplySeqNo 00204 { 00205 // ping arrived too late: count as out of order arrival 00206 EV << "Arrived out of order (too late)\n"; 00207 outOfOrderArrivalCount++; 00208 } 00209 }
IPvXAddress PingApp::destAddr [protected] |
Referenced by handleMessage(), and sendPing().
IPvXAddress PingApp::srcAddr [protected] |
Referenced by handleMessage(), and sendPing().
int PingApp::packetSize [protected] |
Referenced by initialize(), and sendPing().
cPar* PingApp::intervalp [protected] |
Referenced by initialize(), and scheduleNextPing().
int PingApp::hopLimit [protected] |
Referenced by initialize(), and sendPing().
int PingApp::count [protected] |
Referenced by initialize(), and scheduleNextPing().
simtime_t PingApp::startTime [protected] |
Referenced by initialize().
simtime_t PingApp::stopTime [protected] |
Referenced by initialize(), and scheduleNextPing().
bool PingApp::printPing [protected] |
Referenced by initialize(), and processPingResponse().
long PingApp::sendSeqNo [protected] |
Referenced by finish(), initialize(), scheduleNextPing(), and sendPing().
long PingApp::expectedReplySeqNo [protected] |
Referenced by countPingResponse(), finish(), and initialize().
cStdDev PingApp::delayStat [protected] |
Referenced by countPingResponse(), finish(), and initialize().
cOutVector PingApp::delayVector [protected] |
Referenced by countPingResponse(), and initialize().
cOutVector PingApp::dropVector [protected] |
Referenced by countPingResponse(), and initialize().
long PingApp::dropCount [protected] |
Referenced by countPingResponse(), finish(), and initialize().
long PingApp::outOfOrderArrivalCount [protected] |
Referenced by countPingResponse(), finish(), and initialize().