-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathrttEstimation_TCP.py
117 lines (99 loc) · 3.21 KB
/
rttEstimation_TCP.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#!/usr/bin/env python
import sys
from socket import inet_ntoa
from struct import unpack_from
from collections import defaultdict
def rttEstimation(filename=None,binary=False):
seq = {}
if binary:
if filename!=None:
fIn = open(filename,"rb")
else:
fIn = sys.stdin
# Skip the header
txt = fIn.readline()
while not txt.startswith("!binary"):
txt = fIn.readline()
#First Record length
nextRec = fIn.read(4)
else:
if filename!=None:
fIn = open(filename,"r")
else:
fIn = sys.stdin
# Skip the header
txt = fIn.readline()
while not txt.startswith("!data"):
txt = fIn.readline()
txt = fIn.readline()
#Read the trace
while (binary and nextRec != "" and len(nextRec) == 4) or (not binary and txt):
try:
#For each packet get the timestamps, IP addresses, and TCP header fields
if binary:
# Get IPs, ports, size and protocol
recLen = unpack_from("!i",nextRec)[0]
ts = unpack_from('!II',fIn.read(8))
#tsu = unpack('!I',fIn.read(4))[0]
ipSrc = inet_ntoa(fIn.read(4))
portSrc = unpack_from('!H',fIn.read(2))[0]
ipDst = inet_ntoa(fIn.read(4))
portDst = unpack_from('!H',fIn.read(2))[0]
tcpFlags= unpack_from("!b",fIn.read(1))[0]
tcpSeq = unpack_from("!I",fIn.read(4))[0]
tcpAck = unpack_from("!I",fIn.read(4))[0]
payload = unpack_from("!I",fIn.read(4))[0]
ethDst = unpack_from('!BBBBBB',fIn.read(6)) # old versions of IPsumdump are doing wrong things here...
else:
word = txt.split()
tsStr = word[0].split(".")
ts = [int(tsStr[0]),int(tsStr[1])]
ipSrc = word[1]
portSrc = word[2]
ipDst = word[3]
portDst = word[4]
tcpFlags = 0
if "A" in word[5]:
tcpFlags = tcpFlags | 16
if "S" in word[5]:
tcpFlags = tcpFlags | 2
tcpSeq = int(word[6])
tcpAck = int(word[7])
payload= int(word[8])
ethDst = word[9]
except ValueError:
#sys.stderr.write("WARN: ignored packet,"+txt+"\n")
if binary:
#next record length
nextRec = fIn.read(4)
else:
txt =fIn.readline()
continue
if binary:
#next record length
nextRec = fIn.read(4)
else:
txt =fIn.readline()
if tcpFlags & 2: # Syn flag consume 1 byte
tcpSeq += 1
else:
tcpSeq += payload
# Hash keys to identify flows
src = "{0}:{1}".format(ipSrc,portSrc)
dst = "{0}:{1}".format(ipDst,portDst)
if not src in seq:
seq[src]={dst:{tcpSeq:ts}}
elif not dst in seq[src]:
seq[src][dst]={tcpSeq:ts}
elif not tcpSeq in seq[src][dst]:
seq[src][dst][tcpSeq] = ts
else: # Retransmission
seq[src][dst][tcpSeq] = None # Reset the timer
if tcpFlags & 16: # ACK packet
if dst in seq and src in seq[dst] and tcpAck in seq[dst][src]:
ts0 = seq[dst][src][tcpAck]
if ts0 != None:
print("{0},{1},{2:f},{3}".format(ipSrc,ipDst,ts[0]-ts0[0]+(ts[1]-ts0[1])*1e-6,ethDst) )
seq[dst][src][tcpAck] = None
if __name__ == "__main__":
rttEstimation()