Add proper per-file copyright notices/licenses and top-level license.
[bluesky.git] / parsetrace / analyze-tcp.py
index b83fb82..fb58b6a 100755 (executable)
@@ -8,7 +8,7 @@ import impacket, json, pcapy, re, sys
 import impacket.ImpactDecoder, impacket.ImpactPacket
 
 # Estimate of the network RTT
-RTT_EST = 0.03
+RTT_EST = 0.03 * 1e6
 
 def dump_data(obj):
     return json.dumps(result_list, sort_keys=True, indent=2)
@@ -65,7 +65,7 @@ class TcpAnalysis:
         if self.start_time is None:
             self.start_time = ts
         ts -= self.start_time
-        pkt = Packet(self, ts * 1e-6, self.decoder.decode(data))
+        pkt = Packet(self, ts, self.decoder.decode(data))
         self.packets.append(pkt)
 
 def split_trace(packets, predicate, before=True):
@@ -91,7 +91,7 @@ def split_trace(packets, predicate, before=True):
     if len(segment) > 0:
         yield segment
 
-def analyze_get(packets):
+def analyze_get(packets, prev_time = None):
     packets = iter(packets)
     p = packets.next()
 
@@ -104,7 +104,7 @@ def analyze_get(packets):
         addr = p.ip.get_ip_dst()
         p = packets.next()
         #print "Connection establishment: RTT is", p.ts - start_ts
-        return {'syn_rtt': p.ts - start_ts, 'addr': addr}
+        return {'syn_rtt': (p.ts - start_ts) / 1e6, 'addr': addr}
 
     # Otherwise, we expect the first packet to be the GET request itself
     if not(p.direction > 0 and p.data.startswith('GET')):
@@ -126,49 +126,51 @@ def analyze_get(packets):
     # Scan through the incoming packets, looking for gaps in either the IP ID
     # field or in the timing
     last_ts = resp_ts
+    last_was_short = False
     for p in packets:
         gap = False
+        flags = []
         bytenr = (p.seq[1] - start_seq) & 0xffffffff
         if not p.direction < 0: continue
         if p.tcp.get_FIN(): continue
-        spacings.append((p.ts - last_ts, bytenr))
+
+        if last_was_short:
+            flags.append('LAST_PACKET_SHORT')
+        last_was_short = False
         if p.id != (id_in + 1) & 0xffff:
             gap = True
-            #print "Sequence number gap at", id_in
-        if p.ts - last_ts > 2 * RTT_EST:
-            gap = True
-            #print "Long gap of", p.ts - last_ts
-        elif p.ts - last_ts > RTT_EST / 2:
-            gap = True
-            #print "Short gap of", p.ts - last_ts
-        if gap:
-            #print "    [occurred after", p.seq[0] - start_seq, "bytes, time", p.ts, "sec]"
-            pass
+            flags.append('IPID_GAP')
         if p.datalen not in (1448, 1460):
-            #print "Short packet of", p.datalen, "bytes, brings total to", p.seq[1] - start_seq
-            pass
+            last_was_short = True
         if (p.seq[0] - start_seq) & 0xffffffff != tot_bytes:
-            #print "Packet out of order; got sequence number %d, expected %d" \
-            #        % ((p.seq[0] - start_seq) & 0xffffffff, tot_bytes)
-            pass
+            flags.append('OUT_OF_ORDER')
+        if ((p.seq[0] - start_seq) & 0xffffffff) % 9000 == 0:
+            flags.append('9000')
+        spacings.append(((p.ts - last_ts) / 1e6, bytenr) + tuple(flags))
         last_ts = p.ts
         id_in = p.id
         tot_bytes = max(tot_bytes, bytenr)
 
     #print "Transferred %d bytes in %s seconds, initial response after %s" % (tot_bytes, last_ts - start_ts, resp_ts - start_ts)
+    if prev_time is not None:
+        prev_delay = start_ts - prev_time
+    else:
+        prev_delay = 0
     return {'bytes': tot_bytes,
             'start_latency': resp_ts - start_ts,
             'finish_latency': last_ts - start_ts,
-            'interpacket_times': spacings}
+            'interpacket_times': spacings,
+            'delay_from_previous': prev_delay}
 
 if __name__ == '__main__':
     for f in sys.argv[1:]:
         conn = TcpAnalysis()
         conn.process_file(f)
-        ts = 0.0
+        ts = 0
         def request_start(p):
             return p.direction > 0 and p.datalen > 0
         result_list = []
+        prev_time = None
         for s in split_trace(conn.packets, request_start):
             s = list(s)
             if False:
@@ -181,9 +183,10 @@ if __name__ == '__main__':
                     #print p
                     #if p.direction > 0 and p.datalen > 0:
                         #print "Request:", repr(p.data)
-            results = analyze_get(s)
+            results = analyze_get(s, prev_time)
             if results is not None:
                 result_list.append(results)
+            prev_time = s[-1].ts
             #print "===="
 
         print dump_data(result_list)