diff --git a/sc_stats.py b/sc_stats.py index 1e9fb82..8a5360b 100755 --- a/sc_stats.py +++ b/sc_stats.py @@ -7,7 +7,17 @@ # import sys import time -from sc_warts import WartsReader +from math import sqrt +from sc_warts import WartsReader, obj_type + +def basic(vals): + n = len(vals)/1.0 + mean = sum(vals)/n + ss = sum((x-mean)**2 for x in vals) + stddev = 0.0 + if n > 1: + stddev = sqrt(ss/n) + return (min(vals), mean, max(vals), stddev) class WartsStats(WartsReader): def __init__(self, wartsfile, verbose=False): @@ -35,14 +45,11 @@ class WartsStats(WartsReader): def elapsed(self): return self.ts_end - self.ts_begin - """ Takes a list of warts hops from a WartsReader. Returns sequential IP path list, along with a dictionary of RTTs and meta data (indexed by TTL) """ - def next_trace(self): - (flags, hops) = self.next() - if flags == False: - return (None, None, None, None) + def do_trace(self, obj): + (flags, hops) = (obj.flags, obj.hops) ts = flags['timeval'] if ts > self.ts_end: self.ts_end = ts @@ -74,6 +81,21 @@ class WartsStats(WartsReader): self.dict_append(meta, i, "!N") return (flags, ips, rtts, meta) + def do_ping(self, obj): + (flags, responses) = (obj.flags, obj.hops) + return (flags, responses) + + def next(self): + obj = None + while True: + obj = self.next_object() + if not obj: + return (None, None) + elif obj.typ == obj_type['PING']: + return (obj.typ, self.do_ping(obj)) + elif obj.typ == obj_type['TRACE']: + return (obj.typ, self.do_trace(obj)) + @staticmethod def addhop(lasthop, hop, interfaces, edges, ignore_anon=True): interfaces.add(hop) @@ -94,7 +116,12 @@ class WartsStats(WartsReader): edges = set() # Edges cnt = 0 while True: - (flags, ips, rtts, meta) = self.next_trace() + (typ, data) = self.next() + if typ == None: + break + if typ != obj_type['TRACE']: + continue + (flags, ips, rtts, meta) = data if flags == None: break cnt+=1 dests.add(flags['dstaddr']) diff --git a/sc_warts2text.py b/sc_warts2text.py index 720993f..4a45753 100755 --- a/sc_warts2text.py +++ b/sc_warts2text.py @@ -5,7 +5,38 @@ # Description: Replicate output of scamper's sc_warts2text import sys -from sc_stats import WartsStats +from sc_stats import WartsStats, basic, obj_type + +def print_trace(flags, ips, rtts, meta): + print "traceroute from %s to %s" % (flags['srcaddr'], flags['dstaddr']) + for i, ip in enumerate(ips): + ttl = i+1 + print "%2d %s" % (ttl, ip), + if ttl in rtts: + print " %2.3f ms" % (rtts[ttl]), + if ttl in meta: + for v in meta[ttl]: + print "%s" % (v), + print + +def print_ping(flags, responses): + rtts = [] + print "ping %s to %s: %d byte packets" % (flags['srcaddr'], flags['dstaddr'], flags['size']) + rcount = set() + for response in responses: + rcount.add(response['probeid']) + rtt = response['rtt']/1000.0 + rtts.append(rtt) + print "%d bytes from %s, seq=%d ttl=%d time=%3.3f ms" % \ + (response['replysize'], response['addr'], response['probeid'], + response['replyttl'], rtt) + print "--- %s ping statistics ---" % flags['dstaddr'] + loss = 100.0 - (len(rcount) * 100.0 / flags['psent']) + print "%d packets transmitted, %d packets received, %d%% packet loss" % \ + (flags['psent'], len(rcount), loss) + if len(rcount) > 0: + print "round-trip min/avg/max/stddev = %2.3f/%2.3f/%2.3f/%2.3f ms" % \ + basic(rtts) if __name__ == "__main__": assert len(sys.argv) >= 2 @@ -15,19 +46,17 @@ if __name__ == "__main__": w = WartsStats(sys.argv[1], verbose=False) while True: try: - (flags, ips, rtts, meta) = w.next_trace() - if flags == None: break - if target and target != flags['dstaddr']: continue - print "traceroute from %s to %s" % (flags['srcaddr'], flags['dstaddr']) - for i, ip in enumerate(ips): - ttl = i+1 - print "%2d %s" % (ttl, ip), - if ttl in rtts: - print " %2.3f ms" % (rtts[ttl]), - if ttl in meta: - for v in meta[ttl]: - print "%s" % (v), - print + (typ, data) = w.next() + if typ == None: + break + elif typ == obj_type['TRACE']: + (flags, ips, rtts, meta) = data + if target and target != flags['dstaddr']: continue + print_trace(flags, ips, rtts, meta) + elif typ == obj_type['PING']: + (flags, responses) = data + if target and target != flags['dstaddr']: continue + print_ping(flags, responses) except Exception, e: print "Flags:", flags print "** Error:", e