-
Notifications
You must be signed in to change notification settings - Fork 0
/
plot_tcp.py
87 lines (79 loc) · 3.78 KB
/
plot_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
import matplotlib.pyplot as plt
from scapy.all import rdpcap, TCP
def calculate_rtt(packets):
# Dictionary to store the timestamps of sent packets for each TCP connection
sent_packets = {}
# List to store the RTT values
rtt_values = []
# First loop - index by IPs & Ports, store timestamps and byte range (seq & seq+payload length)
for packet in packets:
if TCP in packet:
tcp_layer = packet[TCP]
ip_layer = packet.getlayer(1)
src_ip = ip_layer.src
dst_ip = ip_layer.dst
src_port = tcp_layer.sport
dst_port = tcp_layer.dport
seq = tcp_layer.seq
segment_index = (src_ip, dst_ip, src_port, dst_port)
# python sorts based on the first element of each inner list.
# If there is a tie (i.e., the first elements are the same), it will then consider the second element, and so on.
# if len(tcp_layer.payload) > 0: ????
segment_data = [seq, seq + len(tcp_layer.payload), float(packet.time)]
if not segment_index in sent_packets:
sent_packets[segment_index] = [segment_data]
else:
sent_packets[segment_index].append(segment_data)
# Sort all the segment_datas by sequence number and byte range
for connection in sent_packets:
print("connection", connection)
# print(sent_packets[connection])
sent_packets[connection].sort()
print(sent_packets[connection])
# Second loop - match acks with sequence numbers
for packet in packets:
if TCP in packet:
tcp_layer = packet[TCP]
ip_layer = packet.getlayer(1)
src_ip = ip_layer.src
dst_ip = ip_layer.dst
src_port = tcp_layer.sport
dst_port = tcp_layer.dport
seq = tcp_layer.seq
ack = tcp_layer.ack
flags = tcp_layer.flags
segment_index = (dst_ip, src_ip, dst_port, src_port)
if 'A' in flags and segment_index in sent_packets:
acknowledged_sent_segments = []
# Look for all the segments acknowledged in the sent_packets dictionary
for seq, acked_byte, packet_timestamp in sent_packets[segment_index]:
acknowledged_sent_segments.append([seq, acked_byte, packet_timestamp])
if acked_byte == ack -1:
amount_acked_segments = len(acknowledged_sent_segments)
rtt = packet.time - acknowledged_sent_segments[0][2] # packet_timestamp of the first acked segment (since it's sorted by seq no)
rtt_values.append([amount_acked_segments, rtt])
print("found ack! -- ", amount_acked_segments, " acked segments | rtt: ", rtt)
# Delete all the acknowledged_sent_segments from sent_packets[segment_index] so it's ready for the next loop
for acked_segments in acknowledged_sent_segments:
sent_packets[segment_index].remove(acked_segments)
break
return rtt_values
def plot_tcp_segments_vs_rtt(pcap_file):
packets = rdpcap(pcap_file)
rtt_values = calculate_rtt(packets)
#num_segments = list(range(1, len(rtt_values) + 1))
values = []
rtts = []
for amount_acked_segments, rtt in rtt_values:
values.append(amount_acked_segments)
rtts.append(rtt)
plt.figure(figsize=(10, 6))
plt.plot(rtts, values, 'bo-', markersize=5)
plt.xlabel('RTT (s)')
plt.ylabel('Number of TCP Segments')
plt.title('Number of TCP Segments vs. RTT')
plt.grid(True)
plt.show()
# Example usage
pcap_file = 'http_with_jpeg-1-request.cap' # Replace with your pcap file path
plot_tcp_segments_vs_rtt(pcap_file)