http://www.mediawiki.org/wiki/Special:Code/MediaWiki/72473
Revision: 72473
Author: tstarling
Date: 2010-09-06 09:26:14 +0000 (Mon, 06 Sep 2010)
Log Message:
-----------
Packet loss counter, based loosely on the existing delta.cpp. The idea is that
it can be used as a pipe processor, sending output to some file, to give packet
loss statistics every 10 minutes.
Modified Paths:
--------------
trunk/udplog/Makefile
Added Paths:
-----------
trunk/udplog/srcmisc/packet-loss.cpp
Modified: trunk/udplog/Makefile
===================================================================
--- trunk/udplog/Makefile 2010-09-06 09:08:45 UTC (rev 72472)
+++ trunk/udplog/Makefile 2010-09-06 09:26:14 UTC (rev 72473)
@@ -1,4 +1,4 @@
-TARGETS = log2udp udprecv delta udp2log/udp2log
+TARGETS = log2udp udprecv delta udp2log/udp2log packet-loss
HOST_OBJS = srcmisc/host.o srclib/HostEntry.o srclib/IPAddress.o
LOG2UDP_OBJS = srcmisc/log2udp.o srclib/HostEntry.o srclib/IPAddress.o
srclib/Socket.o srclib/SocketAddress.o
UDPRECV_OBJS = srcmisc/udprecv.o srclib/IPAddress.o srclib/Socket.o
srclib/SocketAddress.o
@@ -25,6 +25,9 @@
delta: srcmisc/delta.cpp
g++ $(CFLAGS) -o delta srcmisc/delta.cpp
+packet-loss: srcmisc/packet-loss.cpp
+ g++ $(CFLAGS) -o packet-loss srcmisc/packet-loss.cpp
+
udp2log/udp2log: $(UDP2LOG_OBJS)
g++ $(CFLAGS) -o udp2log/udp2log -lboost_program_options
$(UDP2LOG_OBJS)
Copied: trunk/udplog/srcmisc/packet-loss.cpp (from rev 72465,
trunk/udplog/srcmisc/delta.cpp)
===================================================================
--- trunk/udplog/srcmisc/packet-loss.cpp (rev 0)
+++ trunk/udplog/srcmisc/packet-loss.cpp 2010-09-06 09:26:14 UTC (rev
72473)
@@ -0,0 +1,213 @@
+#include <iostream>
+#include <map>
+#include <stdint.h>
+#include <boost/lexical_cast.hpp>
+#include <cstring>
+#include <time.h>
+#include <stdlib.h>
+#include <math.h>
+
+using std::strtok;
+
+typedef std::map<std::string, uint64_t>::iterator SeqIterator;
+
+struct HostData {
+ HostData() : received(1), sent(0) {}
+
+ // Number of packets received (sampled)
+ int64_t received;
+
+ // Number of packets sent, estimated from sequence numbers (unsampled)
+ int64_t sent;
+};
+typedef std::map<std::string, HostData>::iterator HostIterator;
+
+struct SampleData {
+ SampleData() : total(0), outOfOrder(0), invalid(0) {}
+
+ // Number of sampled lines received
+ int64_t total;
+
+ // Number of sampled lines out of order
+ int64_t outOfOrder;
+
+ // Number of sampled lines which were invalid
+ int64_t invalid;
+
+ std::map<std::string, HostData> hosts;
+
+ void Report(const struct tm * timeStruct, int sampleRate);
+ void PrintRatio(int64_t numerator, int64_t denominator, double
numeratorError);
+
+};
+
+const time_t reportInterval = 600;
+
+
+int main(int argc, char** argv)
+{
+ using namespace std;
+ const size_t bufSize = 65536;
+ map<string, uint64_t> seqs;
+ char buffer[bufSize];
+ int sampleRate;
+
+ SampleData initialData;
+ SampleData currentData;
+ time_t lastReportTime = 0;
+ time_t currentTime;
+ struct tm timeStruct;
+
+ if (argc < 2) {
+ cerr << "usage: packet-loss <sample-rate>\n";
+ exit(1);
+ }
+
+ try {
+ sampleRate = boost::lexical_cast<int>(argv[1]);
+ } catch (...) {
+ cerr << "packet-loss: invalid sample rate\n";
+ exit(1);
+ }
+ if (sampleRate < 1) {
+ cerr << "packet-loss: invalid sample rate\n";
+ exit(1);
+ }
+
+ while (cin.good()) {
+ cin.getline(buffer, bufSize);
+ if (!cin.gcount()) {
+ continue;
+ }
+ currentData.total++;
+ if (cin.gcount() > (streamsize)(bufSize - 2)) {
+ // Oversize
+ currentData.invalid++;
+ continue;
+ }
+ char * strConn = strtok(buffer, " ");
+ char * strSeq = strtok(NULL, " ");
+ char * strTime = strtok(NULL, " ");
+ char * restOfLine = strtok(NULL, "\n");
+ if (!strConn || !strSeq || !strTime || !restOfLine) {
+ // Invalid line
+ currentData.invalid++;
+ continue;
+ }
+ uint64_t seq;
+ try {
+ seq = boost::lexical_cast<uint64_t>(strSeq);
+ } catch (...) {
+ // Non-numeric sequence number
+ currentData.invalid++;
+ continue;
+ }
+
+ if (!strptime(strTime, "%Y-%m-%dT%H:%M:%S", &timeStruct)) {
+ // Invalid date/time
+ currentData.invalid++;
+ continue;
+ }
+ currentTime = mktime(&timeStruct);
+
+ SeqIterator seqIter = seqs.find(strConn);
+ HostIterator hostIter = currentData.hosts.find(strConn);
+ if (hostIter == currentData.hosts.end()) {
+ // First instance of this host since the last report,
or first instance overall
+ initialData.hosts[strConn] = HostData();
+ currentData.hosts[strConn] = HostData();
+ if (seqIter != seqs.end()) {
+ std::cerr << "packet-loss: unexpected host
entry\n";
+ abort();
+ }
+ seqs[strConn] = seq;
+ } else {
+ if (seqIter == seqs.end()) {
+ std::cerr << "packet-loss: unexpected lack of
host entry\n";
+ abort();
+ } else if (seqIter->second == (uint64_t)-1) {
+ // First instance of this host since
out-of-order data
+ seqs[strConn] = seq;
+ } else if (seqIter->second > seq) {
+ // Out-of-order, suspend counting until we
resync
+ currentData.outOfOrder++;
+ seqIter->second = (uint64_t)-1;
+ } else {
+ // Normal case: sequence number increased
+ int64_t delta = (int64_t)(seq -
seqIter->second);
+ hostIter->second.sent += delta;
+ hostIter->second.received ++;
+ seqIter->second = seq;
+ }
+ }
+
+ if (currentTime - lastReportTime >= reportInterval) {
+ lastReportTime = currentTime;
+ currentData.Report(&timeStruct, sampleRate);
+ currentData = initialData;
+ }
+ }
+ // Final report
+ currentTime = time(NULL);
+ currentData.Report(&timeStruct, sampleRate);
+}
+
+void SampleData::Report(const struct tm * timeStruct, int sampleRate) {
+ using namespace std;
+ char timebuf[256];
+
+ strftime(timebuf, sizeof(timebuf), "[%Y-%m-%dT%H:%M:%S] ", timeStruct);
+
+ cout << timebuf << "invalid: ";
+ PrintRatio(invalid, total, sqrt(total));
+ cout << "\n";
+
+ cout << timebuf << "out of order: ";
+ PrintRatio(outOfOrder, total, sqrt(total));
+ cout << "\n";
+
+ HostIterator iter;
+ int64_t totalSent = 0, totalReceived = 0;
+ for (iter = hosts.begin(); iter != hosts.end(); iter++) {
+ if (iter->second.received < 10) {
+ // Sample size too small
+ continue;
+ }
+ cout << timebuf << iter->first << " lost: ";
+ PrintRatio(
+ iter->second.sent - iter->second.received * sampleRate,
+ iter->second.sent,
+ sqrt(iter->second.received) * sampleRate
+ );
+ cout << "\n";
+ totalSent += iter->second.sent;
+ totalReceived += iter->second.received;
+ }
+
+ cout << timebuf << "total lost: ";
+ PrintRatio(
+ totalSent - totalReceived * sampleRate,
+ totalSent,
+ sqrt(totalReceived) * sampleRate
+ );
+ cout << "\n";
+}
+
+void SampleData::PrintRatio(int64_t numerator, int64_t denominator, double
numeratorError) {
+ using namespace std;
+ if (denominator == 0) {
+ cout << "(0 +/- 0)%";
+ } else {
+ double percent = (double)numerator / denominator * 100;
+ double percentError = numeratorError / denominator * 100;
+ cout.precision(5);
+ cout.flags(ios::fixed);
+ cout << "(" << percent << " +/- ";
+ cout.precision(5);
+ cout.flags(ios::fixed);
+ cout << percentError << ")%";
+ }
+}
+
+// vim: ts=4 sw=4:
+
_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs